From 53f13d88a57dfc60162aeaeb9a4372d693f140c4 Mon Sep 17 00:00:00 2001
From: Octol1ttle <l1ttleofficial@outlook.com>
Date: Mon, 29 Aug 2022 21:24:38 +0500
Subject: [PATCH] Async command handling

---
 Boyfriend/Boyfriend.cs            |  8 +++--
 Boyfriend/Boyfriend.csproj        |  2 +-
 Boyfriend/CommandHandler.cs       | 60 ++++++++++++++++++-------------
 Boyfriend/Commands/BanCommand.cs  |  8 ++---
 Boyfriend/Commands/MuteCommand.cs |  9 +++--
 Boyfriend/EventHandler.cs         |  4 +--
 Boyfriend/Utils.cs                |  3 +-
 7 files changed, 54 insertions(+), 40 deletions(-)

diff --git a/Boyfriend/Boyfriend.cs b/Boyfriend/Boyfriend.cs
index b4aa241..876bd20 100644
--- a/Boyfriend/Boyfriend.cs
+++ b/Boyfriend/Boyfriend.cs
@@ -12,11 +12,15 @@ public static class Boyfriend {
 
     private static readonly DiscordSocketConfig Config = new() {
         MessageCacheSize = 250,
-        GatewayIntents = GatewayIntents.All
+        GatewayIntents = GatewayIntents.All,
+        AlwaysDownloadUsers = true,
+        AlwaysResolveStickers = false,
+        AlwaysDownloadDefaultStickers = false,
+        LargeThreshold = 500
     };
 
     public static readonly DiscordSocketClient Client = new(Config);
-    private static readonly Game Activity = new("Retrospecter - Genocide", ActivityType.Listening);
+    private static readonly Game Activity = new("Toby Fox - The World Revolving", ActivityType.Listening);
 
     private static readonly Dictionary<ulong, Dictionary<string, string>> GuildConfigDictionary = new();
 
diff --git a/Boyfriend/Boyfriend.csproj b/Boyfriend/Boyfriend.csproj
index 80329ec..8839dbb 100644
--- a/Boyfriend/Boyfriend.csproj
+++ b/Boyfriend/Boyfriend.csproj
@@ -15,7 +15,7 @@
     </PropertyGroup>
 
     <ItemGroup>
-        <PackageReference Include="Discord.Net" Version="3.7.2"/>
+        <PackageReference Include="Discord.Net" Version="3.8.0"/>
         <PackageReference Include="Humanizer.Core" Version="2.14.1"/>
         <PackageReference Include="Humanizer.Core.ru" Version="2.14.1"/>
         <PackageReference Include="Newtonsoft.Json" Version="13.0.2-beta1"/>
diff --git a/Boyfriend/CommandHandler.cs b/Boyfriend/CommandHandler.cs
index 097993e..a8eed4d 100644
--- a/Boyfriend/CommandHandler.cs
+++ b/Boyfriend/CommandHandler.cs
@@ -22,10 +22,14 @@ public static class CommandHandler {
     public static readonly StringBuilder StackedPrivateFeedback = new();
 
 #pragma warning disable CA2211
-    public static bool ConfigWriteScheduled = false; // HOW IT CAN BE PRIVATE????
+    public static bool ConfigWriteScheduled = false; // Can't be private
 #pragma warning restore CA2211
 
+    private static bool _handlerBusy;
+
     public static async Task HandleCommand(SocketUserMessage message) {
+        while (_handlerBusy) await Task.Delay(200);
+        _handlerBusy = true;
         StackedReplyMessage.Clear();
         StackedPrivateFeedback.Clear();
         StackedPublicFeedback.Clear();
@@ -43,34 +47,42 @@ public static class CommandHandler {
         var currentLine = 0;
         foreach (var line in list) {
             currentLine++;
-            foreach (var command in Commands) {
-                var lineNoMention = MentionRegex.Replace(line, "", 1);
-                if (!command.Aliases.Contains(regex.Replace(lineNoMention, "", 1).Trim().ToLower().Split()[0]))
-                    continue;
+            await RunCommands(line, regex, context, currentLine == list.Length);
+        }
 
-                await context.Channel.TriggerTypingAsync();
+        if (ConfigWriteScheduled) await Boyfriend.WriteGuildConfig(guild.Id);
 
-                var args = line.Split().Skip(1).ToArray();
+        var adminChannel = Utils.GetAdminLogChannel(guild.Id);
+        var systemChannel = guild.SystemChannel;
+        if (StackedPrivateFeedback.Length > 0 && adminChannel != null && adminChannel.Id != message.Channel.Id)
+            await Utils.SilentSendAsync(adminChannel, StackedPrivateFeedback.ToString());
+        if (StackedPublicFeedback.Length > 0 && systemChannel != null && systemChannel.Id != adminChannel?.Id
+            && systemChannel.Id != message.Channel.Id)
+            await Utils.SilentSendAsync(systemChannel, StackedPublicFeedback.ToString());
+        _handlerBusy = false;
+    }
 
-                if (command.ArgsLengthRequired <= args.Length)
+    private static async Task RunCommands(string line, Regex regex, SocketCommandContext context, bool shouldAwait) {
+        foreach (var command in Commands) {
+            var lineNoMention = MentionRegex.Replace(line, "", 1);
+            if (!command.Aliases.Contains(regex.Replace(lineNoMention, "", 1).Trim().ToLower().Split()[0]))
+                continue;
+
+            await context.Channel.TriggerTypingAsync();
+
+            var args = line.Split().Skip(1).ToArray();
+
+            if (command.ArgsLengthRequired <= args.Length)
+                if (shouldAwait)
                     await command.Run(context, args);
                 else
-                    StackedReplyMessage.AppendFormat(Messages.NotEnoughArguments, command.ArgsLengthRequired.ToString(),
-                        args.Length.ToString());
-
-                if (currentLine != list.Length) continue;
-                if (ConfigWriteScheduled) await Boyfriend.WriteGuildConfig(guild.Id);
-                if (StackedReplyMessage.Length > 0)
-                    await message.ReplyAsync(StackedReplyMessage.ToString(), false, null, AllowedMentions.None);
-
-                var adminChannel = Utils.GetAdminLogChannel(guild.Id);
-                var systemChannel = guild.SystemChannel;
-                if (StackedPrivateFeedback.Length > 0 && adminChannel != null && adminChannel.Id != message.Channel.Id)
-                    await Utils.SilentSendAsync(adminChannel, StackedPrivateFeedback.ToString());
-                if (StackedPublicFeedback.Length > 0 && systemChannel != null && systemChannel.Id != adminChannel?.Id
-                    && systemChannel.Id != message.Channel.Id)
-                    await Utils.SilentSendAsync(systemChannel, StackedPublicFeedback.ToString());
-            }
+                    _ = command.Run(context, args);
+            else
+                StackedReplyMessage.AppendFormat(Messages.NotEnoughArguments, command.ArgsLengthRequired.ToString(),
+                    args.Length.ToString()).AppendLine();
+            if (StackedReplyMessage.Length <= 1675 && !shouldAwait) continue;
+            await context.Message.ReplyAsync(StackedReplyMessage.ToString(), false, null, AllowedMentions.None);
+            StackedReplyMessage.Clear();
         }
     }
 
diff --git a/Boyfriend/Commands/BanCommand.cs b/Boyfriend/Commands/BanCommand.cs
index ce83d35..0f67c81 100644
--- a/Boyfriend/Commands/BanCommand.cs
+++ b/Boyfriend/Commands/BanCommand.cs
@@ -65,12 +65,10 @@ public class BanCommand : Command {
         await Utils.SendFeedback(feedback, guild.Id, author.Mention, true);
 
         if (duration.TotalSeconds > 0) {
-            async void DelayUnban() {
+            var _ = async () => {
                 await Task.Delay(duration);
                 await UnbanCommand.UnbanUser(guild, guild.CurrentUser, toBan, Messages.PunishmentExpired);
-            }
-
-            new Task(DelayUnban).Start();
+            };
         }
     }
-}
\ No newline at end of file
+}
diff --git a/Boyfriend/Commands/MuteCommand.cs b/Boyfriend/Commands/MuteCommand.cs
index 7dd8aef..d9b61d7 100644
--- a/Boyfriend/Commands/MuteCommand.cs
+++ b/Boyfriend/Commands/MuteCommand.cs
@@ -91,12 +91,11 @@ public class MuteCommand : Command {
                 CommandHandler.ConfigWriteScheduled = true;
 
                 if (hasDuration) {
-                    async void DelayUnmute() {
-                        await Task.Delay(duration);
+                    var copy = duration;
+                    var _ = async () => {
+                        await Task.Delay(copy);
                         await UnmuteCommand.UnmuteMember(guild, guild.CurrentUser, toMute, Messages.PunishmentExpired);
-                    }
-
-                    new Task(DelayUnmute).Start();
+                    };
                 }
             }
 
diff --git a/Boyfriend/EventHandler.cs b/Boyfriend/EventHandler.cs
index 91b8a25..c4f6a99 100644
--- a/Boyfriend/EventHandler.cs
+++ b/Boyfriend/EventHandler.cs
@@ -83,7 +83,7 @@ public class EventHandler {
                                           (message.Content.Contains(prev) || message.Content.Contains(prevFailsafe))))
             return;
 
-        await CommandHandler.HandleCommand(message);
+        _ = CommandHandler.HandleCommand(message);
     }
 
     private static async Task MessageUpdatedEvent(Cacheable<IMessage, ulong> messageCached, SocketMessage messageSocket,
@@ -176,4 +176,4 @@ public class EventHandler {
             await channel.SendMessageAsync(string.Format(Messages.EventCompleted, Utils.Wrap(scheduledEvent.Name),
                 Utils.Wrap(scheduledEvent.StartTime.Subtract(DateTimeOffset.Now).Negate().ToString())));
     }
-}
\ No newline at end of file
+}
diff --git a/Boyfriend/Utils.cs b/Boyfriend/Utils.cs
index 292b611..213196e 100644
--- a/Boyfriend/Utils.cs
+++ b/Boyfriend/Utils.cs
@@ -118,6 +118,7 @@ public static class Utils {
                 }
             }
 
+        numberBuilder.Clear();
         return new TimeSpan(days, hours, minutes, seconds);
     }
 
@@ -168,4 +169,4 @@ public static class Utils {
     public static void SetCurrentLanguage(ulong guildId) {
         Messages.Culture = CultureInfoCache[Boyfriend.GetGuildConfig(guildId)["Lang"]];
     }
-}
\ No newline at end of file
+}