1
0
Fork 1
mirror of https://github.com/TeamOctolings/Octobot.git synced 2025-05-04 21:16:29 +03:00

ton of stuff

- new command handler
- multilanguage support
- time out support
- responses
- a ton of stuff
This commit is contained in:
l1ttleO 2022-01-18 22:38:15 +05:00
parent 1c9caf6d75
commit f30485dd71
Signed by: Octol1ttle
GPG key ID: B77C34313AEE1FFF
29 changed files with 1686 additions and 520 deletions

View file

@ -0,0 +1,61 @@
using Discord;
using Discord.Commands;
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable ClassNeverInstantiated.Global
namespace Boyfriend.Commands;
public class BanCommand : Command {
public override async Task Run(SocketCommandContext context, string[] args) {
var toBan = await Utils.ParseUser(args[0]);
var reason = Utils.JoinString(args, 1);
TimeSpan duration;
try {
duration = Utils.GetTimeSpan(args[1]);
reason = Utils.JoinString(args, 2);
}
catch (Exception e) when (e is ArgumentNullException or FormatException or OverflowException) {
duration = TimeSpan.FromMilliseconds(-1);
}
var author = context.Guild.GetUser(context.User.Id);
await CommandHandler.CheckPermissions(author, GuildPermission.BanMembers);
var memberToBan = context.Guild.GetUser(toBan.Id);
if (memberToBan != null)
await CommandHandler.CheckInteractions(author, memberToBan);
await BanUser(context.Guild, context.Channel as ITextChannel, context.Guild.GetUser(context.User.Id),
toBan, duration, reason);
}
public static async Task BanUser(IGuild guild, ITextChannel? channel, IGuildUser author, IUser toBan,
TimeSpan duration, string reason) {
var authorMention = author.Mention;
await Utils.SendDirectMessage(toBan, string.Format(Messages.YouWereBanned, author.Mention, guild.Name,
Utils.WrapInline(reason)));
var guildBanMessage = $"({author.Username}#{author.Discriminator}) {reason}";
await guild.AddBanAsync(toBan, 0, guildBanMessage);
var notification = string.Format(Messages.UserBanned, authorMention, toBan.Mention, Utils.WrapInline(reason));
await Utils.SilentSendAsync(channel, string.Format(Messages.BanResponse, toBan.Mention,
Utils.WrapInline(reason)));
await Utils.SilentSendAsync(await guild.GetSystemChannelAsync(), notification);
await Utils.SilentSendAsync(await Utils.GetAdminLogChannel(guild), notification);
var task = new Task(() => UnbanCommand.UnbanUser(guild, null, guild.GetCurrentUserAsync().Result, toBan,
Messages.PunishmentExpired));
await Utils.StartDelayed(task, duration, () => guild.GetBanAsync(toBan).Result != null);
}
public override List<string> GetAliases() {
return new List<string> {"ban", "бан"};
}
public override int GetArgumentsAmountRequired() {
return 2;
}
public override string GetSummary() {
return "Банит пользователя";
}
}

View file

@ -1,45 +0,0 @@
using Discord;
using Discord.Commands;
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable ClassNeverInstantiated.Global
namespace Boyfriend.Commands;
public class BanModule : ModuleBase<SocketCommandContext> {
[Command("ban")]
[Summary("Банит пользователя")]
[Alias("бан")]
public async Task Run(string user, [Remainder]string reason) {
TimeSpan duration;
try {
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);
}
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, 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)}";
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);
}
}

View file

@ -0,0 +1,49 @@
using Discord;
using Discord.Commands;
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable ClassNeverInstantiated.Global
namespace Boyfriend.Commands;
public class ClearCommand : Command {
public override async Task Run(SocketCommandContext context, string[] args) {
int toDelete;
try {
toDelete = Convert.ToInt32(args[0]);
}
catch (Exception e) when (e is FormatException or OverflowException) {
throw new ApplicationException(Messages.ClearInvalidAmountSpecified);
}
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 ApplicationException(Messages.ClearNegativeAmount);
case > 200:
throw new ApplicationException(Messages.ClearAmountTooLarge);
default: {
var messages = await channel.GetMessagesAsync(toDelete + 1).FlattenAsync();
await channel.DeleteMessagesAsync(messages);
await Utils.SilentSendAsync(await Utils.GetAdminLogChannel(context.Guild),
string.Format(Messages.MessagesDeleted, context.User.Mention, toDelete + 1,
Utils.MentionChannel(context.Channel.Id)));
break;
}
}
}
public override List<string> GetAliases() {
return new List<string> {"clear", "purge", "очистить", "стереть"};
}
public override int GetArgumentsAmountRequired() {
return 1;
}
public override string GetSummary() {
return "Очищает сообщения";
}
}

View file

@ -1,33 +0,0 @@
using Discord;
using Discord.Commands;
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable ClassNeverInstantiated.Global
namespace Boyfriend.Commands;
public class ClearModule : ModuleBase<SocketCommandContext> {
[Command("clear")]
[Summary("Удаляет указанное количество сообщений")]
[Alias("очистить")]
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 Exception( "Указано отрицательное количество сообщений!");
case > 200:
throw new Exception("Указано слишком много сообщений!");
default: {
var messages = await channel.GetMessagesAsync(toDelete + 1).FlattenAsync();
await channel.DeleteMessagesAsync(messages);
await Utils.SilentSendAsync(await Utils.GetAdminLogChannel(Context.Guild),
$"{Context.User.Mention} удаляет {toDelete + 1} сообщений в канале " +
$"{Utils.MentionChannel(Context.Channel.Id)}");
break;
}
}
}
}

View file

@ -0,0 +1,19 @@
using Discord;
using Discord.Commands;
using Discord.WebSocket;
namespace Boyfriend.Commands;
public abstract class Command {
public abstract Task Run(SocketCommandContext context, string[] args);
public abstract List<string> GetAliases();
public abstract int GetArgumentsAmountRequired();
public abstract string GetSummary();
protected static async Task Warn(ISocketMessageChannel channel, string warning) {
await Utils.SilentSendAsync(channel as ITextChannel, ":warning: " + warning);
}
}

View file

@ -0,0 +1,30 @@
using Discord.Commands;
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
namespace Boyfriend.Commands;
public class HelpCommand : Command {
public override async Task Run(SocketCommandContext context, string[] args) {
var nl = Environment.NewLine;
var toSend = string.Format(Messages.CommandHelp, nl);
var prefix = Boyfriend.GetGuildConfig(context.Guild).Prefix;
toSend = CommandHandler.Commands.Aggregate(toSend,
(current, command) => current + $"`{prefix}{command.GetAliases()[0]}`: {command.GetSummary()}{nl}");
await context.Channel.SendMessageAsync(toSend);
}
public override List<string> GetAliases() {
return new List<string> {"help", "помощь", "справка"};
}
public override int GetArgumentsAmountRequired() {
return 0;
}
public override string GetSummary() {
return "Показывает эту справку";
}
}

View file

@ -1,25 +0,0 @@
using Discord.Commands;
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
namespace Boyfriend.Commands;
public class HelpModule : ModuleBase<SocketCommandContext> {
[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;
}
}

View file

@ -0,0 +1,47 @@
using Discord;
using Discord.Commands;
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable ClassNeverInstantiated.Global
namespace Boyfriend.Commands;
public class KickCommand : Command {
public override async Task Run(SocketCommandContext context, string[] args) {
var reason = Utils.JoinString(args, 1);
var author = context.Guild.GetUser(context.User.Id);
var toKick = await Utils.ParseMember(context.Guild, args[0]);
await CommandHandler.CheckPermissions(author, GuildPermission.KickMembers);
await CommandHandler.CheckInteractions(author, toKick);
KickMember(context.Guild, context.Channel as ITextChannel, context.Guild.GetUser(context.User.Id), toKick,
reason);
}
private static async void KickMember(IGuild guild, ITextChannel? channel, IUser author, IGuildUser toKick,
string reason) {
var authorMention = author.Mention;
await Utils.SendDirectMessage(toKick, string.Format(Messages.YouWereKicked, authorMention, guild.Name,
Utils.WrapInline(reason)));
var guildKickMessage = $"({author.Username}#{author.Discriminator}) {reason}";
await toKick.KickAsync(guildKickMessage);
var notification = string.Format(Messages.MemberKicked, authorMention, toKick.Mention,
Utils.WrapInline(reason));
await Utils.SilentSendAsync(channel, string.Format(Messages.KickResponse, toKick.Mention,
Utils.WrapInline(reason)));
await Utils.SilentSendAsync(await guild.GetSystemChannelAsync(), notification);
await Utils.SilentSendAsync(await Utils.GetAdminLogChannel(guild), notification);
}
public override List<string> GetAliases() {
return new List<string> {"kick", "кик"};
}
public override int GetArgumentsAmountRequired() {
return 2;
}
public override string GetSummary() {
return "Выгоняет участника";
}
}

View file

@ -1,34 +0,0 @@
using Discord;
using Discord.Commands;
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable ClassNeverInstantiated.Global
namespace Boyfriend.Commands;
public class KickModule : ModuleBase<SocketCommandContext> {
[Command("kick")]
[Summary("Выгоняет пользователя")]
[Alias("кик")]
public async Task Run(string user, [Remainder]string reason) {
var author = Context.Guild.GetUser(Context.User.Id);
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, IUser author, IGuildUser toKick, string reason) {
var authorMention = author.Mention;
await Utils.SendDirectMessage(toKick, $"Тебя кикнул {authorMention} на сервере {guild.Name} за " +
$"{Utils.WrapInline(reason)}");
var guildKickMessage = $"({author.Username}#{author.Discriminator}) {reason}";
await toKick.KickAsync(guildKickMessage);
var notification = $"{authorMention} выгоняет {toKick.Mention} за {Utils.WrapInline(reason)}";
await Utils.SilentSendAsync(await guild.GetSystemChannelAsync(), notification);
await Utils.SilentSendAsync(await Utils.GetAdminLogChannel(guild), notification);
}
}

View file

@ -0,0 +1,92 @@
using Discord;
using Discord.Commands;
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable ClassNeverInstantiated.Global
namespace Boyfriend.Commands;
public class MuteCommand : Command {
public override async Task Run(SocketCommandContext context, string[] args) {
TimeSpan duration;
var reason = Utils.JoinString(args, 1);
try {
duration = Utils.GetTimeSpan(args[1]);
reason = Utils.JoinString(args, 2);
}
catch (Exception e) when (e is ArgumentNullException or FormatException or OverflowException) {
duration = TimeSpan.FromMilliseconds(-1);
}
var author = context.Guild.GetUser(context.User.Id);
var toMute = await Utils.ParseMember(context.Guild, args[0]);
if (toMute == null)
throw new ApplicationException(Messages.UserNotInGuild);
var role = Utils.GetMuteRole(context.Guild);
if (role != null && toMute.RoleIds.Any(x => x == role.Id) ||
toMute.TimedOutUntil != null && toMute.TimedOutUntil.Value.ToUnixTimeMilliseconds()
> DateTimeOffset.Now.ToUnixTimeMilliseconds())
throw new ApplicationException(Messages.MemberAlreadyMuted);
var rolesRemoved = Boyfriend.GetGuildConfig(context.Guild).RolesRemovedOnMute;
if (rolesRemoved.ContainsKey(toMute.Id)) {
foreach (var roleId in rolesRemoved[toMute.Id]) await toMute.AddRoleAsync(roleId);
rolesRemoved.Remove(toMute.Id);
await Warn(context.Channel, Messages.RolesReturned);
return;
}
await CommandHandler.CheckPermissions(author, GuildPermission.ManageMessages, GuildPermission.ManageRoles);
await CommandHandler.CheckInteractions(author, toMute);
MuteMember(context.Guild, context.Channel as ITextChannel, context.Guild.GetUser(context.User.Id), toMute,
duration, reason);
}
private static async void MuteMember(IGuild guild, ITextChannel? channel, 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);
var config = Boyfriend.GetGuildConfig(guild);
if (config.RemoveRolesOnMute && role != null) {
var rolesRemoved = new List<ulong>();
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);
await config.Save();
}
if (role != null)
await toMute.AddRoleAsync(role);
else
await toMute.SetTimeOutAsync(duration);
var notification = string.Format(Messages.MemberMuted, authorMention, toMute.Mention, Utils.WrapInline(reason));
await Utils.SilentSendAsync(channel, string.Format(Messages.MuteResponse, toMute.Mention,
Utils.WrapInline(reason)));
await Utils.SilentSendAsync(await guild.GetSystemChannelAsync(), notification);
await Utils.SilentSendAsync(await Utils.GetAdminLogChannel(guild), notification);
var task = new Task(() => UnmuteCommand.UnmuteMember(guild, null, guild.GetCurrentUserAsync().Result, toMute,
Messages.PunishmentExpired));
if (role != null)
await Utils.StartDelayed(task, duration, () => toMute.RoleIds.Any(x => x == role.Id));
}
public override List<string> GetAliases() {
return new List<string> {"mute", "мут", "мьют"};
}
public override int GetArgumentsAmountRequired() {
return 2;
}
public override string GetSummary() {
return "Глушит участника";
}
}

View file

@ -1,63 +0,0 @@
using Discord;
using Discord.Commands;
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable ClassNeverInstantiated.Global
namespace Boyfriend.Commands;
public class MuteModule : ModuleBase<SocketCommandContext> {
[Command("mute")]
[Summary("Глушит пользователя")]
[Alias("мут")]
public async Task Run(string user, [Remainder]string reason) {
TimeSpan duration;
try {
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);
}
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);
}
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);
var config = Boyfriend.GetGuildConfig(guild);
if (config.RemoveRolesOnMute) {
var rolesRemoved = new List<ulong>();
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(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));
}
}

View file

@ -0,0 +1,25 @@
using Discord.Commands;
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
namespace Boyfriend.Commands;
public class PingCommand : Command {
public override async Task Run(SocketCommandContext context, string[] args) {
await context.Channel.SendMessageAsync($"{Utils.GetBeep(Boyfriend.GetGuildConfig(context.Guild).Lang)}" +
$"{Boyfriend.Client.Latency}{Messages.Milliseconds}");
}
public override List<string> GetAliases() {
return new List<string> {"ping", "пинг", "задержка"};
}
public override int GetArgumentsAmountRequired() {
return 0;
}
public override string GetSummary() {
return "Измеряет время обработки REST-запроса";
}
}

View file

@ -1,14 +0,0 @@
using Discord.Commands;
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
namespace Boyfriend.Commands;
public class PingModule : ModuleBase<SocketCommandContext> {
[Command("ping")]
[Summary("Измеряет время обработки REST-запроса")]
[Alias("пинг")]
public async Task Run()
=> await ReplyAsync($"{Utils.GetBeep()}{Boyfriend.Client.Latency}мс");
}

View file

@ -0,0 +1,125 @@
using System.Globalization;
using Discord;
using Discord.Commands;
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
namespace Boyfriend.Commands;
public class SettingsCommand : Command {
public override async Task Run(SocketCommandContext context, string[] args) {
await CommandHandler.CheckPermissions(context.Guild.GetUser(context.User.Id), GuildPermission.ManageGuild);
var config = Boyfriend.GetGuildConfig(context.Guild);
var guild = context.Guild;
if (args.Length == 0) {
var nl = Environment.NewLine;
var adminLogChannel = guild.GetTextChannel(config.AdminLogChannel);
var admin = adminLogChannel == null ? Messages.ChannelNotSpecified : adminLogChannel.Mention;
var botLogChannel = guild.GetTextChannel(config.BotLogChannel);
var bot = botLogChannel == null ? Messages.ChannelNotSpecified : botLogChannel.Mention;
var muteRole = guild.GetRole(config.MuteRole);
var mute = muteRole == null ? Messages.RoleNotSpecified : muteRole.Mention;
var defaultRole = guild.GetRole(config.DefaultRole);
var defaultr = muteRole == null ? Messages.RoleNotSpecified : defaultRole.Mention;
var toSend = string.Format(Messages.CurrentSettings, nl) +
string.Format(Messages.CurrentSettingsLang, config.Lang, nl) +
string.Format(Messages.CurrentSettingsPrefix, config.Prefix, nl) +
string.Format(Messages.CurrentSettingsRemoveRoles, YesOrNo(config.RemoveRolesOnMute), nl) +
string.Format(Messages.CurrentSettingsUseSystemChannel, YesOrNo(config.UseSystemChannel), nl) +
string.Format(Messages.CurrentSettingsSendWelcomeMessages, YesOrNo(config.UseSystemChannel),
nl) +
string.Format(Messages.CurrentSettingsWelcomeMessage, config.WelcomeMessage, nl) +
string.Format(Messages.CurrentSettingsDefaultRole, defaultr, nl) +
string.Format(Messages.CurrentSettingsMuteRole, mute, nl) +
string.Format(Messages.CurrentSettingsAdminLogChannel, admin, nl) +
string.Format(Messages.CurrentSettingsBotLogChannel, bot);
await Utils.SilentSendAsync(context.Channel as ITextChannel ?? throw new Exception(), toSend);
return;
}
var setting = args[0].ToLower();
var value = args[1].ToLower();
var boolValue = ParseBool(args[1]);
var channel = await Utils.ParseChannelNullable(value) as IGuildChannel;
var role = Utils.ParseRoleNullable(guild, value);
switch (setting) {
case "lang" when value is not ("ru" or "en"):
throw new Exception(Messages.LanguageNotSupported);
case "lang":
config.Lang = value;
Messages.Culture = new CultureInfo(value);
break;
case "prefix":
config.Prefix = value;
break;
case "removerolesonmute":
config.RemoveRolesOnMute = GetBoolValue(boolValue);
break;
case "usesystemchannel":
config.UseSystemChannel = GetBoolValue(boolValue);
break;
case "sendwelcomemessages":
config.SendWelcomeMessages = GetBoolValue(boolValue);
break;
case "welcomemessage":
config.WelcomeMessage = value;
break;
case "defaultrole":
config.DefaultRole = GetRoleId(role);
break;
case "muterole":
config.MuteRole = GetRoleId(role);
break;
case "adminlogchannel":
config.AdminLogChannel = GetChannelId(channel);
break;
case "botlogchannel":
config.BotLogChannel = GetChannelId(channel);
break;
}
await config.Save();
await context.Channel.SendMessageAsync(Messages.SettingsUpdated);
}
private static bool? ParseBool(string toParse) {
try {
return bool.Parse(toParse.ToLower());
}
catch (FormatException) {
return null;
}
}
private static bool GetBoolValue(bool? from) {
return from ?? throw new Exception(Messages.InvalidBoolean);
}
private static ulong GetRoleId(IRole? role) {
return (role ?? throw new Exception(Messages.InvalidRoleSpecified)).Id;
}
private static ulong GetChannelId(IGuildChannel? channel) {
return (channel ?? throw new Exception(Messages.InvalidChannelSpecified)).Id;
}
private static string YesOrNo(bool isYes) {
return isYes ? Messages.Yes : Messages.No;
}
public override List<string> GetAliases() {
return new List<string> {"settings", "настройки", "config", "конфиг "};
}
public override int GetArgumentsAmountRequired() {
return 0;
}
public override string GetSummary() {
return "Настраивает бота отдельно для этого сервера";
}
}

View file

@ -1,115 +0,0 @@
using Discord;
using Discord.Commands;
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
namespace Boyfriend.Commands;
public class SettingsModule : ModuleBase<SocketCommandContext> {
[Command("settings")]
[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;
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;
}
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;
}
var boolValue = ParseBool(sArray[1]);
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 ? "Да" : "Нет";
}
}

View file

@ -0,0 +1,43 @@
using Discord;
using Discord.Commands;
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable ClassNeverInstantiated.Global
namespace Boyfriend.Commands;
public class UnbanCommand : Command {
public override async Task Run(SocketCommandContext context, string[] args) {
var toUnban = await Utils.ParseUser(args[0]);
if (context.Guild.GetBanAsync(toUnban.Id) == null)
throw new Exception(Messages.UserNotBanned);
UnbanUser(context.Guild, context.Channel as ITextChannel, context.Guild.GetUser(context.User.Id), toUnban,
Utils.JoinString(args, 1));
}
public static async void UnbanUser(IGuild guild, ITextChannel? channel, IGuildUser author, IUser toUnban,
string reason) {
await CommandHandler.CheckPermissions(author, GuildPermission.BanMembers);
var authorMention = author.Mention;
var notification = string.Format(Messages.UserUnbanned, authorMention, toUnban.Mention,
Utils.WrapInline(reason));
await guild.RemoveBanAsync(toUnban);
await Utils.SilentSendAsync(channel, string.Format(Messages.UnbanResponse, toUnban.Mention,
Utils.WrapInline(reason)));
await Utils.SilentSendAsync(await guild.GetSystemChannelAsync(), notification);
await Utils.SilentSendAsync(await Utils.GetAdminLogChannel(guild), notification);
}
public override List<string> GetAliases() {
return new List<string> {"unban", "разбан"};
}
public override int GetArgumentsAmountRequired() {
return 2;
}
public override string GetSummary() {
return "Возвращает пользователя из бана";
}
}

View file

@ -1,29 +0,0 @@
using Discord;
using Discord.Commands;
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable ClassNeverInstantiated.Global
namespace Boyfriend.Commands;
public class UnbanModule : ModuleBase<SocketCommandContext> {
[Command("unban")]
[Summary("Возвращает пользователя из бана")]
[Alias("разбан")]
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);
}
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);
await Utils.SilentSendAsync(await guild.GetSystemChannelAsync(), notification);
await Utils.SilentSendAsync(await Utils.GetAdminLogChannel(guild), notification);
}
}

View file

@ -0,0 +1,61 @@
using Discord;
using Discord.Commands;
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable ClassNeverInstantiated.Global
namespace Boyfriend.Commands;
public class UnmuteCommand : Command {
public override async Task Run(SocketCommandContext context, string[] args) {
var toUnmute = await Utils.ParseMember(context.Guild, args[0]);
var author = context.Guild.GetUser(context.User.Id);
await CommandHandler.CheckPermissions(author, GuildPermission.ManageMessages, GuildPermission.ManageRoles);
await CommandHandler.CheckInteractions(author, toUnmute);
var role = Utils.GetMuteRole(context.Guild);
if (role != null)
if (toUnmute.RoleIds.All(x => x != role.Id)) {
var rolesRemoved = Boyfriend.GetGuildConfig(context.Guild).RolesRemovedOnMute;
foreach (var roleId in rolesRemoved[toUnmute.Id]) await toUnmute.AddRoleAsync(roleId);
rolesRemoved.Remove(toUnmute.Id);
throw new ApplicationException(Messages.RolesReturned);
}
UnmuteMember(context.Guild, context.Channel as ITextChannel, context.Guild.GetUser(context.User.Id),
toUnmute, Utils.JoinString(args, 1));
}
public static async void UnmuteMember(IGuild guild, ITextChannel? channel, IGuildUser author, IGuildUser toUnmute,
string reason) {
await CommandHandler.CheckPermissions(author, GuildPermission.ManageMessages, GuildPermission.ManageRoles);
var authorMention = author.Mention;
var notification = string.Format(Messages.MemberUnmuted, authorMention, toUnmute.Mention,
Utils.WrapInline(reason));
await toUnmute.RemoveRoleAsync(Utils.GetMuteRole(guild));
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(channel, string.Format(Messages.UnmuteResponse, toUnmute.Mention,
Utils.WrapInline(reason)));
await Utils.SilentSendAsync(await guild.GetSystemChannelAsync(), notification);
await Utils.SilentSendAsync(await Utils.GetAdminLogChannel(guild), notification);
}
public override List<string> GetAliases() {
return new List<string> {"unmute", "размут"};
}
public override int GetArgumentsAmountRequired() {
return 2;
}
public override string GetSummary() {
return "Снимает мут с участника";
}
}

View file

@ -1,46 +0,0 @@
using Discord;
using Discord.Commands;
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable ClassNeverInstantiated.Global
namespace Boyfriend.Commands;
public class UnmuteModule : ModuleBase<SocketCommandContext> {
[Command("unmute")]
[Summary("Возвращает пользователя из мута")]
[Alias("размут")]
public async Task Run(string user, [Remainder] string reason) {
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)) {
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);
}
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));
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);
}
}