From 270fba5c3cc97758a5d9010406c2c75170bd7ff6 Mon Sep 17 00:00:00 2001 From: l1ttleO Date: Wed, 15 Dec 2021 11:19:14 +0500 Subject: [PATCH] more stuff. yeah --- Boyfriend/Boyfriend.cs | 73 ++++++++++++++++++--------- Boyfriend/CommandHandler.cs | 74 ++++++++++++++++++++++++++++ Boyfriend/Commands/BanModule.cs | 24 ++++++--- Boyfriend/Commands/ClearModule.cs | 7 ++- Boyfriend/Commands/HelpModule.cs | 25 ++++++++++ Boyfriend/Commands/KickModule.cs | 12 ++--- Boyfriend/Commands/MuteModule.cs | 29 ++++++++--- Boyfriend/Commands/SettingsModule.cs | 46 +++++++++++++++++ Boyfriend/Commands/UnbanModule.cs | 11 +++-- Boyfriend/Commands/UnmuteModule.cs | 15 +++--- Boyfriend/EventHandler.cs | 70 ++++++++------------------ Boyfriend/GuildConfig.cs | 22 +++++++++ Boyfriend/Utils.cs | 9 +--- 13 files changed, 301 insertions(+), 116 deletions(-) create mode 100644 Boyfriend/CommandHandler.cs create mode 100644 Boyfriend/Commands/HelpModule.cs create mode 100644 Boyfriend/Commands/SettingsModule.cs create mode 100644 Boyfriend/GuildConfig.cs diff --git a/Boyfriend/Boyfriend.cs b/Boyfriend/Boyfriend.cs index 9937d0e..f643729 100644 --- a/Boyfriend/Boyfriend.cs +++ b/Boyfriend/Boyfriend.cs @@ -1,33 +1,62 @@ -using Discord; +using System.Text.Json; +using Discord; using Discord.WebSocket; namespace Boyfriend; - public static class Boyfriend { - public static void Main() - => Init().GetAwaiter().GetResult(); +public static class Boyfriend { - private static readonly DiscordSocketConfig Config = new() { - MessageCacheSize = 250, - GatewayIntents = GatewayIntents.All - }; - public static readonly DiscordSocketClient Client = new(Config); + public static void Main() + => Init().GetAwaiter().GetResult(); - private static async Task Init() { - Client.Log += Log; - var token = (await File.ReadAllTextAsync("token.txt")).Trim(); + private static readonly DiscordSocketConfig Config = new() { + MessageCacheSize = 250, + GatewayIntents = GatewayIntents.All + }; - await Client.LoginAsync(TokenType.Bot, token); - await Client.StartAsync(); - await Client.SetActivityAsync(new Game("Retrospecter - Electrospasm", ActivityType.Listening)); + public static readonly DiscordSocketClient Client = new(Config); - await new EventHandler().InitEvents(); + private static readonly Dictionary GuildConfigDictionary = new(); - await Task.Delay(-1); + private static async Task Init() { + Client.Log += Log; + var token = (await File.ReadAllTextAsync("token.txt")).Trim(); + + await Client.LoginAsync(TokenType.Bot, token); + await Client.StartAsync(); + await Client.SetActivityAsync(new Game("Retrospecter - Electrospasm", ActivityType.Listening)); + + await new EventHandler().InitEvents(); + + await Task.Delay(-1); + } + + private static Task Log(LogMessage msg) { + Console.WriteLine(msg.ToString()); + return Task.CompletedTask; + } + + public static async Task SetupGuildConfigs() { + foreach (var guild in Client.Guilds) { + var path = "config_" + guild.Id + ".json"; + var openStream = !File.Exists(path) ? File.Create(path) : File.OpenRead(path); + + GuildConfig config; + try { + config = await JsonSerializer.DeserializeAsync(openStream) ?? throw new Exception(); + } catch (JsonException) { + config = new GuildConfig(guild.Id, "ru", "!", false); + } + GuildConfigDictionary.Add(guild.Id, config); } + } - private static Task Log(LogMessage msg) { - Console.WriteLine(msg.ToString()); - return Task.CompletedTask; - } - } \ No newline at end of file + public static GuildConfig GetGuildConfig(IGuild guild) { + GuildConfig toReturn; + toReturn = GuildConfigDictionary.ContainsKey(guild.Id) ? GuildConfigDictionary[guild.Id] + : new GuildConfig(guild.Id, "ru", "!", false); + + if (toReturn.Id != guild.Id) throw new Exception(); + return toReturn; + } +} \ No newline at end of file diff --git a/Boyfriend/CommandHandler.cs b/Boyfriend/CommandHandler.cs new file mode 100644 index 0000000..90026cc --- /dev/null +++ b/Boyfriend/CommandHandler.cs @@ -0,0 +1,74 @@ +using Discord; +using Discord.Commands; +using Discord.WebSocket; + +namespace Boyfriend; + +public static class CommandHandler { + public static async Task HandleCommand(SocketUserMessage message, int argPos) { + var context = new SocketCommandContext(Boyfriend.Client, message); + var result = await EventHandler.Commands.ExecuteAsync(context, argPos, null); + + await HandleErrors(context, result); + } + private static async Task HandleErrors(SocketCommandContext context, IResult result) { + var channel = context.Channel; + var reason = Utils.WrapInline(result.ErrorReason); + switch (result.Error) { + case CommandError.Exception: + await channel.SendMessageAsync(reason); + break; + case CommandError.Unsuccessful: + await channel.SendMessageAsync($"Выполнение команды завершилось неудачей: {reason}"); + break; + case CommandError.MultipleMatches: + await channel.SendMessageAsync($"Обнаружены повторяющиеся типы аргументов! {reason}"); + break; + case CommandError.ParseFailed: + await channel.SendMessageAsync($"Не удалось обработать команду: {reason}"); + break; + case CommandError.UnknownCommand: + await channel.SendMessageAsync($"Неизвестная команда! {reason}"); + break; + case CommandError.UnmetPrecondition: + await channel.SendMessageAsync($"У тебя недостаточно прав для выполнения этой к: {reason}"); + break; + case CommandError.BadArgCount: + await channel.SendMessageAsync($"Неверное количество аргументов! {reason}"); + break; + case CommandError.ObjectNotFound: + await channel.SendMessageAsync($"Нету нужных аргументов! {reason}"); + break; + case null: + break; + default: + throw new Exception("CommandError"); + } + } + + public static async Task CheckPermissions(IGuildUser user, GuildPermission toCheck, + GuildPermission forBot = GuildPermission.StartEmbeddedActivities) { + if (forBot == GuildPermission.StartEmbeddedActivities) forBot = toCheck; + if (!(await user.Guild.GetCurrentUserAsync()).GuildPermissions.Has(forBot)) + throw new Exception("У меня недостаточно прав для выполнения этой команды!"); + if (!user.GuildPermissions.Has(toCheck)) + throw new Exception("У тебя недостаточно прав для выполнения этой команды!"); + } + + public static async Task CheckInteractions(IGuildUser actor, IGuildUser target) { + if (actor.Guild != target.Guild) + throw new Exception("Участники находятся в разных гильдиях!"); + var me = await target.Guild.GetCurrentUserAsync(); + if (actor.Id == actor.Guild.OwnerId) return; + if (target.Id == target.Guild.OwnerId) + throw new Exception("Ты не можешь взаимодействовать с владельцем сервера!"); + if (actor == target) + throw new Exception("Ты не можешь взаимодействовать с самим собой!"); + if (target == me) + throw new Exception("Ты не можешь со мной взаимодействовать!"); + if (actor.Hierarchy <= target.Hierarchy) + throw new Exception("Ты не можешь взаимодействовать с этим участником!"); + if (me.Hierarchy <= target.Hierarchy) + throw new Exception("Я не могу взаимодействовать с этим участником!"); + } +} \ No newline at end of file diff --git a/Boyfriend/Commands/BanModule.cs b/Boyfriend/Commands/BanModule.cs index 049c203..a89c1d5 100644 --- a/Boyfriend/Commands/BanModule.cs +++ b/Boyfriend/Commands/BanModule.cs @@ -12,18 +12,26 @@ public class BanModule : ModuleBase { [Command("ban")] [Summary("Банит пользователя")] [Alias("бан")] - [RequireBotPermission(GuildPermission.BanMembers)] - [RequireUserPermission(GuildPermission.BanMembers)] - public Task Run(string user, TimeSpan duration, [Remainder]string reason) { - var toBan = Utils.ParseUser(user).Result; - BanUser(Context.Guild, Context.User, toBan, duration, reason); - return Task.CompletedTask; + public async Task Run(string user, string durationString, [Remainder]string reason) { + TimeSpan duration; + try { + duration = TimeSpan.Parse(durationString); + } catch (Exception e) when (e is ArgumentNullException or FormatException or OverflowException) { + duration = TimeSpan.FromMilliseconds(-1); + reason = durationString + reason; + } + var author = Context.Guild.GetUser(Context.User.Id); + var toBan = await Utils.ParseUser(user); + await CommandHandler.CheckPermissions(author, GuildPermission.BanMembers); + var memberToBan = Context.Guild.GetUser(toBan.Id); + if (memberToBan != null) + await CommandHandler.CheckInteractions(author, memberToBan); + BanUser(Context.Guild, Context.Guild.GetUser(Context.User.Id), toBan, duration, reason); } - public static async void BanUser(IGuild guild, IUser author, IUser toBan, TimeSpan duration, string reason) { + public static async void BanUser(IGuild guild, IGuildUser author, IUser toBan, TimeSpan duration, string reason) { var authorMention = author.Mention; await Utils.SendDirectMessage(toBan, $"Тебя забанил {author.Mention} на сервере {guild.Name} за `{reason}`"); - var guildBanMessage = $"({author.Username}#{author.Discriminator}) {reason}"; await guild.AddBanAsync(toBan, 0, guildBanMessage); var notification = $"{authorMention} банит {toBan.Mention} за {Utils.WrapInline(reason)}"; diff --git a/Boyfriend/Commands/ClearModule.cs b/Boyfriend/Commands/ClearModule.cs index f17dab0..bd5f87f 100644 --- a/Boyfriend/Commands/ClearModule.cs +++ b/Boyfriend/Commands/ClearModule.cs @@ -12,15 +12,14 @@ public class ClearModule : ModuleBase { [Command("clear")] [Summary("Удаляет указанное количество сообщений")] [Alias("очистить")] - [RequireBotPermission(GuildPermission.ManageMessages)] - [RequireUserPermission(GuildPermission.ManageMessages)] public async Task Run(int toDelete) { if (Context.Channel is not ITextChannel channel) return; + await CommandHandler.CheckPermissions(Context.Guild.GetUser(Context.User.Id), GuildPermission.ManageMessages); switch (toDelete) { case < 1: - throw new ArgumentException("toDelete is less than 1."); + throw new Exception( "Указано отрицательное количество сообщений!"); case > 200: - throw new ArgumentException("toDelete is more than 200."); + throw new Exception("Указано слишком много сообщений!"); default: { var messages = await channel.GetMessagesAsync(toDelete + 1).FlattenAsync(); await channel.DeleteMessagesAsync(messages); diff --git a/Boyfriend/Commands/HelpModule.cs b/Boyfriend/Commands/HelpModule.cs new file mode 100644 index 0000000..cafea6d --- /dev/null +++ b/Boyfriend/Commands/HelpModule.cs @@ -0,0 +1,25 @@ +using Discord.Commands; +// ReSharper disable UnusedType.Global +// ReSharper disable UnusedMember.Global + +namespace Boyfriend.Commands; + +public class HelpModule : ModuleBase { + + [Command("help")] + [Summary("Показывает эту справку")] + [Alias("помощь", "справка")] + public Task Run() { + var nl = Environment.NewLine; + var toSend = $"Справка по командам:{nl}"; + var prefix = Boyfriend.GetGuildConfig(Context.Guild).Prefix; + foreach (var command in EventHandler.Commands.Commands) { + var aliases = command.Aliases.Aggregate("", (current, alias) => + current + (current == "" ? "" : $", {prefix}") + alias); + toSend += $"`{prefix}{aliases}`: {command.Summary}{nl}"; + } + + Context.Channel.SendMessageAsync(toSend); + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/Boyfriend/Commands/KickModule.cs b/Boyfriend/Commands/KickModule.cs index 4989557..f45f0d0 100644 --- a/Boyfriend/Commands/KickModule.cs +++ b/Boyfriend/Commands/KickModule.cs @@ -12,15 +12,15 @@ public class KickModule : ModuleBase { [Command("kick")] [Summary("Выгоняет пользователя")] [Alias("кик")] - [RequireBotPermission(GuildPermission.KickMembers)] - [RequireUserPermission(GuildPermission.KickMembers)] - public Task Run(string user, [Remainder]string reason) { + public async Task Run(string user, [Remainder]string reason) { + var author = Context.Guild.GetUser(Context.User.Id); var toKick = Utils.ParseMember(Context.Guild, user).Result; - KickMember(Context.Guild, Context.User, toKick, reason); - return Task.CompletedTask; + await CommandHandler.CheckPermissions(author, GuildPermission.KickMembers); + await CommandHandler.CheckInteractions(author, toKick); + KickMember(Context.Guild, Context.Guild.GetUser(Context.User.Id), toKick, reason); } - private static async void KickMember(IGuild guild, IUser author, IGuildUser toKick, string reason) { + private static async void KickMember(IGuild guild, IGuildUser author, IGuildUser toKick, string reason) { var authorMention = author.Mention; await Utils.SendDirectMessage(toKick, $"Тебя кикнул {authorMention} на сервере {guild.Name} за " + $"{Utils.WrapInline(reason)}"); diff --git a/Boyfriend/Commands/MuteModule.cs b/Boyfriend/Commands/MuteModule.cs index f95cbd3..9d383c8 100644 --- a/Boyfriend/Commands/MuteModule.cs +++ b/Boyfriend/Commands/MuteModule.cs @@ -12,18 +12,33 @@ public class MuteModule : ModuleBase { [Command("mute")] [Summary("Глушит пользователя")] [Alias("мут")] - [RequireBotPermission(GuildPermission.ManageRoles)] - [RequireUserPermission(GuildPermission.ManageMessages)] - public Task Run(string user, TimeSpan duration, [Remainder]string reason) { - var toMute = Utils.ParseMember(Context.Guild, user).Result; - MuteMember(Context.Guild, Context.User, toMute, duration, reason); - return Task.CompletedTask; + public async Task Run(string user, string durationString, [Remainder]string reason) { + TimeSpan duration; + try { + duration = TimeSpan.Parse(durationString); + } catch (Exception e) when (e is ArgumentNullException or FormatException or OverflowException) { + duration = TimeSpan.FromMilliseconds(-1); + reason = durationString + reason; + } + var author = Context.Guild.GetUser(Context.User.Id); + var toMute = await Utils.ParseMember(Context.Guild, user); + await CommandHandler.CheckPermissions(author, GuildPermission.ManageMessages, GuildPermission.ManageRoles); + await CommandHandler.CheckInteractions(author, toMute); + MuteMember(Context.Guild, Context.Guild.GetUser(Context.User.Id), toMute, duration, reason); } - private static async void MuteMember(IGuild guild, IMentionable author, IGuildUser toMute, TimeSpan duration, + private static async void MuteMember(IGuild guild, IGuildUser author, IGuildUser toMute, TimeSpan duration, string reason) { + await CommandHandler.CheckPermissions(author, GuildPermission.ManageMessages, GuildPermission.ManageRoles); var authorMention = author.Mention; var role = Utils.GetMuteRole(guild); + if (Boyfriend.GetGuildConfig(guild).RemoveRolesOnMute) { + foreach (var roleId in toMute.RoleIds) { + await toMute.RemoveRoleAsync(roleId); + + } + } + await toMute.AddRoleAsync(role); var notification = $"{authorMention} глушит {toMute.Mention} за {Utils.WrapInline(reason)}"; await Utils.SilentSendAsync(guild.GetSystemChannelAsync().Result, notification); diff --git a/Boyfriend/Commands/SettingsModule.cs b/Boyfriend/Commands/SettingsModule.cs new file mode 100644 index 0000000..a528bbf --- /dev/null +++ b/Boyfriend/Commands/SettingsModule.cs @@ -0,0 +1,46 @@ +using Discord.Commands; +// ReSharper disable UnusedType.Global +// ReSharper disable UnusedMember.Global + +namespace Boyfriend.Commands; + +public class SettingsModule : ModuleBase { + + [Command("settings")] + [Summary("Настраивает бота")] + [Alias("config", "настройки", "конфиг")] + public async Task Run([Remainder] string s = "") { + var config = Boyfriend.GetGuildConfig(Context.Guild); + var sArray = s.Split(" "); + if (s == "") { + var nl = Environment.NewLine; + await Context.Channel.SendMessageAsync($"Текущие настройки:{nl}Язык: `{config.Lang}`" + + $"{nl}Префикс: `{config.Prefix}`" + + $"{nl}Удалять роли при муте: " + + $"{(config.RemoveRolesOnMute ? "Да" : "Нет")}"); + return; + } + + if (sArray[0].ToLower() == "lang") { + if (sArray[1].ToLower() != "ru") throw new Exception("Язык не поддерживается!"); + config.Lang = sArray[1].ToLower(); + } + + + if (sArray[0].ToLower() == "prefix") + config.Prefix = sArray[1]; + + if (sArray[0].ToLower() == "removerolesonmute") { + try { + config.RemoveRolesOnMute = bool.Parse(sArray[1].ToLower()); + } catch (FormatException) { + await Context.Channel.SendMessageAsync("Неверный параметр! Требуется `true` или `false`"); + return; + } + } + + config.Save(); + + await Context.Channel.SendMessageAsync("Настройки успешно обновлены!"); + } +} \ No newline at end of file diff --git a/Boyfriend/Commands/UnbanModule.cs b/Boyfriend/Commands/UnbanModule.cs index 0a2e841..57039db 100644 --- a/Boyfriend/Commands/UnbanModule.cs +++ b/Boyfriend/Commands/UnbanModule.cs @@ -11,15 +11,16 @@ public class UnbanModule : ModuleBase { [Command("unban")] [Summary("Возвращает пользователя из бана")] [Alias("разбан")] - [RequireBotPermission(GuildPermission.BanMembers)] - [RequireUserPermission(GuildPermission.BanMembers)] public Task Run(string user, [Remainder] string reason) { - var toBan = Utils.ParseUser(user).Result; - UnbanUser(Context.Guild, Context.User, toBan, reason); + var toUnban = Utils.ParseUser(user).Result; + if (Context.Guild.GetBanAsync(toUnban.Id) == null) + throw new Exception("Пользователь не забанен!"); + UnbanUser(Context.Guild, Context.Guild.GetUser(Context.User.Id), toUnban, reason); return Task.CompletedTask; } - public static async void UnbanUser(IGuild guild, IUser author, IUser toUnban, string reason) { + public static async void UnbanUser(IGuild guild, IGuildUser author, IUser toUnban, string reason) { + await CommandHandler.CheckPermissions(author, GuildPermission.BanMembers); var authorMention = author.Mention; var notification = $"{authorMention} возвращает из бана {toUnban.Mention} за {Utils.WrapInline(reason)}"; await guild.RemoveBanAsync(toUnban); diff --git a/Boyfriend/Commands/UnmuteModule.cs b/Boyfriend/Commands/UnmuteModule.cs index 6135909..0e81805 100644 --- a/Boyfriend/Commands/UnmuteModule.cs +++ b/Boyfriend/Commands/UnmuteModule.cs @@ -11,15 +11,18 @@ public class UnmuteModule : ModuleBase { [Command("unmute")] [Summary("Возвращает пользователя из мута")] [Alias("размут")] - [RequireBotPermission(GuildPermission.ManageRoles)] - [RequireUserPermission(GuildPermission.ManageMessages)] - public Task Run(string user, [Remainder] string reason) { + public async Task Run(string user, [Remainder] string reason) { var toUnmute = Utils.ParseMember(Context.Guild, user).Result; - UnmuteMember(Context.Guild, Context.User, toUnmute, reason); - return Task.CompletedTask; + var author = Context.Guild.GetUser(Context.User.Id); + await CommandHandler.CheckPermissions(author, GuildPermission.ManageMessages, GuildPermission.ManageRoles); + await CommandHandler.CheckInteractions(author, toUnmute); + if (toUnmute.RoleIds.All(x => x != Utils.GetMuteRole(Context.Guild).Id)) + throw new Exception("Пользователь не в муте!"); + UnmuteMember(Context.Guild, Context.Guild.GetUser(Context.User.Id), toUnmute, reason); } - public static async void UnmuteMember(IGuild guild, IUser author, IGuildUser toUnmute, string reason) { + public static async void UnmuteMember(IGuild guild, IGuildUser author, IGuildUser toUnmute, string reason) { + await CommandHandler.CheckPermissions(author, GuildPermission.ManageMessages, GuildPermission.ManageRoles); var authorMention = author.Mention; var notification = $"{authorMention} возвращает из мута {toUnmute.Mention} за {Utils.WrapInline(reason)}"; await toUnmute.RemoveRoleAsync(Utils.GetMuteRole(guild)); diff --git a/Boyfriend/EventHandler.cs b/Boyfriend/EventHandler.cs index 2c14e6d..1ab8dd8 100644 --- a/Boyfriend/EventHandler.cs +++ b/Boyfriend/EventHandler.cs @@ -8,7 +8,7 @@ namespace Boyfriend; public class EventHandler { private readonly DiscordSocketClient _client = Boyfriend.Client; - private readonly CommandService _commands = new(); + public static readonly CommandService Commands = new(); public async Task InitEvents() { _client.Ready += ReadyEvent; @@ -16,50 +16,16 @@ public class EventHandler { _client.MessageReceived += MessageReceivedEvent; _client.MessageUpdated += MessageUpdatedEvent; _client.UserJoined += UserJoinedEvent; - await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), null); - } - - private static async Task HandleErrors(SocketCommandContext context, IResult result) { - var channel = context.Channel; - var reason = Utils.WrapInline(result.ErrorReason); - switch (result.Error) { - case CommandError.Exception: - await channel.SendMessageAsync($"Произошла непредвиденная ошибка при выполнении команды: {reason}"); - break; - case CommandError.Unsuccessful: - await channel.SendMessageAsync($"Выполнение команды завершилось неудачей: {reason}"); - break; - case CommandError.MultipleMatches: - await channel.SendMessageAsync($"Обнаружены повторяющиеся типы аргументов! {reason}"); - break; - case CommandError.ParseFailed: - await channel.SendMessageAsync($"Не удалось обработать команду: {reason}"); - break; - case CommandError.UnknownCommand: - await channel.SendMessageAsync($"Неизвестная команда! {reason}"); - break; - case CommandError.UnmetPrecondition: - await channel.SendMessageAsync($"У тебя недостаточно прав для выполнения этой команды! {reason}"); - break; - case CommandError.BadArgCount: - await channel.SendMessageAsync($"Неверное количество аргументов! {reason}"); - break; - case CommandError.ObjectNotFound: - await channel.SendMessageAsync($"Нету нужных аргументов! {reason}"); - break; - case null: - break; - default: - throw new ArgumentException("CommandError"); - - } + await Commands.AddModulesAsync(Assembly.GetEntryAssembly(), null); } [Obsolete("Stop hard-coding things!")] private async Task ReadyEvent() { if (_client.GetChannel(618044439939645444) is not IMessageChannel botLogChannel) - throw new ArgumentException("Invalid bot log channel"); + throw new Exception("Invalid bot log channel"); await botLogChannel.SendMessageAsync($"{Utils.GetBeep()}Я запустился! (C#)"); + + await Boyfriend.SetupGuildConfigs(); } private static async Task MessageDeletedEvent(Cacheable message, @@ -72,34 +38,38 @@ public class EventHandler { await Utils.SilentSendAsync(Utils.GetAdminLogChannel(), toSend); } - private async Task MessageReceivedEvent(SocketMessage messageParam) { - if (messageParam is not SocketUserMessage {Author: IGuildUser user} message) return; - var argPos = 0; + private static async Task MessageReceivedEvent(SocketMessage messageParam) { + if (messageParam is not SocketUserMessage message) return; + var user = (IGuildUser) message.Author; var guild = user.Guild; + var argPos = 0; if ((message.MentionedUsers.Count > 3 || message.MentionedRoles.Count > 2) && !user.GuildPermissions.MentionEveryone) BanModule.BanUser(guild, guild.GetCurrentUserAsync().Result, user, TimeSpan.FromMilliseconds(-1), "Более 3-ёх упоминаний в одном сообщении"); - if (!(message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(_client.CurrentUser, ref argPos)) || - message.Author.IsBot) + var prevs = await message.Channel.GetMessagesAsync(3).FlattenAsync(); + var prevsArray = prevs as IMessage[] ?? prevs.ToArray(); + var prev = prevsArray[1].Content; + var prevFailsafe = prevsArray[2].Content; + if (!(message.HasStringPrefix(Boyfriend.GetGuildConfig(guild).Prefix, ref argPos) + || message.HasMentionPrefix(Boyfriend.Client.CurrentUser, ref argPos)) + || user.IsBot && message.Content.Contains(prev) || message.Content.Contains(prevFailsafe)) return; - var context = new SocketCommandContext(_client, message); - - var result = await _commands.ExecuteAsync(context, argPos, null); - await HandleErrors(context, result); + await CommandHandler.HandleCommand(message, argPos); } private static async Task MessageUpdatedEvent(Cacheable messageCached, SocketMessage messageSocket, ISocketMessageChannel channel) { var msg = messageCached.Value; var nl = Environment.NewLine; + if (msg.Content == messageSocket.Content) return; var toSend = msg == null ? $"Отредактировано сообщение от {messageSocket.Author.Mention} в канале" + - $" {Utils.MentionChannel(channel.Id)}," + $" но я забыл что там было до редактирования: " + - $"{Utils.Wrap(messageSocket.Content)}" + $" {Utils.MentionChannel(channel.Id)}," + " но я забыл что там было до редактирования: " + + Utils.Wrap(messageSocket.Content) : $"Отредактировано сообщение от {msg.Author.Mention} " + $"в канале {Utils.MentionChannel(channel.Id)}." + $"{nl}До:{nl}{Utils.Wrap(msg.Content)}{nl}После:{nl}{Utils.Wrap(messageSocket.Content)}"; diff --git a/Boyfriend/GuildConfig.cs b/Boyfriend/GuildConfig.cs new file mode 100644 index 0000000..c9a6c26 --- /dev/null +++ b/Boyfriend/GuildConfig.cs @@ -0,0 +1,22 @@ +using System.Text.Json; + +namespace Boyfriend; + +public class GuildConfig { + public ulong Id { get; } + public string Lang { get; set; } + public string Prefix { get; set; } + public bool RemoveRolesOnMute { get; set; } + + public GuildConfig(ulong id, string lang, string prefix, bool removeRolesOnMute) { + Id = id; + Lang = lang; + Prefix = prefix; + RemoveRolesOnMute = removeRolesOnMute; + } + + public async void Save() { + await using var stream = File.OpenWrite("config_" + Id + ".json"); + await JsonSerializer.SerializeAsync(stream, this); + } +} \ No newline at end of file diff --git a/Boyfriend/Utils.cs b/Boyfriend/Utils.cs index 9c0ced5..3ff7c4a 100644 --- a/Boyfriend/Utils.cs +++ b/Boyfriend/Utils.cs @@ -13,7 +13,7 @@ public static class Utils { [Obsolete("Stop hard-coding things!")] public static ITextChannel GetAdminLogChannel() { if (Boyfriend.Client.GetChannel(870929165141032971) is not ITextChannel adminLogChannel) - throw new ArgumentException("Invalid admin log channel"); + throw new Exception("Invalid admin log channel"); return adminLogChannel; } @@ -31,13 +31,6 @@ public static class Utils { } public static async Task StartDelayed(Task toRun, TimeSpan delay, Func? condition = null) { - switch (delay.TotalMilliseconds) { - case < -1: - throw new ArgumentOutOfRangeException(nameof(delay), "Указана отрицательная продолжительность!"); - case > int.MaxValue: - throw new ArgumentOutOfRangeException(nameof(delay), "Указана слишком большая продолжительность!"); - } - await Task.Delay(delay); var conditionResult = condition?.Invoke() ?? true; if (conditionResult)