mirror of
https://github.com/RPCS3/discord-bot.git
synced 2025-01-09 12:22:26 +00:00
commit
750baff306
@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks;
|
||||
using CompatBot.Utils;
|
||||
using DSharpPlus;
|
||||
using DSharpPlus.CommandsNext;
|
||||
using DSharpPlus.CommandsNext.Attributes;
|
||||
using DSharpPlus.Entities;
|
||||
@ -24,7 +22,7 @@ namespace CompatBot.Commands.Attributes
|
||||
public override async Task<bool> ExecuteCheckAsync(CommandContext ctx, bool help)
|
||||
{
|
||||
var result = await IsAllowed(ctx, help);
|
||||
Config.Log.Debug($"Check for {GetType().Name} resulted in {result}");
|
||||
Config.Log.Debug($"Check for {GetType().Name} and user {ctx.User.Username}#{ctx.User.Discriminator} ({ctx.User.Id}) resulted in {result}");
|
||||
if (result)
|
||||
{
|
||||
if (ReactOnSuccess != null && !help)
|
||||
|
@ -304,15 +304,13 @@ namespace CompatBot.Commands
|
||||
}
|
||||
else if (txt != null)
|
||||
{
|
||||
var newStartTime = FixTimeString(txt.Content);
|
||||
if (!DateTime.TryParse(newStartTime, out var newTime))
|
||||
if (!TimeParser.TryParse(txt.Content, out var newTime))
|
||||
{
|
||||
errorMsg = $"Couldn't parse `{newStartTime}` as a start date and time";
|
||||
errorMsg = $"Couldn't parse `{txt.Content}` as a start date and time";
|
||||
goto step1;
|
||||
}
|
||||
|
||||
var duration = evt.End - evt.Start;
|
||||
newTime = Normalize(newTime);
|
||||
evt.Start = newTime.Ticks;
|
||||
evt.End = evt.Start + duration;
|
||||
evt.Year = newTime.Year;
|
||||
@ -487,25 +485,6 @@ namespace CompatBot.Commands
|
||||
return score > 0.5 ? name : eventName;
|
||||
}
|
||||
|
||||
private static string FixTimeString(string dateTime)
|
||||
{
|
||||
return dateTime.ToUpperInvariant()
|
||||
.Replace("PST", "-08:00")
|
||||
.Replace("EST", "-05:00")
|
||||
.Replace("BST", "-03:00")
|
||||
.Replace("JST", "+09:00")
|
||||
.Replace("AEST", "+10:00");
|
||||
}
|
||||
|
||||
private static DateTime Normalize(DateTime date)
|
||||
{
|
||||
if (date.Kind == DateTimeKind.Utc)
|
||||
return date;
|
||||
if (date.Kind == DateTimeKind.Local)
|
||||
return date.ToUniversalTime();
|
||||
return date.AsUtc();
|
||||
}
|
||||
|
||||
private static async Task<TimeSpan?> TryParseTimeSpanAsync(CommandContext ctx, string duration, bool react = true)
|
||||
{
|
||||
var d = Duration.Match(duration);
|
||||
|
@ -87,7 +87,7 @@ namespace CompatBot.Commands
|
||||
}
|
||||
|
||||
await ctx.Client.ReportAsync("👀 Message report", msg, new[] {ctx.Message.Author}, comment, ReportSeverity.Medium).ConfigureAwait(false);
|
||||
await msg.ReactWithAsync(ctx.Client, Config.Reactions.Moderated).ConfigureAwait(false);
|
||||
await msg.ReactWithAsync(Config.Reactions.Moderated).ConfigureAwait(false);
|
||||
await ctx.ReactWithAsync(Config.Reactions.Success, "Message reported").ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ namespace CompatBot.Commands
|
||||
var prInfo = await githubClient.GetPrInfoAsync(pr, Config.Cts.Token).ConfigureAwait(false);
|
||||
if (prInfo.Number == 0)
|
||||
{
|
||||
await message.ReactWithAsync(client, Config.Reactions.Failure, prInfo.Message ?? "PR not found").ConfigureAwait(false);
|
||||
await message.ReactWithAsync(Config.Reactions.Failure, prInfo.Message ?? "PR not found").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ namespace CompatBot.Commands
|
||||
embed.ThumbnailUrl = "https://cdn.discordapp.com/attachments/417347469521715210/516340151589535745/onionoff.png";
|
||||
}
|
||||
var sqvat = ctx.Client.GetEmoji(":sqvat:", Config.Reactions.No);
|
||||
await ctx.Message.ReactWithAsync(ctx.Client, sqvat).ConfigureAwait(false);
|
||||
await ctx.Message.ReactWithAsync(sqvat).ConfigureAwait(false);
|
||||
}
|
||||
if (embeds.Count > 1 || embeds[0].Fields?.Count > 0)
|
||||
embeds[embeds.Count - 1] = embeds.Last().WithFooter("Note that you need to install all listed updates one by one");
|
||||
|
@ -88,7 +88,7 @@ namespace CompatBot.Commands
|
||||
else
|
||||
de = DiscordEmoji.FromUnicode(emoji + c);
|
||||
emoji = "";
|
||||
await message.ReactWithAsync(ctx.Client, de).ConfigureAwait(false);
|
||||
await message.ReactWithAsync(de).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch
|
||||
|
@ -28,7 +28,7 @@ namespace CompatBot.EventHandlers
|
||||
if (matches.Count == 0)
|
||||
return;
|
||||
|
||||
await args.Message.ReactWithAsync(args.Client, Config.Reactions.PleaseWait).ConfigureAwait(false);
|
||||
await args.Message.ReactWithAsync(Config.Reactions.PleaseWait).ConfigureAwait(false);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -131,7 +131,7 @@ namespace CompatBot.EventHandlers
|
||||
emoji = ThankYouReactions[rng.Next(ThankYouReactions.Length)];
|
||||
thankYouMessage = LimitedToSpamChannel.IsSpamChannel(args.Channel) ? ThankYouMessages[rng.Next(ThankYouMessages.Length)] : null;
|
||||
}
|
||||
await args.Message.ReactWithAsync(args.Client, emoji, thankYouMessage).ConfigureAwait(false);
|
||||
await args.Message.ReactWithAsync(emoji, thankYouMessage).ConfigureAwait(false);
|
||||
}
|
||||
if (needToSilence)
|
||||
{
|
||||
@ -142,7 +142,7 @@ namespace CompatBot.EventHandlers
|
||||
emoji = SadReactions[rng.Next(SadReactions.Length)];
|
||||
sadMessage = SadMessages[rng.Next(SadMessages.Length)];
|
||||
}
|
||||
await args.Message.ReactWithAsync(args.Client, emoji, sadMessage).ConfigureAwait(false);
|
||||
await args.Message.ReactWithAsync(emoji, sadMessage).ConfigureAwait(false);
|
||||
|
||||
if (args.Author.IsSmartlisted(args.Client, args.Message.Channel.Guild))
|
||||
{
|
||||
@ -154,7 +154,7 @@ namespace CompatBot.EventHandlers
|
||||
await msg.DeleteAsync("asked to shut up").ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
await args.Message.ReactWithAsync(args.Client, DiscordEmoji.FromUnicode("🙅"), @"No can do, boss ¯\\_(ツ)\_/¯").ConfigureAwait(false);
|
||||
await args.Message.ReactWithAsync(DiscordEmoji.FromUnicode("🙅"), @"No can do, boss ¯\\_(ツ)\_/¯").ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -111,9 +111,7 @@ namespace CompatBot.EventHandlers
|
||||
{
|
||||
Config.Log.Warn(e);
|
||||
await client.ReportAsync("🛃 An unapproved discord invite", message, "In invalid or expired invite", null, ReportSeverity.Medium).ConfigureAwait(false);
|
||||
await message.ReactWithAsync(
|
||||
client,
|
||||
Config.Reactions.Moderated,
|
||||
await message.ReactWithAsync(Config.Reactions.Moderated,
|
||||
$"{message.Author.Mention} please remove this expired or invalid invite, and refrain from posting it again until you have received an approval from a moderator.",
|
||||
true
|
||||
).ConfigureAwait(false);
|
||||
|
@ -59,7 +59,7 @@ namespace CompatBot.EventHandlers
|
||||
|
||||
public static async Task LookupAndPostProductCodeEmbedAsync(DiscordClient client, DiscordMessage message, List<string> codesToLookup)
|
||||
{
|
||||
await message.ReactWithAsync(client, Config.Reactions.PleaseWait).ConfigureAwait(false);
|
||||
await message.ReactWithAsync(Config.Reactions.PleaseWait).ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
var results = new List<(string code, Task<DiscordEmbedBuilder> task)>(codesToLookup.Count);
|
||||
@ -149,7 +149,7 @@ namespace CompatBot.EventHandlers
|
||||
titleInfoEmbed.Title = "How about no (๑•ิཬ•ั๑)";
|
||||
if (!string.IsNullOrEmpty(titleInfoEmbed.ThumbnailUrl))
|
||||
titleInfoEmbed.ThumbnailUrl = "https://cdn.discordapp.com/attachments/417347469521715210/516340151589535745/onionoff.png";
|
||||
await message.ReactWithAsync(client, sqvat).ConfigureAwait(false);
|
||||
await message.ReactWithAsync(sqvat).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ namespace CompatBot.EventHandlers
|
||||
if (reporters.Count < Config.Moderation.StarbucksThreshold)
|
||||
return;
|
||||
|
||||
await message.ReactWithAsync(client, emoji).ConfigureAwait(false);
|
||||
await message.ReactWithAsync(emoji).ConfigureAwait(false);
|
||||
await client.ReportAsync(Config.Reactions.Starbucks + " Media talk report", message, reporters, null, ReportSeverity.Medium).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@ -193,24 +193,26 @@ namespace CompatBot.EventHandlers
|
||||
}
|
||||
|
||||
|
||||
private static async Task CheckGameFansAsync(DiscordClient client, DiscordChannel channel, DiscordMessage message)
|
||||
private static Task CheckGameFansAsync(DiscordClient client, DiscordChannel channel, DiscordMessage message)
|
||||
{
|
||||
var bot = client.GetMember(channel.Guild, client.CurrentUser);
|
||||
var ch = channel.IsPrivate ? channel.Users.FirstOrDefault(u => u.Id != client.CurrentUser.Id)?.Username + "'s DM" : "#" + channel.Name;
|
||||
if (!channel.PermissionsFor(bot).HasPermission(Permissions.AddReactions))
|
||||
{
|
||||
Config.Log.Debug($"No permissions to react in #{channel.Name}");
|
||||
return;
|
||||
Config.Log.Debug($"No permissions to react in {ch}");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
var mood = client.GetEmoji(":sqvat:", "😒");
|
||||
if (message.Reactions.Any(r => r.Emoji == mood && r.IsMe))
|
||||
return;
|
||||
return Task.CompletedTask;
|
||||
|
||||
var reactionMsg = string.Concat(message.Reactions.Select(r => TextMap.TryGetValue(r.Emoji, out var txt) ? txt : " ")).Trim();
|
||||
if (string.IsNullOrEmpty(reactionMsg))
|
||||
return;
|
||||
return Task.CompletedTask;
|
||||
|
||||
Config.Log.Debug("Emoji text: " + reactionMsg);
|
||||
Config.Log.Debug($"Emoji text: {reactionMsg} (in {ch})");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ namespace CompatBot.Utils
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task ReactWithAsync(this DiscordMessage message, DiscordClient client, DiscordEmoji emoji, string fallbackMessage = null, bool? showBoth = null)
|
||||
public static async Task ReactWithAsync(this DiscordMessage message, DiscordEmoji emoji, string fallbackMessage = null, bool? showBoth = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -90,7 +90,7 @@ namespace CompatBot.Utils
|
||||
|
||||
public static Task ReactWithAsync(this CommandContext ctx, DiscordEmoji emoji, string fallbackMessage = null, bool? showBoth = null)
|
||||
{
|
||||
return ReactWithAsync(ctx.Message, ctx.Client, emoji, fallbackMessage, showBoth ?? (ctx.Prefix == Config.AutoRemoveCommandPrefix));
|
||||
return ReactWithAsync(ctx.Message, emoji, fallbackMessage, showBoth ?? (ctx.Prefix == Config.AutoRemoveCommandPrefix));
|
||||
}
|
||||
|
||||
public static async Task<IReadOnlyCollection<DiscordMessage>> GetMessagesBeforeAsync(this DiscordChannel channel, ulong beforeMessageId, int limit = 100, DateTime? timeLimit = null)
|
||||
|
@ -33,7 +33,7 @@ namespace CompatBot.Utils
|
||||
{
|
||||
reactions = reactions.Where(r => r != null).ToArray();
|
||||
foreach (var emoji in reactions)
|
||||
await message.ReactWithAsync(interactivity.Client, emoji).ConfigureAwait(false);
|
||||
await message.ReactWithAsync(emoji).ConfigureAwait(false);
|
||||
var expectedChannel = message.Channel;
|
||||
var waitTextResponseTask = interactivity.WaitForMessageAsync(m => m.Author == user && m.Channel == expectedChannel && !string.IsNullOrEmpty(m.Content), timeout);
|
||||
var waitReactionResponse = interactivity.WaitForReactionAsync(arg => reactions.Contains(arg.Emoji), message, user, timeout);
|
||||
|
@ -388,7 +388,7 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
}
|
||||
}
|
||||
|
||||
private static HashSet<string> DesIds = new HashSet<string>
|
||||
private static readonly HashSet<string> DesIds = new HashSet<string>
|
||||
{
|
||||
"BLES00932", "BLUS30443", "BCJS30022", "BCJS70013",
|
||||
"NPEB01202", "NPUB30910", "NPJA00102",
|
||||
|
86
CompatBot/Utils/TimeParser.cs
Normal file
86
CompatBot/Utils/TimeParser.cs
Normal file
@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Remotion.Linq.Clauses;
|
||||
|
||||
namespace CompatBot.Utils
|
||||
{
|
||||
public static class TimeParser
|
||||
{
|
||||
private static readonly Dictionary<string, TimeZoneInfo> TimeZoneMap;
|
||||
|
||||
static TimeParser()
|
||||
{
|
||||
var tzAcronyms = new Dictionary<string, string[]>
|
||||
{
|
||||
["PT"] = new[] { "Pacific Standard Time" },
|
||||
["PST"] = new[] { "Pacific Standard Time" },
|
||||
["PDT"] = new[] { "Pacific Standard Time" },
|
||||
["EST"] = new[] { "Eastern Standard Time" },
|
||||
["EDT"] = new[] { "Eastern Standard Time" },
|
||||
["CEST"] = new[] { "Central European Standard Time" },
|
||||
["BST"] = new[] { "British Summer Time", "GMT Standard Time" },
|
||||
["JST"] = new[] { "Japan Standard Time", "Tokyo Standard Time" },
|
||||
};
|
||||
var uniqueNames = new HashSet<string>(
|
||||
from tznl in tzAcronyms.Values
|
||||
from tzn in tznl
|
||||
select tzn
|
||||
);
|
||||
var tzList = TimeZoneInfo.GetSystemTimeZones();
|
||||
var result = new Dictionary<string, TimeZoneInfo>();
|
||||
foreach (var tzi in tzList)
|
||||
{
|
||||
if (uniqueNames.Contains(tzi.StandardName) || uniqueNames.Contains(tzi.StandardName))
|
||||
{
|
||||
var acronyms = from tza in tzAcronyms
|
||||
where tza.Value.Contains(tzi.StandardName) || tza.Value.Contains(tzi.DaylightName)
|
||||
select tza.Key;
|
||||
foreach (var tza in acronyms)
|
||||
result[tza] = tzi;
|
||||
}
|
||||
}
|
||||
TimeZoneMap = result;
|
||||
}
|
||||
|
||||
public static bool TryParse(string dateTime, out DateTime result)
|
||||
{
|
||||
result = default;
|
||||
if (string.IsNullOrEmpty(dateTime))
|
||||
return false;
|
||||
|
||||
dateTime = dateTime.ToUpperInvariant();
|
||||
if (char.IsDigit(dateTime[dateTime.Length - 1]))
|
||||
{
|
||||
return DateTime.TryParse(dateTime, out result);
|
||||
}
|
||||
|
||||
var cutIdx = dateTime.LastIndexOf(' ');
|
||||
if (cutIdx < 0)
|
||||
return false;
|
||||
|
||||
var tza = dateTime.Substring(cutIdx + 1);
|
||||
dateTime = dateTime.Substring(0, cutIdx);
|
||||
if (TimeZoneMap.TryGetValue(tza, out var tzi))
|
||||
{
|
||||
if (!DateTime.TryParse(dateTime, out result))
|
||||
return false;
|
||||
|
||||
result = TimeZoneInfo.ConvertTimeToUtc(result, tzi);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static DateTime Normalize(this DateTime date)
|
||||
{
|
||||
if (date.Kind == DateTimeKind.Utc)
|
||||
return date;
|
||||
if (date.Kind == DateTimeKind.Local)
|
||||
return date.ToUniversalTime();
|
||||
return date.AsUtc();
|
||||
}
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.14.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
20
Tests/TimeParserTests.cs
Normal file
20
Tests/TimeParserTests.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using CompatBot.Utils;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TimeParserTests
|
||||
{
|
||||
[TestCase("2019-8-19 6:00 PT", "2019-08-19 13:00")]
|
||||
[TestCase("2019-8-19 17:00 bst", "2019-08-19 16:00")]
|
||||
public void TimeZoneConverterTest(string input, string utcInput)
|
||||
{
|
||||
var utc = DateTime.Parse(utcInput).Normalize();
|
||||
Assert.That(TimeParser.TryParse(input, out var result), Is.True);
|
||||
Assert.That(result, Is.EqualTo(utc));
|
||||
Assert.That(result.Kind, Is.EqualTo(DateTimeKind.Utc));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user