From 1c9caf6d75c5b9d486c291c740bf2ea3487c4395 Mon Sep 17 00:00:00 2001 From: l1ttleO Date: Thu, 16 Dec 2021 00:07:04 +0500 Subject: [PATCH] now fully configurable :D --- Boyfriend/Boyfriend.cs | 19 +++-- Boyfriend/Commands/BanModule.cs | 11 +-- Boyfriend/Commands/ClearModule.cs | 2 +- Boyfriend/Commands/KickModule.cs | 8 +-- Boyfriend/Commands/MuteModule.cs | 31 +++++--- Boyfriend/Commands/SettingsModule.cs | 103 ++++++++++++++++++++++----- Boyfriend/Commands/UnbanModule.cs | 9 ++- Boyfriend/Commands/UnmuteModule.cs | 24 +++++-- Boyfriend/EventHandler.cs | 29 +++++--- Boyfriend/GuildConfig.cs | 15 +++- Boyfriend/Utils.cs | 41 ++++++++--- 11 files changed, 221 insertions(+), 71 deletions(-) diff --git a/Boyfriend/Boyfriend.cs b/Boyfriend/Boyfriend.cs index f643729..ef1c5ab 100644 --- a/Boyfriend/Boyfriend.cs +++ b/Boyfriend/Boyfriend.cs @@ -45,18 +45,29 @@ public static class Boyfriend { try { config = await JsonSerializer.DeserializeAsync(openStream) ?? throw new Exception(); } catch (JsonException) { - config = new GuildConfig(guild.Id, "ru", "!", false); + config = new GuildConfig(guild.Id, "ru", "!", false, true, true, 0, 0, 0); } GuildConfigDictionary.Add(guild.Id, config); } } public static GuildConfig GetGuildConfig(IGuild guild) { - GuildConfig toReturn; - toReturn = GuildConfigDictionary.ContainsKey(guild.Id) ? GuildConfigDictionary[guild.Id] - : new GuildConfig(guild.Id, "ru", "!", false); + var toReturn = GuildConfigDictionary.ContainsKey(guild.Id) ? GuildConfigDictionary[guild.Id] + : new GuildConfig(guild.Id, "ru", "!", false, true, true, 0, 0, 0); if (toReturn.Id != guild.Id) throw new Exception(); return toReturn; } + + public static IGuild FindGuild(ITextChannel channel) { + foreach (var guild in Client.Guilds) { + if (guild.Channels.Any(x => x == channel)) return guild; + } + + throw new Exception("Не удалось найти сервер по каналу!"); + } + + public static void ThrowFatal(Exception e) { + throw e; + } } \ No newline at end of file diff --git a/Boyfriend/Commands/BanModule.cs b/Boyfriend/Commands/BanModule.cs index a89c1d5..cd1295b 100644 --- a/Boyfriend/Commands/BanModule.cs +++ b/Boyfriend/Commands/BanModule.cs @@ -12,13 +12,14 @@ public class BanModule : ModuleBase { [Command("ban")] [Summary("Банит пользователя")] [Alias("бан")] - public async Task Run(string user, string durationString, [Remainder]string reason) { + public async Task Run(string user, [Remainder]string reason) { TimeSpan duration; try { - duration = TimeSpan.Parse(durationString); + var reasonArray = reason.Split(); + duration = Utils.GetTimeSpan(reasonArray[0]); + reason = string.Join(" ", reasonArray.Skip(1)); } 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); @@ -35,8 +36,8 @@ public class BanModule : ModuleBase { var guildBanMessage = $"({author.Username}#{author.Discriminator}) {reason}"; await guild.AddBanAsync(toBan, 0, guildBanMessage); var notification = $"{authorMention} банит {toBan.Mention} за {Utils.WrapInline(reason)}"; - await Utils.SilentSendAsync(guild.GetSystemChannelAsync().Result, notification); - await Utils.SilentSendAsync(Utils.GetAdminLogChannel(), notification); + await Utils.SilentSendAsync(await guild.GetSystemChannelAsync(), notification); + await Utils.SilentSendAsync(await Utils.GetAdminLogChannel(guild), notification); var task = new Task(() => UnbanModule.UnbanUser(guild, guild.GetCurrentUserAsync().Result, toBan, "Время наказания истекло")); await Utils.StartDelayed(task, duration, () => guild.GetBanAsync(toBan).Result != null); diff --git a/Boyfriend/Commands/ClearModule.cs b/Boyfriend/Commands/ClearModule.cs index bd5f87f..94eade6 100644 --- a/Boyfriend/Commands/ClearModule.cs +++ b/Boyfriend/Commands/ClearModule.cs @@ -23,7 +23,7 @@ public class ClearModule : ModuleBase { default: { var messages = await channel.GetMessagesAsync(toDelete + 1).FlattenAsync(); await channel.DeleteMessagesAsync(messages); - await Utils.GetAdminLogChannel().SendMessageAsync( + await Utils.SilentSendAsync(await Utils.GetAdminLogChannel(Context.Guild), $"{Context.User.Mention} удаляет {toDelete + 1} сообщений в канале " + $"{Utils.MentionChannel(Context.Channel.Id)}"); break; diff --git a/Boyfriend/Commands/KickModule.cs b/Boyfriend/Commands/KickModule.cs index f45f0d0..67fb9fd 100644 --- a/Boyfriend/Commands/KickModule.cs +++ b/Boyfriend/Commands/KickModule.cs @@ -14,13 +14,13 @@ public class KickModule : ModuleBase { [Alias("кик")] 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; + var toKick = await Utils.ParseMember(Context.Guild, user); 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, IGuildUser author, IGuildUser toKick, string reason) { + private static async void KickMember(IGuild guild, IUser author, IGuildUser toKick, string reason) { var authorMention = author.Mention; await Utils.SendDirectMessage(toKick, $"Тебя кикнул {authorMention} на сервере {guild.Name} за " + $"{Utils.WrapInline(reason)}"); @@ -28,7 +28,7 @@ public class KickModule : ModuleBase { var guildKickMessage = $"({author.Username}#{author.Discriminator}) {reason}"; await toKick.KickAsync(guildKickMessage); var notification = $"{authorMention} выгоняет {toKick.Mention} за {Utils.WrapInline(reason)}"; - await Utils.SilentSendAsync(guild.GetSystemChannelAsync().Result, notification); - await Utils.SilentSendAsync(Utils.GetAdminLogChannel(), notification); + await Utils.SilentSendAsync(await guild.GetSystemChannelAsync(), notification); + await Utils.SilentSendAsync(await Utils.GetAdminLogChannel(guild), notification); } } \ No newline at end of file diff --git a/Boyfriend/Commands/MuteModule.cs b/Boyfriend/Commands/MuteModule.cs index 9d383c8..24a67d5 100644 --- a/Boyfriend/Commands/MuteModule.cs +++ b/Boyfriend/Commands/MuteModule.cs @@ -12,16 +12,21 @@ public class MuteModule : ModuleBase { [Command("mute")] [Summary("Глушит пользователя")] [Alias("мут")] - public async Task Run(string user, string durationString, [Remainder]string reason) { + public async Task Run(string user, [Remainder]string reason) { TimeSpan duration; try { - duration = TimeSpan.Parse(durationString); + var reasonArray = reason.Split(); + duration = Utils.GetTimeSpan(reasonArray[0]); + reason = string.Join(" ", reasonArray.Skip(1)); } 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); + if (toMute.RoleIds.Any(x => x == Utils.GetMuteRole(Context.Guild).Id)) + throw new Exception("Участник уже заглушен!"); + if (Boyfriend.GetGuildConfig(Context.Guild).RolesRemovedOnMute.ContainsKey(toMute.Id)) + throw new Exception("Кто-то убрал роль мута самостоятельно!"); 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); @@ -32,17 +37,25 @@ public class MuteModule : ModuleBase { 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); + var config = Boyfriend.GetGuildConfig(guild); - } + if (config.RemoveRolesOnMute) { + var rolesRemoved = new List(); + try { + foreach (var roleId in toMute.RoleIds) { + if (roleId == guild.Id) continue; + await toMute.RemoveRoleAsync(roleId); + rolesRemoved.Add(roleId); + } + } catch (NullReferenceException) {} + config.RolesRemovedOnMute.Add(toMute.Id, rolesRemoved); + config.Save(); } await toMute.AddRoleAsync(role); var notification = $"{authorMention} глушит {toMute.Mention} за {Utils.WrapInline(reason)}"; - await Utils.SilentSendAsync(guild.GetSystemChannelAsync().Result, notification); - await Utils.SilentSendAsync(Utils.GetAdminLogChannel(), notification); + await Utils.SilentSendAsync(await guild.GetSystemChannelAsync(), notification); + await Utils.SilentSendAsync(await Utils.GetAdminLogChannel(guild), notification); var task = new Task(() => UnmuteModule.UnmuteMember(guild, guild.GetCurrentUserAsync().Result, toMute, "Время наказания истекло")); await Utils.StartDelayed(task, duration, () => toMute.RoleIds.Any(x => x == role.Id)); diff --git a/Boyfriend/Commands/SettingsModule.cs b/Boyfriend/Commands/SettingsModule.cs index a528bbf..dd25c56 100644 --- a/Boyfriend/Commands/SettingsModule.cs +++ b/Boyfriend/Commands/SettingsModule.cs @@ -1,4 +1,5 @@ -using Discord.Commands; +using Discord; +using Discord.Commands; // ReSharper disable UnusedType.Global // ReSharper disable UnusedMember.Global @@ -10,37 +11,105 @@ public class SettingsModule : ModuleBase { [Summary("Настраивает бота")] [Alias("config", "настройки", "конфиг")] public async Task Run([Remainder] string s = "") { + await CommandHandler.CheckPermissions(Context.Guild.GetUser(Context.User.Id), GuildPermission.ManageGuild); var config = Boyfriend.GetGuildConfig(Context.Guild); var sArray = s.Split(" "); + var guild = Context.Guild; if (s == "") { var nl = Environment.NewLine; - await Context.Channel.SendMessageAsync($"Текущие настройки:{nl}Язык: `{config.Lang}`" + - $"{nl}Префикс: `{config.Prefix}`" + - $"{nl}Удалять роли при муте: " + - $"{(config.RemoveRolesOnMute ? "Да" : "Нет")}"); + var adminLogChannel = guild.GetTextChannel(config.AdminLogChannel); + var admin = adminLogChannel == null ? "Не указан" : adminLogChannel.Mention; + var botLogChannel = guild.GetTextChannel(config.BotLogChannel); + var bot = botLogChannel == null ? "Не указан" : botLogChannel.Mention; + var muteRole = guild.GetRole(config.MuteRole); + var mute = muteRole == null ? "Не указана" : muteRole.Mention; + var toSend = $"Текущие настройки:{nl}" + + $"Язык (`lang`): `{config.Lang}`{nl}" + + $"Префикс (`prefix`): `{config.Prefix}`{nl}" + + $"Удалять роли при муте (`removeRolesOnMute`): {YesOrNo(config.RemoveRolesOnMute)}{nl}" + + "Использовать канал системных сообщений для уведомлений (`useSystemChannel`): " + + $"{YesOrNo(config.UseSystemChannel)}{nl}" + + $"Отправлять приветствия (`sendWelcomeMessages`): {YesOrNo(config.UseSystemChannel)}{nl}" + + $"Роль мута (`muteRole`): {mute}{nl}" + + $"Канал админ-уведомлений (`adminLogChannel`): " + + $"{admin}{nl}" + + $"Канал бот-уведомлений (`botLogChannel`): " + + $"{bot}"; + await Utils.SilentSendAsync(Context.Channel as ITextChannel ?? throw new Exception(), toSend); return; } - if (sArray[0].ToLower() == "lang") { - if (sArray[1].ToLower() != "ru") throw new Exception("Язык не поддерживается!"); - config.Lang = sArray[1].ToLower(); + var setting = sArray[0].ToLower(); + var value = sArray[1].ToLower(); + + ITextChannel? channel; + try { + channel = await Utils.ParseChannel(value) as ITextChannel; + } catch (FormatException) { + channel = null; } + IRole? role; + try { + role = Utils.ParseRole(guild, value); + } + catch (FormatException) { + role = null; + } - if (sArray[0].ToLower() == "prefix") - config.Prefix = sArray[1]; + var boolValue = ParseBool(sArray[1]); - if (sArray[0].ToLower() == "removerolesonmute") { - try { - config.RemoveRolesOnMute = bool.Parse(sArray[1].ToLower()); - } catch (FormatException) { - await Context.Channel.SendMessageAsync("Неверный параметр! Требуется `true` или `false`"); - return; - } + switch (setting) { + case "lang" when sArray[1].ToLower() != "ru": + throw new Exception("Язык не поддерживается!"); + case "lang": + config.Lang = value; + break; + case "prefix": + config.Prefix = value; + break; + case "removerolesonmute": + config.RemoveRolesOnMute = boolValue ?? + throw new Exception("Неверный параметр! Требуется `true` или `false"); + break; + case "usesystemchannel": + config.UseSystemChannel = boolValue ?? + throw new Exception("Неверный параметр! Требуется `true` или `false"); + break; + case "sendwelcomemessages": + config.SendWelcomeMessages = boolValue ?? + throw new Exception("Неверный параметр! Требуется `true` или `false"); + break; + case "adminlogchannel": + config.AdminLogChannel = Convert.ToUInt64((channel ?? + throw new Exception("Указан недействительный канал!")) + .Id); + break; + case "botlogchannel": + config.BotLogChannel = Convert.ToUInt64((channel ?? + throw new Exception("Указан недействительный канал!")) + .Id); + break; + case "muterole": + config.MuteRole = Convert.ToUInt64((role ?? throw new Exception("Указана недействительная роль!")) + .Id); + break; } config.Save(); await Context.Channel.SendMessageAsync("Настройки успешно обновлены!"); } + + private static bool? ParseBool(string toParse) { + try { + return bool.Parse(toParse.ToLower()); + } catch (FormatException) { + return null; + } + } + + private static string YesOrNo(bool isYes) { + return isYes ? "Да" : "Нет"; + } } \ No newline at end of file diff --git a/Boyfriend/Commands/UnbanModule.cs b/Boyfriend/Commands/UnbanModule.cs index 57039db..33b5902 100644 --- a/Boyfriend/Commands/UnbanModule.cs +++ b/Boyfriend/Commands/UnbanModule.cs @@ -11,12 +11,11 @@ public class UnbanModule : ModuleBase { [Command("unban")] [Summary("Возвращает пользователя из бана")] [Alias("разбан")] - public Task Run(string user, [Remainder] string reason) { - var toUnban = Utils.ParseUser(user).Result; + public async Task Run(string user, [Remainder] string reason) { + var toUnban = await Utils.ParseUser(user); 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, IGuildUser author, IUser toUnban, string reason) { @@ -24,7 +23,7 @@ public class UnbanModule : ModuleBase { var authorMention = author.Mention; var notification = $"{authorMention} возвращает из бана {toUnban.Mention} за {Utils.WrapInline(reason)}"; await guild.RemoveBanAsync(toUnban); - await Utils.SilentSendAsync(guild.GetSystemChannelAsync().Result, notification); - await Utils.SilentSendAsync(Utils.GetAdminLogChannel(), notification); + await Utils.SilentSendAsync(await guild.GetSystemChannelAsync(), notification); + await Utils.SilentSendAsync(await Utils.GetAdminLogChannel(guild), notification); } } \ No newline at end of file diff --git a/Boyfriend/Commands/UnmuteModule.cs b/Boyfriend/Commands/UnmuteModule.cs index 0e81805..9baee78 100644 --- a/Boyfriend/Commands/UnmuteModule.cs +++ b/Boyfriend/Commands/UnmuteModule.cs @@ -12,12 +12,17 @@ public class UnmuteModule : ModuleBase { [Summary("Возвращает пользователя из мута")] [Alias("размут")] public async Task Run(string user, [Remainder] string reason) { - var toUnmute = Utils.ParseMember(Context.Guild, user).Result; + var toUnmute = await Utils.ParseMember(Context.Guild, user); 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("Пользователь не в муте!"); + if (toUnmute.RoleIds.All(x => x != Utils.GetMuteRole(Context.Guild).Id)) { + var rolesRemoved = Boyfriend.GetGuildConfig(Context.Guild).RolesRemovedOnMute; + if (!rolesRemoved.ContainsKey(toUnmute.Id)) throw new Exception("Пользователь не в муте!"); + rolesRemoved.Remove(toUnmute.Id); + throw new Exception("Пользователь не в муте, но я нашёл и удалил запись о его удалённых ролях!"); + } + UnmuteMember(Context.Guild, Context.Guild.GetUser(Context.User.Id), toUnmute, reason); } @@ -26,7 +31,16 @@ public class UnmuteModule : ModuleBase { var authorMention = author.Mention; var notification = $"{authorMention} возвращает из мута {toUnmute.Mention} за {Utils.WrapInline(reason)}"; await toUnmute.RemoveRoleAsync(Utils.GetMuteRole(guild)); - await Utils.SilentSendAsync(guild.GetSystemChannelAsync().Result, notification); - await Utils.SilentSendAsync(Utils.GetAdminLogChannel(), notification); + var config = Boyfriend.GetGuildConfig(guild); + + if (config.RolesRemovedOnMute.ContainsKey(toUnmute.Id)) { + foreach (var roleId in config.RolesRemovedOnMute[toUnmute.Id]) { + await toUnmute.AddRoleAsync(roleId); + } + config.RolesRemovedOnMute.Remove(toUnmute.Id); + } + + await Utils.SilentSendAsync(await guild.GetSystemChannelAsync(), notification); + await Utils.SilentSendAsync(await Utils.GetAdminLogChannel(guild), notification); } } \ No newline at end of file diff --git a/Boyfriend/EventHandler.cs b/Boyfriend/EventHandler.cs index 1ab8dd8..05d6fb2 100644 --- a/Boyfriend/EventHandler.cs +++ b/Boyfriend/EventHandler.cs @@ -19,23 +19,27 @@ public class EventHandler { 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 Exception("Invalid bot log channel"); - await botLogChannel.SendMessageAsync($"{Utils.GetBeep()}Я запустился! (C#)"); - + private static async Task ReadyEvent() { await Boyfriend.SetupGuildConfigs(); + + foreach (var guild in Boyfriend.Client.Guilds) { + var channel = guild.GetTextChannel(Boyfriend.GetGuildConfig(guild).BotLogChannel); + if (channel == null) continue; + await channel.SendMessageAsync($"{Utils.GetBeep()}Я запустился! (C#)"); + } } private static async Task MessageDeletedEvent(Cacheable message, Cacheable channel) { var msg = message.Value; var toSend = msg == null - ? "Удалено сообщение в канале {Utils.MentionChannel(channel.Id)}, но я забыл что там было" + ? $"Удалено сообщение в канале {Utils.MentionChannel(channel.Id)}, но я забыл что там было" : $"Удалено сообщение от {msg.Author.Mention} в канале " + $"{Utils.MentionChannel(channel.Id)}: {Environment.NewLine}{Utils.Wrap(msg.Content)}"; - await Utils.SilentSendAsync(Utils.GetAdminLogChannel(), toSend); + try { + await Utils.SilentSendAsync(await Utils.GetAdminLogChannel( + Boyfriend.FindGuild(channel.Value as ITextChannel)), toSend); + } catch (ArgumentException) {} } private static async Task MessageReceivedEvent(SocketMessage messageParam) { @@ -46,15 +50,17 @@ public class EventHandler { if ((message.MentionedUsers.Count > 3 || message.MentionedRoles.Count > 2) && !user.GuildPermissions.MentionEveryone) - BanModule.BanUser(guild, guild.GetCurrentUserAsync().Result, user, TimeSpan.FromMilliseconds(-1), + BanModule.BanUser(guild, await guild.GetCurrentUserAsync(), user, TimeSpan.FromMilliseconds(-1), "Более 3-ёх упоминаний в одном сообщении"); 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.Channel is not ITextChannel channel) throw new Exception(); if (!(message.HasStringPrefix(Boyfriend.GetGuildConfig(guild).Prefix, ref argPos) || message.HasMentionPrefix(Boyfriend.Client.CurrentUser, ref argPos)) + || user == await Boyfriend.FindGuild(channel).GetCurrentUserAsync() || user.IsBot && message.Content.Contains(prev) || message.Content.Contains(prevFailsafe)) return; @@ -73,7 +79,10 @@ public class EventHandler { : $"Отредактировано сообщение от {msg.Author.Mention} " + $"в канале {Utils.MentionChannel(channel.Id)}." + $"{nl}До:{nl}{Utils.Wrap(msg.Content)}{nl}После:{nl}{Utils.Wrap(messageSocket.Content)}"; - await Utils.SilentSendAsync(Utils.GetAdminLogChannel(), toSend); + try { + await Utils.SilentSendAsync(await Utils.GetAdminLogChannel(Boyfriend.FindGuild(channel as ITextChannel)), + toSend); + } catch (ArgumentException) {} } private static async Task UserJoinedEvent(SocketGuildUser user) { diff --git a/Boyfriend/GuildConfig.cs b/Boyfriend/GuildConfig.cs index c9a6c26..80490de 100644 --- a/Boyfriend/GuildConfig.cs +++ b/Boyfriend/GuildConfig.cs @@ -7,12 +7,25 @@ public class GuildConfig { public string Lang { get; set; } public string Prefix { get; set; } public bool RemoveRolesOnMute { get; set; } + public bool UseSystemChannel { get; set; } + public bool SendWelcomeMessages { get; set; } + public ulong MuteRole { get; set; } + public ulong AdminLogChannel { get; set; } + public ulong BotLogChannel { get; set; } + public Dictionary> RolesRemovedOnMute { get; set; } - public GuildConfig(ulong id, string lang, string prefix, bool removeRolesOnMute) { + public GuildConfig(ulong id, string lang, string prefix, bool removeRolesOnMute, bool useSystemChannel, + bool sendWelcomeMessages, ulong muteRole, ulong adminLogChannel, ulong botLogChannel) { Id = id; Lang = lang; Prefix = prefix; RemoveRolesOnMute = removeRolesOnMute; + UseSystemChannel = useSystemChannel; + SendWelcomeMessages = sendWelcomeMessages; + MuteRole = muteRole; + AdminLogChannel = adminLogChannel; + BotLogChannel = botLogChannel; + RolesRemovedOnMute = new Dictionary>(); } public async void Save() { diff --git a/Boyfriend/Utils.cs b/Boyfriend/Utils.cs index 3ff7c4a..2c9ad4b 100644 --- a/Boyfriend/Utils.cs +++ b/Boyfriend/Utils.cs @@ -1,4 +1,5 @@ -using System.Text.RegularExpressions; +using System.Globalization; +using System.Text.RegularExpressions; using Discord; using Discord.Net; @@ -6,15 +7,16 @@ namespace Boyfriend; public static class Utils { public static string GetBeep() { - var letters = new[] { "а", "о", "и"}; + var letters = new[] {"а", "о", "и"}; return $"Б{letters[new Random().Next(3)]}п! "; } - [Obsolete("Stop hard-coding things!")] - public static ITextChannel GetAdminLogChannel() { - if (Boyfriend.Client.GetChannel(870929165141032971) is not ITextChannel adminLogChannel) - throw new Exception("Invalid admin log channel"); - return adminLogChannel; + public static async Task GetAdminLogChannel(IGuild guild) { + var adminLogChannel = await ParseChannel(Boyfriend.GetGuildConfig(guild).AdminLogChannel.ToString()); + if (adminLogChannel is ITextChannel channel) + return channel; + + throw new Exception("Неверный канал админ-логов для гильдии " + guild.Id); } public static string Wrap(string original) { @@ -50,6 +52,14 @@ public static class Utils { return await guild.GetUserAsync(ParseMention(mention)); } + public static async Task ParseChannel(string mention) { + return await Boyfriend.Client.GetChannelAsync(ParseMention(mention)); + } + + public static IRole ParseRole(IGuild guild, string mention) { + return guild.GetRole(ParseMention(mention)); + } + public static async Task SendDirectMessage(IUser user, string toSend) { try { await user.SendMessageAsync(toSend); @@ -60,12 +70,23 @@ public static class Utils { } public static IRole GetMuteRole(IGuild guild) { - var role = guild.Roles.FirstOrDefault(x => x.Name.ToLower() is "заключённый" or "muted"); - if (role == null) throw new Exception("Не удалось найти роль мута"); + var role = guild.Roles.FirstOrDefault(x => x.Id == Boyfriend.GetGuildConfig(guild).MuteRole); + if (role == null) throw new Exception("Требуется указать роль мута в настройках!"); return role; } public static async Task SilentSendAsync(ITextChannel channel, string text) { - await channel.SendMessageAsync(text, false, null, null, AllowedMentions.None); + try { + await channel.SendMessageAsync(text, false, null, null, AllowedMentions.None); + } catch (ArgumentException) {} + } + + private static readonly string[] Formats = { + "%d'd'%h'h'%m'm'%s's'", "%d'd'%h'h'%m'm'", "%d'd'%h'h'%s's'", "%d'd'%h'h'", "%d'd'%m'm'%s's'", "%d'd'%m'm'", + "%d'd'%s's'", "%d'd'", "%h'h'%m'm'%s's'", "%h'h'%m'm'", "%h'h'%s's'", "%h'h'", "%m'm'%s's'", "%m'm'", "%s's'" + }; + public static TimeSpan GetTimeSpan(string from) { + return TimeSpan.ParseExact(from.ToLowerInvariant(), Formats, + CultureInfo.InvariantCulture); } } \ No newline at end of file