mirror of
https://github.com/TeamOctolings/Octobot.git
synced 2025-01-31 09:09:00 +03:00
another two or three refactors
This commit is contained in:
parent
868b6bcaa7
commit
790f77aa49
21 changed files with 1447 additions and 944 deletions
|
@ -1,5 +1,8 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.1.32407.343
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Boyfriend", "Boyfriend\Boyfriend.csproj", "{21640A7A-75C2-4515-A1DF-CE8B6EEBD260}"
|
||||
EndProject
|
||||
Global
|
||||
|
@ -13,4 +16,10 @@ Global
|
|||
{21640A7A-75C2-4515-A1DF-CE8B6EEBD260}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{21640A7A-75C2-4515-A1DF-CE8B6EEBD260}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {2EDBF9CE-35F0-4810-93F7-FE0159EFD865}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Globalization;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Text;
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using Newtonsoft.Json;
|
||||
|
@ -6,6 +7,8 @@ using Newtonsoft.Json;
|
|||
namespace Boyfriend;
|
||||
|
||||
public static class Boyfriend {
|
||||
public static readonly StringBuilder StringBuilder = new();
|
||||
private static readonly Dictionary<ulong, SocketGuild> GuildCache = new();
|
||||
|
||||
private static readonly DiscordSocketConfig Config = new() {
|
||||
MessageCacheSize = 250,
|
||||
|
@ -13,8 +16,34 @@ public static class Boyfriend {
|
|||
};
|
||||
|
||||
public static readonly DiscordSocketClient Client = new(Config);
|
||||
private static readonly Game Activity = new("Retrospecter - Genocide", ActivityType.Listening);
|
||||
|
||||
private static readonly Dictionary<ulong, GuildConfig> GuildConfigDictionary = new();
|
||||
private static readonly Dictionary<ulong, Dictionary<string, string>> GuildConfigDictionary = new();
|
||||
private static readonly Dictionary<ulong, Dictionary<ulong, ReadOnlyCollection<ulong>>> RemovedRolesDictionary =
|
||||
new();
|
||||
|
||||
private static readonly Dictionary<string, string> EmptyGuildConfig = new();
|
||||
private static readonly Dictionary<ulong, ReadOnlyCollection<ulong>> EmptyRemovedRoles = new();
|
||||
|
||||
public static readonly Dictionary<string, string> DefaultConfig = new() {
|
||||
{"Lang", "en"},
|
||||
{"Prefix", "!"},
|
||||
{"RemoveRolesOnMute", "false"},
|
||||
{"SendWelcomeMessages", "true"},
|
||||
{"ReceiveStartupMessages", "false"},
|
||||
{"FrowningFace", "true"},
|
||||
{"WelcomeMessage", Messages.DefaultWelcomeMessage},
|
||||
{"EventStartedReceivers", "interested,role"},
|
||||
{"StarterRole", "0"},
|
||||
{"MuteRole", "0"},
|
||||
{"EventNotifyReceiverRole", "0"},
|
||||
{"AdminLogChannel", "0"},
|
||||
{"BotLogChannel", "0"},
|
||||
{"EventCreatedChannel", "0"},
|
||||
{"EventStartedChannel", "0"},
|
||||
{"EventCancelledChannel", "0"},
|
||||
{"EventCompletedChannel", "0"}
|
||||
};
|
||||
|
||||
public static void Main() {
|
||||
Init().GetAwaiter().GetResult();
|
||||
|
@ -27,7 +56,7 @@ public static class Boyfriend {
|
|||
|
||||
await Client.LoginAsync(TokenType.Bot, token);
|
||||
await Client.StartAsync();
|
||||
await Client.SetActivityAsync(new Game("Retrospecter - Expurgation", ActivityType.Listening));
|
||||
await Client.SetActivityAsync(Activity);
|
||||
|
||||
new EventHandler().InitEvents();
|
||||
|
||||
|
@ -40,36 +69,64 @@ public static class Boyfriend {
|
|||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public static async Task SetupGuildConfigs() {
|
||||
foreach (var guild in Client.Guilds) {
|
||||
var path = "config_" + guild.Id + ".json";
|
||||
if (!File.Exists(path)) File.Create(path);
|
||||
public static async Task WriteGuildConfig(ulong id) {
|
||||
var json = JsonConvert.SerializeObject(GuildConfigDictionary[id], Formatting.Indented);
|
||||
var removedRoles = JsonConvert.SerializeObject(RemovedRolesDictionary[id], Formatting.Indented);
|
||||
|
||||
var config = JsonConvert.DeserializeObject<GuildConfig>(await File.ReadAllTextAsync(path));
|
||||
if (config == null) {
|
||||
Messages.Culture = new CultureInfo("ru");
|
||||
config = new GuildConfig(guild.Id);
|
||||
}
|
||||
config.Validate();
|
||||
|
||||
GuildConfigDictionary.Add(config.Id.GetValueOrDefault(0), config);
|
||||
}
|
||||
await File.WriteAllTextAsync($"config_{id}.json", json);
|
||||
await File.WriteAllTextAsync($"removedroles_{id}.json", removedRoles);
|
||||
}
|
||||
|
||||
public static GuildConfig GetGuildConfig(IGuild guild) {
|
||||
Messages.Culture = new CultureInfo("ru");
|
||||
public static Dictionary<string, string> GetGuildConfig(ulong id) {
|
||||
if (!RemovedRolesDictionary.ContainsKey(id))
|
||||
RemovedRolesDictionary.Add(id, EmptyRemovedRoles);
|
||||
|
||||
var config = GuildConfigDictionary.ContainsKey(guild.Id) ? GuildConfigDictionary[guild.Id]
|
||||
: new GuildConfig(guild.Id);
|
||||
config.Validate();
|
||||
if (GuildConfigDictionary.ContainsKey(id)) return GuildConfigDictionary[id];
|
||||
|
||||
var path = $"config_{id}.json";
|
||||
|
||||
if (!File.Exists(path)) File.Create(path).Dispose();
|
||||
|
||||
var json = File.ReadAllText(path);
|
||||
var config = JsonConvert.DeserializeObject<Dictionary<string, string>>(json) ?? EmptyGuildConfig;
|
||||
|
||||
foreach (var key in DefaultConfig.Keys)
|
||||
if (!config.ContainsKey(key))
|
||||
config.Add(key, DefaultConfig[key]);
|
||||
|
||||
foreach (var key in config.Keys)
|
||||
if (!DefaultConfig.ContainsKey(key))
|
||||
config.Remove(key);
|
||||
|
||||
GuildConfigDictionary.Add(id, config);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
public static IGuild FindGuild(IMessageChannel channel) {
|
||||
public static Dictionary<ulong, ReadOnlyCollection<ulong>> GetRemovedRoles(ulong id) {
|
||||
if (RemovedRolesDictionary.ContainsKey(id)) return RemovedRolesDictionary[id];
|
||||
|
||||
var path = $"removedroles_{id}.json";
|
||||
|
||||
if (!File.Exists(path)) File.Create(path);
|
||||
|
||||
var json = File.ReadAllText(path);
|
||||
var removedRoles = JsonConvert.DeserializeObject<Dictionary<ulong, ReadOnlyCollection<ulong>>>(json) ??
|
||||
EmptyRemovedRoles;
|
||||
|
||||
RemovedRolesDictionary.Add(id, removedRoles);
|
||||
|
||||
return removedRoles;
|
||||
}
|
||||
|
||||
public static SocketGuild FindGuild(ulong channel) {
|
||||
if (GuildCache.ContainsKey(channel)) return GuildCache[channel];
|
||||
foreach (var guild in Client.Guilds)
|
||||
if (guild.Channels.Any(x => x == channel))
|
||||
foreach (var x in guild.Channels) {
|
||||
if (x.Id != channel) continue;
|
||||
GuildCache.Add(channel, guild);
|
||||
return guild;
|
||||
}
|
||||
|
||||
throw new Exception(Messages.CouldntFindGuildByChannel);
|
||||
}
|
||||
|
|
|
@ -15,8 +15,10 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Discord.Net" Version="3.3.2"/>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Discord.Net" Version="3.6.1"/>
|
||||
<PackageReference Include="Humanizer.Core" Version="2.14.1"/>
|
||||
<PackageReference Include="Humanizer.Core.ru" Version="2.14.1"/>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Text.RegularExpressions;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Boyfriend.Commands;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
|
@ -7,75 +8,104 @@ using Discord.WebSocket;
|
|||
namespace Boyfriend;
|
||||
|
||||
public static class CommandHandler {
|
||||
|
||||
public static readonly Command[] Commands = {
|
||||
new BanCommand(), new ClearCommand(), new HelpCommand(),
|
||||
new KickCommand(), new MuteCommand(), new PingCommand(),
|
||||
new SettingsCommand(), new UnbanCommand(), new UnmuteCommand()
|
||||
};
|
||||
|
||||
public static async Task HandleCommand(SocketUserMessage message) {
|
||||
var context = new SocketCommandContext(Boyfriend.Client, message);
|
||||
private static readonly Dictionary<string, Regex> RegexCache = new();
|
||||
|
||||
public static readonly StringBuilder StackedReplyMessage = new();
|
||||
public static readonly StringBuilder StackedPublicFeedback = new();
|
||||
public static readonly StringBuilder StackedPrivateFeedback = new();
|
||||
|
||||
#pragma warning disable CA2211
|
||||
public static bool ConfigWriteScheduled = false; // HOW IT CAN BE PRIVATE????
|
||||
#pragma warning restore CA2211
|
||||
|
||||
public static async Task HandleCommand(SocketUserMessage message) {
|
||||
StackedReplyMessage.Clear();
|
||||
StackedPrivateFeedback.Clear();
|
||||
StackedPublicFeedback.Clear();
|
||||
var context = new SocketCommandContext(Boyfriend.Client, message);
|
||||
var guild = context.Guild;
|
||||
var config = Boyfriend.GetGuildConfig(guild.Id);
|
||||
|
||||
Regex regex;
|
||||
if (RegexCache.ContainsKey(config["Prefix"])) {
|
||||
regex = RegexCache[config["Prefix"]];
|
||||
} else {
|
||||
regex = new Regex(Regex.Escape(config["Prefix"]));
|
||||
RegexCache.Add(config["Prefix"], regex);
|
||||
}
|
||||
|
||||
var list = message.Content.Split("\n");
|
||||
var currentLine = 0;
|
||||
foreach (var line in list) {
|
||||
currentLine++;
|
||||
foreach (var command in Commands) {
|
||||
var regex = new Regex(Regex.Escape(Boyfriend.GetGuildConfig(context.Guild).Prefix!));
|
||||
if (!command.GetAliases().Contains(regex.Replace(message.Content, "", 1).Split()[0]))
|
||||
if (!command.Aliases.Contains(regex.Replace(line, "", 1).ToLower().Split()[0]))
|
||||
continue;
|
||||
|
||||
var args = message.Content.Split().Skip(1).ToArray();
|
||||
try {
|
||||
if (command.GetArgumentsAmountRequired() > args.Length)
|
||||
throw new ApplicationException(string.Format(Messages.NotEnoughArguments,
|
||||
command.GetArgumentsAmountRequired(), args.Length));
|
||||
await context.Channel.TriggerTypingAsync();
|
||||
|
||||
var args = line.Split().Skip(1).ToArray();
|
||||
|
||||
if (command.ArgsLengthRequired <= args.Length)
|
||||
await command.Run(context, args);
|
||||
} catch (Exception e) {
|
||||
var signature = e switch {
|
||||
ApplicationException => ":x:",
|
||||
UnauthorizedAccessException => ":no_entry_sign:",
|
||||
_ => ":stop_sign:"
|
||||
};
|
||||
var stacktrace = e.StackTrace;
|
||||
var toSend = $"{signature} `{e.Message}`";
|
||||
if (stacktrace != null && e is not ApplicationException && e is not UnauthorizedAccessException)
|
||||
toSend += $"{Environment.NewLine}{Utils.Wrap(stacktrace)}";
|
||||
await context.Channel.SendMessageAsync(toSend);
|
||||
throw;
|
||||
}
|
||||
else
|
||||
StackedReplyMessage.AppendFormat(Messages.NotEnoughArguments, command.ArgsLengthRequired.ToString(),
|
||||
args.Length.ToString());
|
||||
|
||||
break;
|
||||
if (currentLine != list.Length) continue;
|
||||
if (ConfigWriteScheduled) await Boyfriend.WriteGuildConfig(guild.Id);
|
||||
await context.Message.ReplyAsync(StackedReplyMessage.ToString(), false, null, AllowedMentions.None);
|
||||
|
||||
var adminChannel = Utils.GetAdminLogChannel(guild.Id);
|
||||
var systemChannel = guild.SystemChannel;
|
||||
if (adminChannel != null)
|
||||
await Utils.SilentSendAsync(adminChannel, StackedPrivateFeedback.ToString());
|
||||
if (systemChannel != null)
|
||||
await Utils.SilentSendAsync(systemChannel, StackedPublicFeedback.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task CheckPermissions(IGuildUser user, GuildPermission toCheck,
|
||||
public static string HasPermission(ref SocketGuildUser user, GuildPermission toCheck,
|
||||
GuildPermission forBot = GuildPermission.StartEmbeddedActivities) {
|
||||
var me = await user.Guild.GetCurrentUserAsync();
|
||||
var me = user.Guild.CurrentUser;
|
||||
|
||||
if (user.Id == user.Guild.OwnerId || (me.GuildPermissions.Has(GuildPermission.Administrator) &&
|
||||
user.GuildPermissions.Has(GuildPermission.Administrator))) return "";
|
||||
|
||||
if (forBot == GuildPermission.StartEmbeddedActivities) forBot = toCheck;
|
||||
|
||||
if (user.Id != user.Guild.OwnerId
|
||||
&& (!me.GuildPermissions.Has(GuildPermission.Administrator)
|
||||
|| !user.GuildPermissions.Has(GuildPermission.Administrator))) {
|
||||
if (!me.GuildPermissions.Has(forBot))
|
||||
throw new UnauthorizedAccessException(Messages.CommandNoPermissionBot);
|
||||
if (!user.GuildPermissions.Has(toCheck))
|
||||
throw new UnauthorizedAccessException(Messages.CommandNoPermissionUser);
|
||||
}
|
||||
return Messages.CommandNoPermissionBot;
|
||||
|
||||
return !user.GuildPermissions.Has(toCheck) ? Messages.CommandNoPermissionUser : "";
|
||||
}
|
||||
|
||||
public static async Task CheckInteractions(IGuildUser actor, IGuildUser target) {
|
||||
var me = await target.Guild.GetCurrentUserAsync();
|
||||
|
||||
public static string CanInteract(ref SocketGuildUser actor, ref SocketGuildUser target) {
|
||||
if (actor.Guild != target.Guild)
|
||||
throw new Exception(Messages.InteractionsDifferentGuilds);
|
||||
if (actor.Id == actor.Guild.OwnerId) return;
|
||||
return Messages.InteractionsDifferentGuilds;
|
||||
if (actor.Id == actor.Guild.OwnerId)
|
||||
return "";
|
||||
|
||||
if (target.Id == target.Guild.OwnerId)
|
||||
throw new UnauthorizedAccessException(Messages.InteractionsOwner);
|
||||
return Messages.InteractionsOwner;
|
||||
if (actor == target)
|
||||
throw new UnauthorizedAccessException(Messages.InteractionsYourself);
|
||||
return Messages.InteractionsYourself;
|
||||
|
||||
var me = target.Guild.CurrentUser;
|
||||
|
||||
if (target == me)
|
||||
throw new UnauthorizedAccessException(Messages.InteractionsMe);
|
||||
return Messages.InteractionsMe;
|
||||
if (me.Hierarchy <= target.Hierarchy)
|
||||
throw new UnauthorizedAccessException(Messages.InteractionsFailedBot);
|
||||
if (actor.Hierarchy <= target.Hierarchy)
|
||||
throw new UnauthorizedAccessException(Messages.InteractionsFailedUser);
|
||||
return Messages.InteractionsFailedBot;
|
||||
|
||||
return actor.Hierarchy <= target.Hierarchy ? Messages.InteractionsFailedUser : "";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,73 +1,72 @@
|
|||
using Discord;
|
||||
using Discord.Commands;
|
||||
|
||||
// ReSharper disable UnusedType.Global
|
||||
// ReSharper disable UnusedMember.Global
|
||||
// ReSharper disable ClassNeverInstantiated.Global
|
||||
using Discord.WebSocket;
|
||||
|
||||
namespace Boyfriend.Commands;
|
||||
|
||||
public class BanCommand : Command {
|
||||
public override string[] Aliases { get; } = {"ban", "бан"};
|
||||
public override int ArgsLengthRequired => 2;
|
||||
|
||||
public override async Task Run(SocketCommandContext context, string[] args) {
|
||||
var reason = Utils.JoinString(args, 1);
|
||||
var toBan = Utils.ParseUser(args[0]);
|
||||
|
||||
TimeSpan duration;
|
||||
try {
|
||||
duration = Utils.GetTimeSpan(args[1]);
|
||||
reason = Utils.JoinString(args, 2);
|
||||
} catch (Exception e) when (e is ArgumentNullException or FormatException or OverflowException) {
|
||||
await Warn(context.Channel as ITextChannel, Messages.DurationParseFailed);
|
||||
duration = TimeSpan.FromMilliseconds(-1);
|
||||
if (toBan == null) {
|
||||
Error(Messages.UserDoesntExist, false);
|
||||
return;
|
||||
}
|
||||
|
||||
await BanUser(context.Guild, context.Channel as ITextChannel, context.Guild.GetUser(context.User.Id),
|
||||
await Utils.ParseUser(args[0]), duration, reason);
|
||||
var guild = context.Guild;
|
||||
var author = (SocketGuildUser) context.User;
|
||||
|
||||
var permissionCheckResponse = CommandHandler.HasPermission(ref author, GuildPermission.BanMembers);
|
||||
if (permissionCheckResponse != "") {
|
||||
Error(permissionCheckResponse, true);
|
||||
return;
|
||||
}
|
||||
|
||||
public static async Task BanUser(IGuild guild, ITextChannel? channel, IGuildUser author, IUser toBan,
|
||||
TimeSpan duration, string reason) {
|
||||
var authorMention = author.Mention;
|
||||
var guildBanMessage = $"({Utils.GetNameAndDiscrim(author)}) {reason}";
|
||||
var memberToBan = await guild.GetUserAsync(toBan.Id);
|
||||
var expiresIn = duration.TotalSeconds > 0 ? string.Format(Messages.PunishmentExpiresIn, Environment.NewLine,
|
||||
DateTimeOffset.Now.ToUnixTimeSeconds() + duration.TotalSeconds) : "";
|
||||
var notification = string.Format(Messages.UserBanned, authorMention, toBan.Mention, Utils.WrapInline(reason),
|
||||
expiresIn);
|
||||
var reason = Utils.JoinString(ref args, 2);
|
||||
var memberToBan = Utils.ParseMember(guild, args[0]);
|
||||
|
||||
await CommandHandler.CheckPermissions(author, GuildPermission.BanMembers);
|
||||
if (memberToBan != null)
|
||||
await CommandHandler.CheckInteractions(author, memberToBan);
|
||||
if (memberToBan != null) {
|
||||
var interactionCheckResponse = CommandHandler.CanInteract(ref author, ref memberToBan);
|
||||
if (interactionCheckResponse != "") {
|
||||
Error(interactionCheckResponse, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var duration = Utils.GetTimeSpan(ref args[1]) ?? TimeSpan.FromMilliseconds(-1);
|
||||
if (duration.TotalSeconds < 0) {
|
||||
Warn(Messages.DurationParseFailed);
|
||||
reason = Utils.JoinString(ref args, 1);
|
||||
}
|
||||
|
||||
await BanUser(guild, author, toBan, duration, reason);
|
||||
}
|
||||
|
||||
public static async Task BanUser(SocketGuild guild, SocketGuildUser author, SocketUser toBan, TimeSpan duration,
|
||||
string reason) {
|
||||
var guildBanMessage = $"({author}) {reason}";
|
||||
|
||||
await Utils.SendDirectMessage(toBan,
|
||||
string.Format(Messages.YouWereBanned, author.Mention, guild.Name, Utils.WrapInline(reason)));
|
||||
|
||||
await guild.AddBanAsync(toBan, 0, guildBanMessage);
|
||||
|
||||
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 feedback = string.Format(Messages.FeedbackUserBanned, toBan.Mention,
|
||||
Utils.GetHumanizedTimeOffset(ref duration), Utils.WrapInline(reason));
|
||||
Success(feedback, author.Mention, false, false);
|
||||
await Utils.SendFeedback(feedback, guild.Id, author.Mention, true);
|
||||
|
||||
if (duration.TotalSeconds > 0) {
|
||||
await Task.Run(async () => {
|
||||
async void DelayUnban() {
|
||||
await Task.Delay(duration);
|
||||
try {
|
||||
await UnbanCommand.UnbanUser(guild, null, await guild.GetCurrentUserAsync(), toBan,
|
||||
Messages.PunishmentExpired);
|
||||
} catch (ApplicationException) {}
|
||||
});
|
||||
}
|
||||
await UnbanCommand.UnbanUser(guild, guild.CurrentUser, toBan, Messages.PunishmentExpired);
|
||||
}
|
||||
|
||||
public override List<string> GetAliases() {
|
||||
return new List<string> {"ban", "бан"};
|
||||
var task = new Task(DelayUnban);
|
||||
task.Start();
|
||||
}
|
||||
|
||||
public override int GetArgumentsAmountRequired() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public override string GetSummary() {
|
||||
return "Банит пользователя";
|
||||
}
|
||||
}
|
|
@ -1,54 +1,46 @@
|
|||
using Discord;
|
||||
using Discord.Commands;
|
||||
|
||||
// ReSharper disable UnusedType.Global
|
||||
// ReSharper disable UnusedMember.Global
|
||||
// ReSharper disable ClassNeverInstantiated.Global
|
||||
using Discord.WebSocket;
|
||||
|
||||
namespace Boyfriend.Commands;
|
||||
|
||||
public class ClearCommand : Command {
|
||||
public override async Task Run(SocketCommandContext context, string[] args) {
|
||||
var user = context.User;
|
||||
public override string[] Aliases { get; } = {"clear", "purge", "очистить", "стереть"};
|
||||
public override int ArgsLengthRequired => 1;
|
||||
|
||||
int toDelete;
|
||||
try {
|
||||
toDelete = Convert.ToInt32(args[0]);
|
||||
} catch (Exception e) when (e is FormatException or OverflowException) {
|
||||
throw new ApplicationException(Messages.ClearInvalidAmountSpecified);
|
||||
public override async Task Run(SocketCommandContext context, string[] args) {
|
||||
var user = (SocketGuildUser) context.User;
|
||||
|
||||
if (context.Channel is not SocketTextChannel channel) throw new Exception();
|
||||
|
||||
var permissionCheckResponse = CommandHandler.HasPermission(ref user, GuildPermission.ManageMessages);
|
||||
if (permissionCheckResponse != "") {
|
||||
Error(permissionCheckResponse, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (context.Channel is not ITextChannel channel) return;
|
||||
|
||||
await CommandHandler.CheckPermissions(context.Guild.GetUser(user.Id), GuildPermission.ManageMessages);
|
||||
if (!int.TryParse(args[0], out var toDelete)) {
|
||||
Error(Messages.ClearInvalidAmountSpecified, false);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (toDelete) {
|
||||
case < 1:
|
||||
throw new ApplicationException(Messages.ClearNegativeAmount);
|
||||
Error(Messages.ClearNegativeAmount, false);
|
||||
break;
|
||||
case > 200:
|
||||
throw new ApplicationException(Messages.ClearAmountTooLarge);
|
||||
default: {
|
||||
Error(Messages.ClearAmountTooLarge, false);
|
||||
break;
|
||||
default:
|
||||
var messages = await channel.GetMessagesAsync(toDelete + 1).FlattenAsync();
|
||||
|
||||
await channel.DeleteMessagesAsync(messages, Utils.GetRequestOptions(Utils.GetNameAndDiscrim(user)));
|
||||
await channel.DeleteMessagesAsync(messages, Utils.GetRequestOptions(user.ToString()!));
|
||||
|
||||
await Utils.SendFeedback(
|
||||
string.Format(Messages.FeedbackMessagesCleared, (toDelete + 1).ToString(), channel.Mention),
|
||||
context.Guild.Id, user.Mention);
|
||||
|
||||
await Utils.SilentSendAsync(await Utils.GetAdminLogChannel(context.Guild),
|
||||
string.Format(Messages.MessagesDeleted, 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 "Очищает сообщения";
|
||||
}
|
||||
}
|
|
@ -1,18 +1,32 @@
|
|||
using Discord;
|
||||
using System.Text;
|
||||
using Discord.Commands;
|
||||
|
||||
namespace Boyfriend.Commands;
|
||||
|
||||
public abstract class Command {
|
||||
|
||||
public abstract string[] Aliases { get; }
|
||||
|
||||
public abstract int ArgsLengthRequired { get; }
|
||||
public abstract Task Run(SocketCommandContext context, string[] args);
|
||||
|
||||
public abstract List<string> GetAliases();
|
||||
protected static void Output(ref StringBuilder message) {
|
||||
CommandHandler.StackedReplyMessage.Append(message).AppendLine();
|
||||
}
|
||||
|
||||
public abstract int GetArgumentsAmountRequired();
|
||||
protected static void Success(string message, string userMention, bool sendPublicFeedback = false,
|
||||
bool sendPrivateFeedback = true) {
|
||||
CommandHandler.StackedReplyMessage.Append(":white_check_mark: ").AppendLine(message);
|
||||
if (sendPrivateFeedback)
|
||||
Utils.StackFeedback(ref message, ref userMention, sendPublicFeedback);
|
||||
}
|
||||
|
||||
public abstract string GetSummary();
|
||||
protected static void Warn(string message) {
|
||||
CommandHandler.StackedReplyMessage.Append(":warning: ").AppendLine(message);
|
||||
}
|
||||
|
||||
protected static async Task Warn(ITextChannel? channel, string warning) {
|
||||
await Utils.SilentSendAsync(channel, ":warning: " + warning);
|
||||
protected static void Error(string message, bool accessDenied) {
|
||||
var symbol = accessDenied ? ":no_entry_sign: " : ":x: ";
|
||||
CommandHandler.StackedReplyMessage.Append(symbol).AppendLine(message);
|
||||
}
|
||||
}
|
|
@ -1,30 +1,22 @@
|
|||
using Discord.Commands;
|
||||
|
||||
// ReSharper disable UnusedType.Global
|
||||
// ReSharper disable UnusedMember.Global
|
||||
using Humanizer;
|
||||
|
||||
namespace Boyfriend.Commands;
|
||||
|
||||
public class HelpCommand : Command {
|
||||
public override async Task Run(SocketCommandContext context, string[] args) {
|
||||
var nl = Environment.NewLine;
|
||||
var prefix = Boyfriend.GetGuildConfig(context.Guild).Prefix;
|
||||
var toSend = string.Format(Messages.CommandHelp, nl);
|
||||
public override string[] Aliases { get; } = {"help", "помощь", "справка"};
|
||||
public override int ArgsLengthRequired => 0;
|
||||
|
||||
toSend = CommandHandler.Commands.Aggregate(toSend,
|
||||
(current, command) => current + $"`{prefix}{command.GetAliases()[0]}`: {command.GetSummary()}{nl}");
|
||||
await context.Channel.SendMessageAsync(toSend);
|
||||
}
|
||||
public override Task Run(SocketCommandContext context, string[] args) {
|
||||
var prefix = Boyfriend.GetGuildConfig(context.Guild.Id)["Prefix"];
|
||||
var toSend = Boyfriend.StringBuilder.Append(Messages.CommandHelp);
|
||||
|
||||
public override List<string> GetAliases() {
|
||||
return new List<string> {"help", "помощь", "справка"};
|
||||
}
|
||||
foreach (var command in CommandHandler.Commands)
|
||||
toSend.Append(
|
||||
$"\n`{prefix}{command.Aliases[0]}`: {Utils.GetMessage($"CommandDescription{command.Aliases[0].Titleize()}")}");
|
||||
Output(ref toSend);
|
||||
toSend.Clear();
|
||||
|
||||
public override int GetArgumentsAmountRequired() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override string GetSummary() {
|
||||
return "Показывает эту справку";
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
|
@ -1,50 +1,49 @@
|
|||
using Discord;
|
||||
using Discord.Commands;
|
||||
|
||||
// ReSharper disable UnusedType.Global
|
||||
// ReSharper disable UnusedMember.Global
|
||||
// ReSharper disable ClassNeverInstantiated.Global
|
||||
using Discord.WebSocket;
|
||||
|
||||
namespace Boyfriend.Commands;
|
||||
|
||||
public class KickCommand : Command {
|
||||
public override string[] Aliases { get; } = {"kick", "кик", "выгнать"};
|
||||
public override int ArgsLengthRequired => 2;
|
||||
|
||||
public override async Task Run(SocketCommandContext context, string[] args) {
|
||||
var author = context.Guild.GetUser(context.User.Id);
|
||||
var toKick = await Utils.ParseMember(context.Guild, args[0]);
|
||||
var author = (SocketGuildUser) context.User;
|
||||
|
||||
await CommandHandler.CheckPermissions(author, GuildPermission.KickMembers);
|
||||
await CommandHandler.CheckInteractions(author, toKick);
|
||||
|
||||
await KickMember(context.Guild, context.Channel as ITextChannel, author, toKick, Utils.JoinString(args, 1));
|
||||
var permissionCheckResponse = CommandHandler.HasPermission(ref author, GuildPermission.KickMembers);
|
||||
if (permissionCheckResponse != "") {
|
||||
Error(permissionCheckResponse, true);
|
||||
return;
|
||||
}
|
||||
|
||||
private static async Task KickMember(IGuild guild, ITextChannel? channel, IUser author, IGuildUser toKick,
|
||||
string reason) {
|
||||
var authorMention = author.Mention;
|
||||
var guildKickMessage = $"({Utils.GetNameAndDiscrim(author)}) {reason}";
|
||||
var notification = string.Format(Messages.MemberKicked, authorMention, toKick.Mention,
|
||||
Utils.WrapInline(reason));
|
||||
var toKick = Utils.ParseMember(context.Guild, args[0]);
|
||||
|
||||
await Utils.SendDirectMessage(toKick, string.Format(Messages.YouWereKicked, authorMention, guild.Name,
|
||||
Utils.WrapInline(reason)));
|
||||
if (toKick == null) {
|
||||
Error(Messages.UserNotInGuild, false);
|
||||
return;
|
||||
}
|
||||
|
||||
var interactionCheckResponse = CommandHandler.CanInteract(ref author, ref toKick);
|
||||
if (interactionCheckResponse != "") {
|
||||
Error(interactionCheckResponse, true);
|
||||
return;
|
||||
}
|
||||
|
||||
await KickMember(context.Guild, author, toKick, Utils.JoinString(ref args, 1));
|
||||
|
||||
Success(
|
||||
string.Format(Messages.FeedbackMemberKicked, toKick.Mention,
|
||||
Utils.WrapInline(Utils.JoinString(ref args, 1))), author.Mention);
|
||||
}
|
||||
|
||||
private static async Task KickMember(IGuild guild, SocketUser author, SocketGuildUser toKick, string reason) {
|
||||
var authorMention = author.Mention;
|
||||
var guildKickMessage = $"({author}) {reason}";
|
||||
|
||||
await Utils.SendDirectMessage(toKick,
|
||||
string.Format(Messages.YouWereKicked, authorMention, guild.Name, Utils.WrapInline(reason)));
|
||||
|
||||
await toKick.KickAsync(guildKickMessage);
|
||||
|
||||
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 "Выгоняет участника";
|
||||
}
|
||||
}
|
|
@ -1,117 +1,122 @@
|
|||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.Net;
|
||||
|
||||
// ReSharper disable UnusedType.Global
|
||||
// ReSharper disable UnusedMember.Global
|
||||
// ReSharper disable ClassNeverInstantiated.Global
|
||||
using Discord.WebSocket;
|
||||
|
||||
namespace Boyfriend.Commands;
|
||||
|
||||
public class MuteCommand : Command {
|
||||
public override async Task Run(SocketCommandContext context, string[] args) {
|
||||
var author = context.Guild.GetUser(context.User.Id);
|
||||
var config = Boyfriend.GetGuildConfig(context.Guild);
|
||||
var reason = Utils.JoinString(args, 1);
|
||||
var role = Utils.GetMuteRole(context.Guild);
|
||||
var rolesRemoved = config.RolesRemovedOnMute!;
|
||||
var toMute = await Utils.ParseMember(context.Guild, args[0]);
|
||||
public override string[] Aliases { get; } = {"mute", "timeout", "заглушить", "мут"};
|
||||
public override int ArgsLengthRequired => 2;
|
||||
|
||||
TimeSpan duration;
|
||||
try {
|
||||
duration = Utils.GetTimeSpan(args[1]);
|
||||
reason = Utils.JoinString(args, 2);
|
||||
} catch (Exception e) when (e is ArgumentNullException or FormatException or OverflowException) {
|
||||
await Warn(context.Channel as ITextChannel, Messages.DurationParseFailed);
|
||||
duration = TimeSpan.FromMilliseconds(-1);
|
||||
public override async Task Run(SocketCommandContext context, string[] args) {
|
||||
var toMute = Utils.ParseMember(context.Guild, args[0]);
|
||||
var reason = Utils.JoinString(ref args, 2);
|
||||
|
||||
var duration = Utils.GetTimeSpan(ref args[1]) ?? TimeSpan.FromMilliseconds(-1);
|
||||
if (duration.TotalSeconds < 0) {
|
||||
Warn(Messages.DurationParseFailed);
|
||||
reason = Utils.JoinString(ref args, 1);
|
||||
}
|
||||
|
||||
if (toMute == null)
|
||||
throw new ApplicationException(Messages.UserNotInGuild);
|
||||
if (toMute == null) {
|
||||
Error(Messages.UserNotInGuild, false);
|
||||
return;
|
||||
}
|
||||
|
||||
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 guild = context.Guild;
|
||||
var role = Utils.GetMuteRole(ref guild);
|
||||
|
||||
if (role != null) {
|
||||
var hasMuteRole = false;
|
||||
foreach (var x in toMute.Roles) {
|
||||
if (x != role) continue;
|
||||
hasMuteRole = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (hasMuteRole || (toMute.TimedOutUntil != null && toMute.TimedOutUntil.Value.ToUnixTimeMilliseconds() >
|
||||
DateTimeOffset.Now.ToUnixTimeMilliseconds())) {
|
||||
Error(Messages.MemberAlreadyMuted, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var rolesRemoved = Boyfriend.GetRemovedRoles(context.Guild.Id);
|
||||
|
||||
if (rolesRemoved.ContainsKey(toMute.Id)) {
|
||||
foreach (var roleId in rolesRemoved[toMute.Id]) await toMute.AddRoleAsync(roleId);
|
||||
rolesRemoved.Remove(toMute.Id);
|
||||
await config.Save();
|
||||
throw new ApplicationException(Messages.RolesReturned);
|
||||
CommandHandler.ConfigWriteScheduled = true;
|
||||
Warn(Messages.RolesReturned);
|
||||
}
|
||||
|
||||
await CommandHandler.CheckPermissions(author, GuildPermission.ModerateMembers, GuildPermission.ManageRoles);
|
||||
await CommandHandler.CheckInteractions(author, toMute);
|
||||
var author = (SocketGuildUser) context.User;
|
||||
|
||||
await MuteMember(context.Guild, context.Channel as ITextChannel, context.Guild.GetUser(context.User.Id), toMute,
|
||||
duration, reason);
|
||||
var permissionCheckResponse = CommandHandler.HasPermission(ref author, GuildPermission.ModerateMembers);
|
||||
if (permissionCheckResponse != "") {
|
||||
Error(permissionCheckResponse, true);
|
||||
return;
|
||||
}
|
||||
|
||||
private static async Task MuteMember(IGuild guild, ITextChannel? channel, IGuildUser author, IGuildUser toMute,
|
||||
var interactionCheckResponse = CommandHandler.CanInteract(ref author, ref toMute);
|
||||
if (interactionCheckResponse != "") {
|
||||
Error(interactionCheckResponse, true);
|
||||
return;
|
||||
}
|
||||
|
||||
await MuteMember(guild, author, toMute, duration, reason);
|
||||
|
||||
Success(
|
||||
string.Format(Messages.FeedbackMemberMuted, toMute.Mention, Utils.GetHumanizedTimeOffset(ref duration),
|
||||
Utils.WrapInline(reason)), author.Mention, true);
|
||||
}
|
||||
|
||||
private static async Task MuteMember(SocketGuild guild, SocketUser author, SocketGuildUser toMute,
|
||||
TimeSpan duration, string reason) {
|
||||
await CommandHandler.CheckPermissions(author, GuildPermission.ManageMessages, GuildPermission.ManageRoles);
|
||||
var authorMention = author.Mention;
|
||||
var config = Boyfriend.GetGuildConfig(guild);
|
||||
var requestOptions = Utils.GetRequestOptions($"({Utils.GetNameAndDiscrim(author)}) {reason}");
|
||||
var role = Utils.GetMuteRole(guild);
|
||||
var config = Boyfriend.GetGuildConfig(guild.Id);
|
||||
var requestOptions = Utils.GetRequestOptions($"({author}) {reason}");
|
||||
var role = Utils.GetMuteRole(ref guild);
|
||||
var hasDuration = duration.TotalSeconds > 0;
|
||||
var expiresIn = hasDuration ? string.Format(Messages.PunishmentExpiresIn, Environment.NewLine,
|
||||
DateTimeOffset.Now.ToUnixTimeSeconds() + duration.TotalSeconds) : "";
|
||||
var notification = string.Format(Messages.MemberMuted, authorMention, toMute.Mention, Utils.WrapInline(reason),
|
||||
expiresIn);
|
||||
|
||||
if (role != null) {
|
||||
if (config.RemoveRolesOnMute.GetValueOrDefault(false)) {
|
||||
if (config["RemoveRolesOnMute"] == "true") {
|
||||
var rolesRemoved = new List<ulong>();
|
||||
foreach (var roleId in toMute.RoleIds) {
|
||||
foreach (var userRole in toMute.Roles)
|
||||
try {
|
||||
if (roleId == guild.Id) continue;
|
||||
if (roleId == role.Id) continue;
|
||||
await toMute.RemoveRoleAsync(roleId);
|
||||
rolesRemoved.Add(roleId);
|
||||
if (userRole == guild.EveryoneRole || userRole == role) continue;
|
||||
await toMute.RemoveRoleAsync(role);
|
||||
rolesRemoved.Add(userRole.Id);
|
||||
} catch (HttpException e) {
|
||||
await Warn(channel,
|
||||
string.Format(Messages.RoleRemovalFailed, $"<@&{roleId}>", Utils.WrapInline(e.Reason)));
|
||||
}
|
||||
Warn(string.Format(Messages.RoleRemovalFailed, $"<@&{userRole}>", Utils.WrapInline(e.Reason)));
|
||||
}
|
||||
|
||||
config.RolesRemovedOnMute!.Add(toMute.Id, rolesRemoved);
|
||||
await config.Save();
|
||||
Boyfriend.GetRemovedRoles(guild.Id).Add(toMute.Id, rolesRemoved.AsReadOnly());
|
||||
CommandHandler.ConfigWriteScheduled = true;
|
||||
|
||||
if (hasDuration)
|
||||
await Task.Run(async () => {
|
||||
if (hasDuration) {
|
||||
async void DelayUnmute() {
|
||||
await Task.Delay(duration);
|
||||
try {
|
||||
await UnmuteCommand.UnmuteMember(guild, null, await guild.GetCurrentUserAsync(), toMute,
|
||||
Messages.PunishmentExpired);
|
||||
} catch (ApplicationException) {}
|
||||
});
|
||||
await UnmuteCommand.UnmuteMember(guild, guild.CurrentUser, toMute, Messages.PunishmentExpired);
|
||||
}
|
||||
|
||||
var task = new Task(DelayUnmute);
|
||||
task.Start();
|
||||
}
|
||||
}
|
||||
|
||||
await toMute.AddRoleAsync(role, requestOptions);
|
||||
} else {
|
||||
if (!hasDuration)
|
||||
throw new ApplicationException(Messages.DurationRequiredForTimeOuts);
|
||||
if (toMute.IsBot)
|
||||
throw new ApplicationException(Messages.CannotTimeOutBot);
|
||||
if (!hasDuration) {
|
||||
Error(Messages.DurationRequiredForTimeOuts, false);
|
||||
return;
|
||||
}
|
||||
if (toMute.IsBot) {
|
||||
Error(Messages.CannotTimeOutBot, false);
|
||||
return;
|
||||
}
|
||||
|
||||
await toMute.SetTimeOutAsync(duration, requestOptions);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
public override List<string> GetAliases() {
|
||||
return new List<string> {"mute", "мут", "мьют"};
|
||||
}
|
||||
|
||||
public override int GetArgumentsAmountRequired() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public override string GetSummary() {
|
||||
return "Глушит участника";
|
||||
}
|
||||
}
|
|
@ -1,25 +1,19 @@
|
|||
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 string[] Aliases { get; } = {"ping", "latency", "pong", "пинг", "задержка", "понг"};
|
||||
public override int ArgsLengthRequired => 0;
|
||||
|
||||
public override List<string> GetAliases() {
|
||||
return new List<string> {"ping", "пинг", "задержка"};
|
||||
}
|
||||
public override Task Run(SocketCommandContext context, string[] args) {
|
||||
var builder = Boyfriend.StringBuilder;
|
||||
|
||||
public override int GetArgumentsAmountRequired() {
|
||||
return 0;
|
||||
}
|
||||
builder.Append(Utils.GetBeep()).Append(Boyfriend.Client.Latency).Append(Messages.Milliseconds);
|
||||
|
||||
public override string GetSummary() {
|
||||
return "Измеряет время обработки REST-запроса";
|
||||
Output(ref builder);
|
||||
builder.Clear();
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
|
@ -1,111 +1,156 @@
|
|||
using System.Reflection;
|
||||
using Discord;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
|
||||
// ReSharper disable UnusedType.Global
|
||||
// ReSharper disable UnusedMember.Global
|
||||
using Discord.WebSocket;
|
||||
|
||||
namespace Boyfriend.Commands;
|
||||
|
||||
public class SettingsCommand : Command {
|
||||
public override async Task Run(SocketCommandContext context, string[] args) {
|
||||
var config = Boyfriend.GetGuildConfig(context.Guild);
|
||||
var guild = context.Guild;
|
||||
public override string[] Aliases { get; } = {"settings", "config", "настройки", "конфиг"};
|
||||
public override int ArgsLengthRequired => 0;
|
||||
|
||||
await CommandHandler.CheckPermissions(context.Guild.GetUser(context.User.Id), GuildPermission.ManageGuild);
|
||||
public override Task Run(SocketCommandContext context, string[] args) {
|
||||
var author = (SocketGuildUser) context.User;
|
||||
|
||||
var permissionCheckResponse = CommandHandler.HasPermission(ref author, GuildPermission.ManageGuild);
|
||||
if (permissionCheckResponse != "") {
|
||||
Error(permissionCheckResponse, true);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
var guild = context.Guild;
|
||||
var config = Boyfriend.GetGuildConfig(guild.Id);
|
||||
|
||||
if (args.Length == 0) {
|
||||
var nl = Environment.NewLine;
|
||||
dynamic forCheck;
|
||||
var adminLogChannel = (forCheck = guild.GetTextChannel(config.AdminLogChannel.GetValueOrDefault(0))) == null
|
||||
? Messages.ChannelNotSpecified : forCheck.Mention;
|
||||
var botLogChannel = (forCheck = guild.GetTextChannel(config.BotLogChannel.GetValueOrDefault(0))) == null
|
||||
? Messages.ChannelNotSpecified : forCheck.Mention;
|
||||
var muteRole = (forCheck = guild.GetRole(config.MuteRole.GetValueOrDefault(0))) == null
|
||||
? Messages.RoleNotSpecified : forCheck.Mention;
|
||||
var defaultRole = (forCheck = guild.GetRole(config.DefaultRole.GetValueOrDefault(0))) == null
|
||||
? Messages.RoleNotSpecified : forCheck.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.GetValueOrDefault(false)), nl) +
|
||||
string.Format(Messages.CurrentSettingsUseSystemChannel,
|
||||
YesOrNo(config.UseSystemChannel.GetValueOrDefault(true)), nl) +
|
||||
string.Format(Messages.CurrentSettingsSendWelcomeMessages,
|
||||
YesOrNo(config.SendWelcomeMessages.GetValueOrDefault(true)), nl) +
|
||||
string.Format(Messages.CurrentSettingsReceiveStartupMessages,
|
||||
YesOrNo(config.ReceiveStartupMessages.GetValueOrDefault(true)), nl) +
|
||||
string.Format(Messages.CurrentSettingsWelcomeMessage, config.WelcomeMessage, nl) +
|
||||
string.Format(Messages.CurrentSettingsDefaultRole, defaultRole, nl) +
|
||||
string.Format(Messages.CurrentSettingsMuteRole, muteRole, nl) +
|
||||
string.Format(Messages.CurrentSettingsAdminLogChannel, adminLogChannel, nl) +
|
||||
string.Format(Messages.CurrentSettingsBotLogChannel, botLogChannel);
|
||||
await Utils.SilentSendAsync(context.Channel as ITextChannel ?? throw new ApplicationException(), toSend);
|
||||
return;
|
||||
var currentSettings = Boyfriend.StringBuilder.AppendLine(Messages.CurrentSettings);
|
||||
|
||||
foreach (var setting in Boyfriend.DefaultConfig) {
|
||||
var format = "{0}";
|
||||
var currentValue = config[setting.Key];
|
||||
|
||||
if (setting.Key.EndsWith("Channel")) {
|
||||
if (guild.GetTextChannel(Convert.ToUInt64(currentValue)) != null)
|
||||
format = "<#{0}>";
|
||||
else
|
||||
currentValue = Messages.ChannelNotSpecified;
|
||||
} else if (setting.Key.EndsWith("Role")) {
|
||||
if (guild.GetRole(Convert.ToUInt64(currentValue)) != null)
|
||||
format = "<@&{0}>";
|
||||
else
|
||||
currentValue = Messages.RoleNotSpecified;
|
||||
} else {
|
||||
if (IsBool(currentValue))
|
||||
currentValue = YesOrNo(currentValue == "true");
|
||||
else
|
||||
format = Utils.WrapInline("{0}")!;
|
||||
}
|
||||
|
||||
var setting = args[0].ToLower();
|
||||
var value = "";
|
||||
|
||||
if (args.Length >= 2)
|
||||
try {
|
||||
value = args[1].ToLower();
|
||||
} catch (IndexOutOfRangeException) {
|
||||
throw new ApplicationException(Messages.InvalidSettingValue);
|
||||
currentSettings.Append($"{Utils.GetMessage($"Settings{setting.Key}")} (`{setting.Key}`): ")
|
||||
.AppendFormat(format, currentValue).AppendLine();
|
||||
}
|
||||
|
||||
PropertyInfo? property = null;
|
||||
foreach (var prop in typeof(GuildConfig).GetProperties())
|
||||
if (setting == prop.Name.ToLower())
|
||||
property = prop;
|
||||
if (property == null || !property.CanWrite)
|
||||
throw new ApplicationException(Messages.SettingDoesntExist);
|
||||
var type = property.PropertyType;
|
||||
Output(ref currentSettings);
|
||||
currentSettings.Clear();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
var selectedSetting = args[0].ToLower();
|
||||
|
||||
var exists = false;
|
||||
foreach (var setting in Boyfriend.DefaultConfig) {
|
||||
if (selectedSetting != setting.Key.ToLower()) continue;
|
||||
selectedSetting = setting.Key;
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
Error(Messages.SettingDoesntExist, false);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
string value;
|
||||
|
||||
if (args.Length >= 2) {
|
||||
value = Utils.JoinString(ref args, 1);
|
||||
if (selectedSetting != "WelcomeMessage")
|
||||
value = value.Replace(" ", "").ToLower();
|
||||
if (value.StartsWith(",") || value.Count(x => x == ',') > 1) {
|
||||
Error(Messages.InvalidSettingValue, false);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
} else {
|
||||
value = "reset";
|
||||
}
|
||||
|
||||
if (IsBool(Boyfriend.DefaultConfig[selectedSetting]) && !IsBool(value)) {
|
||||
value = value switch {
|
||||
"y" or "yes" => "true",
|
||||
"n" or "no" => "false",
|
||||
_ => value
|
||||
};
|
||||
if (!IsBool(value)) {
|
||||
Error(Messages.InvalidSettingValue, false);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
var localizedSelectedSetting = Utils.GetMessage($"Settings{selectedSetting}");
|
||||
|
||||
var mention = Utils.ParseMention(value);
|
||||
if (mention != 0) value = mention.ToString();
|
||||
|
||||
var formatting = Utils.WrapInline("{0}")!;
|
||||
if (selectedSetting.EndsWith("Channel"))
|
||||
formatting = "<#{0}>";
|
||||
if (selectedSetting.EndsWith("Role"))
|
||||
formatting = "<@&{0}>";
|
||||
if (value is "0" or "reset" or "default")
|
||||
formatting = Messages.SettingNotDefined;
|
||||
var formattedValue = IsBool(value) ? YesOrNo(value == "true") : string.Format(formatting, value);
|
||||
|
||||
if (value is "reset" or "default") {
|
||||
property.SetValue(config, null);
|
||||
} else if (type == typeof(string)) {
|
||||
if (setting == "lang" && value is not ("ru" or "en"))
|
||||
throw new ApplicationException(Messages.LanguageNotSupported);
|
||||
property.SetValue(config, value);
|
||||
config[selectedSetting] = Boyfriend.DefaultConfig[selectedSetting];
|
||||
} else {
|
||||
try {
|
||||
if (type == typeof(bool?))
|
||||
property.SetValue(config, Convert.ToBoolean(value));
|
||||
|
||||
if (type == typeof(ulong?)) {
|
||||
var id = Convert.ToUInt64(value);
|
||||
if (property.Name.EndsWith("Channel") && guild.GetTextChannel(id) == null)
|
||||
throw new ApplicationException(Messages.InvalidChannel);
|
||||
if (property.Name.EndsWith("Role") && guild.GetRole(id) == null)
|
||||
throw new ApplicationException(Messages.InvalidRole);
|
||||
|
||||
property.SetValue(config, id);
|
||||
if (value == config[selectedSetting]) {
|
||||
Error(string.Format(Messages.SettingsNothingChanged, localizedSelectedSetting, formattedValue), false);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
} catch (Exception e) when (e is FormatException or OverflowException) {
|
||||
throw new ApplicationException(Messages.InvalidSettingValue);
|
||||
}
|
||||
}
|
||||
config.Validate();
|
||||
|
||||
await config.Save();
|
||||
await context.Channel.SendMessageAsync(Messages.SettingsUpdated);
|
||||
if (selectedSetting == "Lang" && value is not "ru" and not "en") {
|
||||
Error(Messages.LanguageNotSupported, false);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
if (selectedSetting.EndsWith("Channel") && guild.GetTextChannel(mention) == null) {
|
||||
Error(Messages.InvalidChannel, false);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
if (selectedSetting.EndsWith("Role") && guild.GetRole(mention) == null) {
|
||||
Error(Messages.InvalidRole, false);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
config[selectedSetting] = value;
|
||||
}
|
||||
|
||||
if (selectedSetting == "Lang") {
|
||||
Utils.SetCurrentLanguage(guild.Id);
|
||||
localizedSelectedSetting = Utils.GetMessage($"Settings{selectedSetting}");
|
||||
}
|
||||
|
||||
CommandHandler.ConfigWriteScheduled = true;
|
||||
|
||||
Success(string.Format(Messages.FeedbackSettingsUpdated, localizedSelectedSetting, formattedValue),
|
||||
author.Mention);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
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 "Настраивает бота отдельно для этого сервера";
|
||||
private static bool IsBool(string value) {
|
||||
return value is "true" or "false";
|
||||
}
|
||||
}
|
|
@ -1,48 +1,45 @@
|
|||
using Discord;
|
||||
using Discord.Commands;
|
||||
|
||||
// ReSharper disable UnusedType.Global
|
||||
// ReSharper disable UnusedMember.Global
|
||||
// ReSharper disable ClassNeverInstantiated.Global
|
||||
using Discord.WebSocket;
|
||||
|
||||
namespace Boyfriend.Commands;
|
||||
|
||||
public class UnbanCommand : Command {
|
||||
public override string[] Aliases { get; } = {"unban", "разбан"};
|
||||
public override int ArgsLengthRequired => 2;
|
||||
|
||||
public override async Task Run(SocketCommandContext context, string[] args) {
|
||||
await UnbanUser(context.Guild, context.Channel as ITextChannel, context.Guild.GetUser(context.User.Id),
|
||||
await Utils.ParseUser(args[0]), Utils.JoinString(args, 1));
|
||||
var author = (SocketGuildUser) context.User;
|
||||
|
||||
var permissionCheckResponse = CommandHandler.HasPermission(ref author, GuildPermission.BanMembers);
|
||||
if (permissionCheckResponse != "") {
|
||||
Error(permissionCheckResponse, true);
|
||||
return;
|
||||
}
|
||||
|
||||
public static async Task UnbanUser(IGuild guild, ITextChannel? channel, IGuildUser author, IUser toUnban,
|
||||
string reason) {
|
||||
var toUnban = Utils.ParseUser(args[0]);
|
||||
|
||||
var authorMention = author.Mention;
|
||||
var notification = string.Format(Messages.UserUnbanned, authorMention, toUnban.Mention,
|
||||
Utils.WrapInline(reason));
|
||||
var requestOptions = Utils.GetRequestOptions($"({Utils.GetNameAndDiscrim(author)}) {reason}");
|
||||
if (toUnban == null) {
|
||||
Error(Messages.UserDoesntExist, false);
|
||||
return;
|
||||
}
|
||||
|
||||
await CommandHandler.CheckPermissions(author, GuildPermission.BanMembers);
|
||||
var reason = Utils.JoinString(ref args, 1);
|
||||
|
||||
if (guild.GetBanAsync(toUnban.Id) == null)
|
||||
throw new ApplicationException(Messages.UserNotBanned);
|
||||
await UnbanUser(context.Guild, author, toUnban, reason);
|
||||
}
|
||||
|
||||
public static async Task UnbanUser(SocketGuild guild, SocketGuildUser author, SocketUser toUnban, string reason) {
|
||||
if (guild.GetBanAsync(toUnban.Id) == null) {
|
||||
Error(Messages.UserNotBanned, false);
|
||||
return;
|
||||
}
|
||||
|
||||
var requestOptions = Utils.GetRequestOptions($"({author}) {reason}");
|
||||
await guild.RemoveBanAsync(toUnban, requestOptions);
|
||||
|
||||
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 "Возвращает пользователя из бана";
|
||||
var feedback = string.Format(Messages.FeedbackUserUnbanned, toUnban.Mention, Utils.WrapInline(reason));
|
||||
Success(feedback, author.Mention, false, false);
|
||||
await Utils.SendFeedback(feedback, guild.Id, author.Mention, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,71 +1,78 @@
|
|||
using Discord;
|
||||
using Discord.Commands;
|
||||
|
||||
// ReSharper disable UnusedType.Global
|
||||
// ReSharper disable UnusedMember.Global
|
||||
// ReSharper disable ClassNeverInstantiated.Global
|
||||
using Discord.WebSocket;
|
||||
|
||||
namespace Boyfriend.Commands;
|
||||
|
||||
public class UnmuteCommand : Command {
|
||||
public override string[] Aliases { get; } = {"unmute", "размут"};
|
||||
public override int ArgsLengthRequired => 2;
|
||||
|
||||
public override async Task Run(SocketCommandContext context, string[] args) {
|
||||
await UnmuteMember(context.Guild, context.Channel as ITextChannel, context.Guild.GetUser(context.User.Id),
|
||||
await Utils.ParseMember(context.Guild, args[0]), Utils.JoinString(args, 1));
|
||||
var author = (SocketGuildUser) context.User;
|
||||
|
||||
var permissionCheckResponse = CommandHandler.HasPermission(ref author, GuildPermission.ModerateMembers);
|
||||
if (permissionCheckResponse != "") {
|
||||
Error(permissionCheckResponse, true);
|
||||
return;
|
||||
}
|
||||
|
||||
public static async Task UnmuteMember(IGuild guild, ITextChannel? channel, IGuildUser author, IGuildUser toUnmute,
|
||||
var toUnmute = Utils.ParseMember(context.Guild, args[0]);
|
||||
|
||||
if (toUnmute == null) {
|
||||
Error(Messages.UserDoesntExist, false);
|
||||
return;
|
||||
}
|
||||
|
||||
var interactionCheckResponse = CommandHandler.CanInteract(ref author, ref toUnmute);
|
||||
if (interactionCheckResponse != "") {
|
||||
Error(interactionCheckResponse, true);
|
||||
return;
|
||||
}
|
||||
|
||||
var reason = Utils.JoinString(ref args, 1);
|
||||
await UnmuteMember(context.Guild, author, toUnmute, reason);
|
||||
}
|
||||
|
||||
public static async Task UnmuteMember(SocketGuild guild, SocketGuildUser author, SocketGuildUser toUnmute,
|
||||
string reason) {
|
||||
await CommandHandler.CheckPermissions(author, GuildPermission.ModerateMembers, GuildPermission.ManageRoles);
|
||||
await CommandHandler.CheckInteractions(author, toUnmute);
|
||||
var authorMention = author.Mention;
|
||||
var config = Boyfriend.GetGuildConfig(guild);
|
||||
var notification = string.Format(Messages.MemberUnmuted, authorMention, toUnmute.Mention,
|
||||
Utils.WrapInline(reason));
|
||||
var requestOptions = Utils.GetRequestOptions($"({Utils.GetNameAndDiscrim(author)}) {reason}");
|
||||
var role = Utils.GetMuteRole(guild);
|
||||
var requestOptions = Utils.GetRequestOptions($"({author}) {reason}");
|
||||
var role = Utils.GetMuteRole(ref guild);
|
||||
|
||||
if (role != null) {
|
||||
if (toUnmute.RoleIds.All(x => x != role.Id)) {
|
||||
var rolesRemoved = config.RolesRemovedOnMute;
|
||||
|
||||
await toUnmute.AddRolesAsync(rolesRemoved![toUnmute.Id]);
|
||||
rolesRemoved.Remove(toUnmute.Id);
|
||||
await config.Save();
|
||||
throw new ApplicationException(Messages.RolesReturned);
|
||||
var muted = false;
|
||||
foreach (var x in toUnmute.Roles) {
|
||||
if (x != role) continue;
|
||||
muted = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (toUnmute.RoleIds.All(x => x != role.Id))
|
||||
throw new ApplicationException(Messages.MemberNotMuted);
|
||||
var rolesRemoved = Boyfriend.GetRemovedRoles(guild.Id);
|
||||
|
||||
if (rolesRemoved.ContainsKey(toUnmute.Id)) {
|
||||
await toUnmute.AddRolesAsync(rolesRemoved[toUnmute.Id]);
|
||||
rolesRemoved.Remove(toUnmute.Id);
|
||||
CommandHandler.ConfigWriteScheduled = true;
|
||||
}
|
||||
|
||||
if (muted) {
|
||||
await toUnmute.RemoveRoleAsync(role, requestOptions);
|
||||
if (config.RolesRemovedOnMute!.ContainsKey(toUnmute.Id)) {
|
||||
await toUnmute.AddRolesAsync(config.RolesRemovedOnMute[toUnmute.Id]);
|
||||
config.RolesRemovedOnMute.Remove(toUnmute.Id);
|
||||
await config.Save();
|
||||
} else {
|
||||
Error(Messages.MemberNotMuted, false);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (toUnmute.TimedOutUntil == null || toUnmute.TimedOutUntil.Value.ToUnixTimeMilliseconds()
|
||||
< DateTimeOffset.Now.ToUnixTimeMilliseconds())
|
||||
throw new ApplicationException(Messages.MemberNotMuted);
|
||||
if (toUnmute.TimedOutUntil == null || toUnmute.TimedOutUntil.Value.ToUnixTimeMilliseconds() <
|
||||
DateTimeOffset.Now.ToUnixTimeMilliseconds()) {
|
||||
Error(Messages.MemberNotMuted, false);
|
||||
return;
|
||||
}
|
||||
|
||||
await toUnmute.RemoveTimeOutAsync();
|
||||
}
|
||||
|
||||
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 "Снимает мут с участника";
|
||||
var feedback = string.Format(Messages.FeedbackMemberUnmuted, toUnmute.Mention, Utils.WrapInline(reason));
|
||||
Success(feedback, author.Mention, false, false);
|
||||
await Utils.SendFeedback(feedback, guild.Id, author.Mention, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System.Globalization;
|
||||
using Boyfriend.Commands;
|
||||
using Boyfriend.Commands;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
|
@ -15,61 +14,75 @@ public class EventHandler {
|
|||
_client.MessageReceived += MessageReceivedEvent;
|
||||
_client.MessageUpdated += MessageUpdatedEvent;
|
||||
_client.UserJoined += UserJoinedEvent;
|
||||
_client.GuildScheduledEventCreated += ScheduledEventCreatedEvent;
|
||||
_client.GuildScheduledEventCancelled += ScheduledEventCancelledEvent;
|
||||
_client.GuildScheduledEventStarted += ScheduledEventStartedEvent;
|
||||
_client.GuildScheduledEventCompleted += ScheduledEventCompletedEvent;
|
||||
}
|
||||
|
||||
private static async Task ReadyEvent() {
|
||||
await Boyfriend.SetupGuildConfigs();
|
||||
|
||||
var i = new Random().Next(3);
|
||||
var i = Utils.Random.Next(3);
|
||||
|
||||
foreach (var guild in Boyfriend.Client.Guilds) {
|
||||
var config = Boyfriend.GetGuildConfig(guild);
|
||||
var channel = guild.GetTextChannel(config.BotLogChannel.GetValueOrDefault(0));
|
||||
Messages.Culture = new CultureInfo(config.Lang!);
|
||||
var config = Boyfriend.GetGuildConfig(guild.Id);
|
||||
var channel = guild.GetTextChannel(Convert.ToUInt64(config["BotLogChannel"]));
|
||||
Utils.SetCurrentLanguage(guild.Id);
|
||||
|
||||
if (!config.ReceiveStartupMessages.GetValueOrDefault(true) || channel == null) continue;
|
||||
await channel.SendMessageAsync(string.Format(Messages.Ready, Utils.GetBeep(config.Lang!, i)));
|
||||
if (config["ReceiveStartupMessages"] != "true" || channel == null) continue;
|
||||
await channel.SendMessageAsync(string.Format(Messages.Ready, Utils.GetBeep(i)));
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task MessageDeletedEvent(Cacheable<IMessage, ulong> message,
|
||||
Cacheable<IMessageChannel, ulong> channel) {
|
||||
var msg = message.Value;
|
||||
if (msg is null or ISystemMessage || msg.Author.IsBot) return;
|
||||
|
||||
var toSend = msg == null ? string.Format(Messages.UncachedMessageDeleted, Utils.MentionChannel(channel.Id))
|
||||
: string.Format(Messages.CachedMessageDeleted, msg.Author.Mention) +
|
||||
$"{Utils.MentionChannel(channel.Id)}: {Environment.NewLine}{Utils.Wrap(msg.Content)}";
|
||||
await Utils.SilentSendAsync(await Utils.GetAdminLogChannel(Boyfriend.FindGuild(channel.Value)), toSend);
|
||||
var guild = Boyfriend.FindGuild(channel.Value.Id);
|
||||
|
||||
Utils.SetCurrentLanguage(guild.Id);
|
||||
|
||||
var auditLogEntry = (await guild.GetAuditLogsAsync(1).FlattenAsync()).First();
|
||||
var mention = auditLogEntry.User.Mention;
|
||||
if (auditLogEntry.Action != ActionType.MessageDeleted ||
|
||||
DateTimeOffset.Now.Subtract(auditLogEntry.CreatedAt).TotalMilliseconds > 500 ||
|
||||
auditLogEntry.User.IsBot) mention = msg.Author.Mention;
|
||||
|
||||
await Utils.SendFeedback(
|
||||
string.Format(Messages.CachedMessageDeleted, msg.Author.Mention, Utils.MentionChannel(channel.Id),
|
||||
Utils.WrapAsNeeded(msg.CleanContent)), guild.Id, mention);
|
||||
}
|
||||
|
||||
private static async Task MessageReceivedEvent(SocketMessage messageParam) {
|
||||
if (messageParam is not SocketUserMessage message) return;
|
||||
|
||||
var argPos = 0;
|
||||
var user = (IGuildUser) message.Author;
|
||||
var user = (SocketGuildUser) message.Author;
|
||||
var guild = user.Guild;
|
||||
var guildConfig = Boyfriend.GetGuildConfig(guild);
|
||||
var guildConfig = Boyfriend.GetGuildConfig(guild.Id);
|
||||
|
||||
Utils.SetCurrentLanguage(guild.Id);
|
||||
|
||||
if ((message.MentionedUsers.Count > 3 || message.MentionedRoles.Count > 2) &&
|
||||
!user.GuildPermissions.MentionEveryone) {
|
||||
await BanCommand.BanUser(guild, guild.CurrentUser, user, TimeSpan.FromMilliseconds(-1),
|
||||
Messages.AutobanReason);
|
||||
return;
|
||||
}
|
||||
|
||||
var argPos = 0;
|
||||
var prev = "";
|
||||
var prevFailsafe = "";
|
||||
var prevs = await message.Channel.GetMessagesAsync(3).FlattenAsync();
|
||||
var prevsArray = prevs as IMessage[] ?? prevs.ToArray();
|
||||
|
||||
Messages.Culture = new CultureInfo(guildConfig.Lang!);
|
||||
|
||||
if ((message.MentionedUsers.Count > 3 || message.MentionedRoles.Count > 2) &&
|
||||
!user.GuildPermissions.MentionEveryone)
|
||||
await BanCommand.BanUser(guild, null, await guild.GetCurrentUserAsync(), user,
|
||||
TimeSpan.FromMilliseconds(-1), Messages.AutobanReason);
|
||||
|
||||
try {
|
||||
if (prevsArray.Length >= 3) {
|
||||
prev = prevsArray[1].Content;
|
||||
prevFailsafe = prevsArray[2].Content;
|
||||
} catch (IndexOutOfRangeException) {}
|
||||
}
|
||||
|
||||
if (!(message.HasStringPrefix(guildConfig.Prefix, ref argPos) ||
|
||||
message.HasMentionPrefix(Boyfriend.Client.CurrentUser, ref argPos)) ||
|
||||
user == await guild.GetCurrentUserAsync() ||
|
||||
user.IsBot && (message.Content.Contains(prev) || message.Content.Contains(prevFailsafe)))
|
||||
if (!(message.HasStringPrefix(guildConfig["Prefix"], ref argPos) ||
|
||||
message.HasMentionPrefix(Boyfriend.Client.CurrentUser, ref argPos)) || user == guild.CurrentUser ||
|
||||
(user.IsBot && (message.Content.Contains(prev) || message.Content.Contains(prevFailsafe))))
|
||||
return;
|
||||
|
||||
await CommandHandler.HandleCommand(message);
|
||||
|
@ -78,27 +91,89 @@ public class EventHandler {
|
|||
private static async Task MessageUpdatedEvent(Cacheable<IMessage, ulong> messageCached, SocketMessage messageSocket,
|
||||
ISocketMessageChannel channel) {
|
||||
var msg = messageCached.Value;
|
||||
var nl = Environment.NewLine;
|
||||
|
||||
if (msg != null && msg.Content == messageSocket.Content) return;
|
||||
if (msg is null or ISystemMessage || msg.CleanContent == messageSocket.CleanContent || msg.Author.IsBot) return;
|
||||
|
||||
var toSend = msg == null
|
||||
? string.Format(Messages.UncachedMessageEdited, messageSocket.Author.Mention,
|
||||
Utils.MentionChannel(channel.Id)) + Utils.Wrap(messageSocket.Content) : string.Format(
|
||||
Messages.CachedMessageEdited, msg.Author.Mention, Utils.MentionChannel(channel.Id), nl, nl,
|
||||
Utils.Wrap(msg.Content), nl, nl, Utils.Wrap(messageSocket.Content));
|
||||
await Utils.SilentSendAsync(await Utils.GetAdminLogChannel(Boyfriend.FindGuild(channel)), toSend);
|
||||
var guildId = Boyfriend.FindGuild(channel.Id).Id;
|
||||
|
||||
Utils.SetCurrentLanguage(guildId);
|
||||
|
||||
await Utils.SendFeedback(
|
||||
string.Format(Messages.CachedMessageEdited, Utils.MentionChannel(channel.Id),
|
||||
Utils.WrapAsNeeded(msg.CleanContent), Utils.WrapAsNeeded(messageSocket.Content)), guildId,
|
||||
msg.Author.Mention);
|
||||
}
|
||||
|
||||
private static async Task UserJoinedEvent(SocketGuildUser user) {
|
||||
var guild = user.Guild;
|
||||
var config = Boyfriend.GetGuildConfig(guild);
|
||||
var config = Boyfriend.GetGuildConfig(guild.Id);
|
||||
|
||||
if (config.SendWelcomeMessages.GetValueOrDefault(true))
|
||||
if (config["SendWelcomeMessages"] == "true")
|
||||
await Utils.SilentSendAsync(guild.SystemChannel,
|
||||
string.Format(config.WelcomeMessage!, user.Mention, guild.Name));
|
||||
string.Format(config["WelcomeMessage"], user.Mention, guild.Name));
|
||||
|
||||
if (config.DefaultRole != 0)
|
||||
await user.AddRoleAsync(Utils.ParseRole(guild, config.DefaultRole.ToString()!));
|
||||
if (config["StarterRole"] != "0")
|
||||
await user.AddRoleAsync(ulong.Parse(config["StarterRole"]));
|
||||
}
|
||||
|
||||
private static async Task ScheduledEventCreatedEvent(SocketGuildEvent scheduledEvent) {
|
||||
var guild = scheduledEvent.Guild;
|
||||
var eventConfig = Boyfriend.GetGuildConfig(guild.Id);
|
||||
var channel = guild.GetTextChannel(Convert.ToUInt64(eventConfig["EventCreatedChannel"]));
|
||||
|
||||
if (channel != null) {
|
||||
var roleMention = "";
|
||||
var role = guild.GetRole(Convert.ToUInt64(eventConfig["EventNotifyReceiverRole"]));
|
||||
if (role != null)
|
||||
roleMention = $"{role.Mention} ";
|
||||
|
||||
var location = Utils.WrapInline(scheduledEvent.Location) ?? Utils.MentionChannel(scheduledEvent.Channel.Id);
|
||||
|
||||
await Utils.SilentSendAsync(channel,
|
||||
string.Format(Messages.EventCreated, "\n", roleMention, scheduledEvent.Creator.Mention,
|
||||
Utils.WrapInline(scheduledEvent.Name), location,
|
||||
scheduledEvent.StartTime.ToUnixTimeSeconds().ToString(), Utils.Wrap(scheduledEvent.Description)),
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task ScheduledEventCancelledEvent(SocketGuildEvent scheduledEvent) {
|
||||
var guild = scheduledEvent.Guild;
|
||||
var eventConfig = Boyfriend.GetGuildConfig(guild.Id);
|
||||
var channel = guild.GetTextChannel(Convert.ToUInt64(eventConfig["EventCancelledChannel"]));
|
||||
if (channel != null)
|
||||
await channel.SendMessageAsync(string.Format(Messages.EventCancelled, Utils.WrapInline(scheduledEvent.Name),
|
||||
eventConfig["FrowningFace"] == "true" ? $" {Messages.SettingsFrowningFace}" : ""));
|
||||
}
|
||||
|
||||
private static async Task ScheduledEventStartedEvent(SocketGuildEvent scheduledEvent) {
|
||||
var guild = scheduledEvent.Guild;
|
||||
var eventConfig = Boyfriend.GetGuildConfig(guild.Id);
|
||||
var channel = guild.GetTextChannel(Convert.ToUInt64(eventConfig["EventStartedChannel"]));
|
||||
|
||||
if (channel != null) {
|
||||
var receivers = eventConfig["EventStartedReceivers"];
|
||||
var role = guild.GetRole(Convert.ToUInt64(eventConfig["EventNotifyReceiverRole"]));
|
||||
var mentions = Boyfriend.StringBuilder;
|
||||
|
||||
if (receivers.Contains("role") && role != null) mentions.Append($"{role.Mention} ");
|
||||
if (receivers.Contains("users") || receivers.Contains("interested"))
|
||||
foreach (var user in await scheduledEvent.GetUsersAsync(15))
|
||||
mentions = mentions.Append($"{user.Mention} ");
|
||||
|
||||
await channel.SendMessageAsync(string.Format(Messages.EventStarted, mentions,
|
||||
Utils.WrapInline(scheduledEvent.Name),
|
||||
Utils.WrapInline(scheduledEvent.Location) ?? Utils.MentionChannel(scheduledEvent.Channel.Id)));
|
||||
mentions.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task ScheduledEventCompletedEvent(SocketGuildEvent scheduledEvent) {
|
||||
var guild = scheduledEvent.Guild;
|
||||
var eventConfig = Boyfriend.GetGuildConfig(guild.Id);
|
||||
var channel = guild.GetTextChannel(Convert.ToUInt64(eventConfig["EventCompletedChannel"]));
|
||||
if (channel != null)
|
||||
await channel.SendMessageAsync(string.Format(Messages.EventCompleted, Utils.WrapInline(scheduledEvent.Name),
|
||||
Utils.WrapInline(scheduledEvent.StartTime.Subtract(DateTimeOffset.Now).Negate().ToString())));
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
using System.Globalization;
|
||||
using Newtonsoft.Json;
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
|
||||
namespace Boyfriend;
|
||||
|
||||
public class GuildConfig {
|
||||
|
||||
public GuildConfig(ulong id) {
|
||||
Id = id;
|
||||
Validate();
|
||||
}
|
||||
public ulong? Id { get; }
|
||||
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 bool? ReceiveStartupMessages { get; set; }
|
||||
|
||||
public string? WelcomeMessage { get; set; }
|
||||
|
||||
public ulong? DefaultRole { get; set; }
|
||||
public ulong? MuteRole { get; set; }
|
||||
public ulong? AdminLogChannel { get; set; }
|
||||
public ulong? BotLogChannel { get; set; }
|
||||
|
||||
public Dictionary<ulong, List<ulong>>? RolesRemovedOnMute { get; private set; }
|
||||
|
||||
public void Validate() {
|
||||
if (Id == null) throw new Exception("Something went horribly, horribly wrong");
|
||||
|
||||
Lang ??= "ru";
|
||||
Messages.Culture = new CultureInfo(Lang);
|
||||
Prefix ??= "!";
|
||||
RemoveRolesOnMute ??= false;
|
||||
UseSystemChannel ??= true;
|
||||
SendWelcomeMessages ??= true;
|
||||
ReceiveStartupMessages ??= true;
|
||||
WelcomeMessage ??= Messages.DefaultWelcomeMessage;
|
||||
DefaultRole ??= 0;
|
||||
MuteRole ??= 0;
|
||||
AdminLogChannel ??= 0;
|
||||
BotLogChannel ??= 0;
|
||||
RolesRemovedOnMute ??= new Dictionary<ulong, List<ulong>>();
|
||||
}
|
||||
|
||||
public async Task Save() {
|
||||
Validate();
|
||||
RolesRemovedOnMute!.TrimExcess();
|
||||
|
||||
await File.WriteAllTextAsync("config_" + Id + ".json", JsonConvert.SerializeObject(this));
|
||||
}
|
||||
}
|
552
Boyfriend/Messages.Designer.cs
generated
552
Boyfriend/Messages.Designer.cs
generated
|
@ -69,15 +69,6 @@ namespace Boyfriend {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to :white_check_mark: Successfully banned {0} for {1}.
|
||||
/// </summary>
|
||||
internal static string BanResponse {
|
||||
get {
|
||||
return ResourceManager.GetString("BanResponse", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Bah! .
|
||||
/// </summary>
|
||||
|
@ -106,7 +97,7 @@ namespace Boyfriend {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Deleted message from {0} in channel .
|
||||
/// Looks up a localized string similar to Deleted message from {0} in channel {1}: {2}.
|
||||
/// </summary>
|
||||
internal static string CachedMessageDeleted {
|
||||
get {
|
||||
|
@ -115,7 +106,7 @@ namespace Boyfriend {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Message edited from {0} in channel {1}.{2}Before:{3}{4}{5}After:{6}{7}.
|
||||
/// Looks up a localized string similar to Edited message in channel {0}: {1} -> {2}.
|
||||
/// </summary>
|
||||
internal static string CachedMessageEdited {
|
||||
get {
|
||||
|
@ -169,7 +160,88 @@ namespace Boyfriend {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Command help:{0}.
|
||||
/// Looks up a localized string similar to Bans a user.
|
||||
/// </summary>
|
||||
internal static string CommandDescriptionBan {
|
||||
get {
|
||||
return ResourceManager.GetString("CommandDescriptionBan", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Deletes a specified amount of messages in this channel.
|
||||
/// </summary>
|
||||
internal static string CommandDescriptionClear {
|
||||
get {
|
||||
return ResourceManager.GetString("CommandDescriptionClear", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Shows this message.
|
||||
/// </summary>
|
||||
internal static string CommandDescriptionHelp {
|
||||
get {
|
||||
return ResourceManager.GetString("CommandDescriptionHelp", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Kicks a member.
|
||||
/// </summary>
|
||||
internal static string CommandDescriptionKick {
|
||||
get {
|
||||
return ResourceManager.GetString("CommandDescriptionKick", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Mutes a member.
|
||||
/// </summary>
|
||||
internal static string CommandDescriptionMute {
|
||||
get {
|
||||
return ResourceManager.GetString("CommandDescriptionMute", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Shows latency to Discord servers (not counting local processing time).
|
||||
/// </summary>
|
||||
internal static string CommandDescriptionPing {
|
||||
get {
|
||||
return ResourceManager.GetString("CommandDescriptionPing", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Allows you to change certain preferences for this guild.
|
||||
/// </summary>
|
||||
internal static string CommandDescriptionSettings {
|
||||
get {
|
||||
return ResourceManager.GetString("CommandDescriptionSettings", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unbans a user.
|
||||
/// </summary>
|
||||
internal static string CommandDescriptionUnban {
|
||||
get {
|
||||
return ResourceManager.GetString("CommandDescriptionUnban", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unmutes a member.
|
||||
/// </summary>
|
||||
internal static string CommandDescriptionUnmute {
|
||||
get {
|
||||
return ResourceManager.GetString("CommandDescriptionUnmute", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Command help:.
|
||||
/// </summary>
|
||||
internal static string CommandHelp {
|
||||
get {
|
||||
|
@ -205,7 +277,7 @@ namespace Boyfriend {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Current settings:{0}.
|
||||
/// Looks up a localized string similar to Current settings:.
|
||||
/// </summary>
|
||||
internal static string CurrentSettings {
|
||||
get {
|
||||
|
@ -213,105 +285,6 @@ namespace Boyfriend {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Admin log channel (`adminLogChannel`): {0}{1}.
|
||||
/// </summary>
|
||||
internal static string CurrentSettingsAdminLogChannel {
|
||||
get {
|
||||
return ResourceManager.GetString("CurrentSettingsAdminLogChannel", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Bot log channel (`botLogChannel`): {0}.
|
||||
/// </summary>
|
||||
internal static string CurrentSettingsBotLogChannel {
|
||||
get {
|
||||
return ResourceManager.GetString("CurrentSettingsBotLogChannel", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Default role (`defaultRole`): {0}{1}.
|
||||
/// </summary>
|
||||
internal static string CurrentSettingsDefaultRole {
|
||||
get {
|
||||
return ResourceManager.GetString("CurrentSettingsDefaultRole", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Language (`lang`): `{0}`{1}.
|
||||
/// </summary>
|
||||
internal static string CurrentSettingsLang {
|
||||
get {
|
||||
return ResourceManager.GetString("CurrentSettingsLang", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Mute role (`muteRole`): {0}{1}.
|
||||
/// </summary>
|
||||
internal static string CurrentSettingsMuteRole {
|
||||
get {
|
||||
return ResourceManager.GetString("CurrentSettingsMuteRole", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Prefix (`prefix`): `{0}`{1}.
|
||||
/// </summary>
|
||||
internal static string CurrentSettingsPrefix {
|
||||
get {
|
||||
return ResourceManager.GetString("CurrentSettingsPrefix", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Receive startup messages (`receiveStartupMessages`): {0}{1}.
|
||||
/// </summary>
|
||||
internal static string CurrentSettingsReceiveStartupMessages {
|
||||
get {
|
||||
return ResourceManager.GetString("CurrentSettingsReceiveStartupMessages", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Remove roles on mute (`removeRolesOnMute`): {0}{1}.
|
||||
/// </summary>
|
||||
internal static string CurrentSettingsRemoveRoles {
|
||||
get {
|
||||
return ResourceManager.GetString("CurrentSettingsRemoveRoles", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Send welcome messages (`sendWelcomeMessages`): {0}{1}.
|
||||
/// </summary>
|
||||
internal static string CurrentSettingsSendWelcomeMessages {
|
||||
get {
|
||||
return ResourceManager.GetString("CurrentSettingsSendWelcomeMessages", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Use system channel for notifications (`useSystemChannel`): {0}{1}.
|
||||
/// </summary>
|
||||
internal static string CurrentSettingsUseSystemChannel {
|
||||
get {
|
||||
return ResourceManager.GetString("CurrentSettingsUseSystemChannel", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Welcome message: `{0}`{1}.
|
||||
/// </summary>
|
||||
internal static string CurrentSettingsWelcomeMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("CurrentSettingsWelcomeMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0}, welcome to {1}.
|
||||
/// </summary>
|
||||
|
@ -339,6 +312,123 @@ namespace Boyfriend {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Event {0} is cancelled!{1}.
|
||||
/// </summary>
|
||||
internal static string EventCancelled {
|
||||
get {
|
||||
return ResourceManager.GetString("EventCancelled", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Event {0} has completed! Duration: {1}.
|
||||
/// </summary>
|
||||
internal static string EventCompleted {
|
||||
get {
|
||||
return ResourceManager.GetString("EventCompleted", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {1}{2} created event {3}! It will take place in {4} and will start <t:{5}:R>!{0}{6}.
|
||||
/// </summary>
|
||||
internal static string EventCreated {
|
||||
get {
|
||||
return ResourceManager.GetString("EventCreated", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0}Event {1} is starting at {2}!.
|
||||
/// </summary>
|
||||
internal static string EventStarted {
|
||||
get {
|
||||
return ResourceManager.GetString("EventStarted", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to ever.
|
||||
/// </summary>
|
||||
internal static string Ever {
|
||||
get {
|
||||
return ResourceManager.GetString("Ever", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to *[{0}: {1}]*.
|
||||
/// </summary>
|
||||
internal static string FeedbackFormat {
|
||||
get {
|
||||
return ResourceManager.GetString("FeedbackFormat", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Kicked {0}: {1}.
|
||||
/// </summary>
|
||||
internal static string FeedbackMemberKicked {
|
||||
get {
|
||||
return ResourceManager.GetString("FeedbackMemberKicked", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Muted {0} for{1}: {2}.
|
||||
/// </summary>
|
||||
internal static string FeedbackMemberMuted {
|
||||
get {
|
||||
return ResourceManager.GetString("FeedbackMemberMuted", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unmuted {0}: {1}.
|
||||
/// </summary>
|
||||
internal static string FeedbackMemberUnmuted {
|
||||
get {
|
||||
return ResourceManager.GetString("FeedbackMemberUnmuted", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Deleted {0} messages in {1}.
|
||||
/// </summary>
|
||||
internal static string FeedbackMessagesCleared {
|
||||
get {
|
||||
return ResourceManager.GetString("FeedbackMessagesCleared", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Value of setting `{0}` is now set to {1}.
|
||||
/// </summary>
|
||||
internal static string FeedbackSettingsUpdated {
|
||||
get {
|
||||
return ResourceManager.GetString("FeedbackSettingsUpdated", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Banned {0} for{1}: {2}.
|
||||
/// </summary>
|
||||
internal static string FeedbackUserBanned {
|
||||
get {
|
||||
return ResourceManager.GetString("FeedbackUserBanned", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unbanned {0}: {1}.
|
||||
/// </summary>
|
||||
internal static string FeedbackUserUnbanned {
|
||||
get {
|
||||
return ResourceManager.GetString("FeedbackUserUnbanned", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Members are in different guilds!.
|
||||
/// </summary>
|
||||
|
@ -420,15 +510,6 @@ namespace Boyfriend {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to :white_check_mark: Successfully kicked {0} for {1}.
|
||||
/// </summary>
|
||||
internal static string KickResponse {
|
||||
get {
|
||||
return ResourceManager.GetString("KickResponse", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Language not supported!.
|
||||
/// </summary>
|
||||
|
@ -447,24 +528,6 @@ namespace Boyfriend {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0} kicked {1} for {2}.
|
||||
/// </summary>
|
||||
internal static string MemberKicked {
|
||||
get {
|
||||
return ResourceManager.GetString("MemberKicked", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0} muted {1} for {2}{3}.
|
||||
/// </summary>
|
||||
internal static string MemberMuted {
|
||||
get {
|
||||
return ResourceManager.GetString("MemberMuted", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Member not muted!.
|
||||
/// </summary>
|
||||
|
@ -483,15 +546,6 @@ namespace Boyfriend {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0} deleted {1} messages in channel {2}.
|
||||
/// </summary>
|
||||
internal static string MessagesDeleted {
|
||||
get {
|
||||
return ResourceManager.GetString("MessagesDeleted", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to ms.
|
||||
/// </summary>
|
||||
|
@ -501,15 +555,6 @@ namespace Boyfriend {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to :white_check_mark: Successfully muted {0} for {1}.
|
||||
/// </summary>
|
||||
internal static string MuteResponse {
|
||||
get {
|
||||
return ResourceManager.GetString("MuteResponse", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to No.
|
||||
/// </summary>
|
||||
|
@ -537,15 +582,6 @@ namespace Boyfriend {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0}This punishment will expire <t:{1}:R>.
|
||||
/// </summary>
|
||||
internal static string PunishmentExpiresIn {
|
||||
get {
|
||||
return ResourceManager.GetString("PunishmentExpiresIn", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0}I'm ready! (C#).
|
||||
/// </summary>
|
||||
|
@ -592,25 +628,178 @@ namespace Boyfriend {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Settings successfully updated.
|
||||
/// Looks up a localized string similar to Not specified.
|
||||
/// </summary>
|
||||
internal static string SettingsUpdated {
|
||||
internal static string SettingNotDefined {
|
||||
get {
|
||||
return ResourceManager.GetString("SettingsUpdated", resourceCulture);
|
||||
return ResourceManager.GetString("SettingNotDefined", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to :white_check_mark: Successfully unbanned {0} for {1}.
|
||||
/// Looks up a localized string similar to Admin log channel.
|
||||
/// </summary>
|
||||
internal static string UnbanResponse {
|
||||
internal static string SettingsAdminLogChannel {
|
||||
get {
|
||||
return ResourceManager.GetString("UnbanResponse", resourceCulture);
|
||||
return ResourceManager.GetString("SettingsAdminLogChannel", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Deleted message in {0}, but I forgot what was there.
|
||||
/// Looks up a localized string similar to Bot log channel.
|
||||
/// </summary>
|
||||
internal static string SettingsBotLogChannel {
|
||||
get {
|
||||
return ResourceManager.GetString("SettingsBotLogChannel", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Channel for event cancellation notifications.
|
||||
/// </summary>
|
||||
internal static string SettingsEventCancelledChannel {
|
||||
get {
|
||||
return ResourceManager.GetString("SettingsEventCancelledChannel", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Channel for event completion notifications.
|
||||
/// </summary>
|
||||
internal static string SettingsEventCompletedChannel {
|
||||
get {
|
||||
return ResourceManager.GetString("SettingsEventCompletedChannel", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Channel for event creation notifications.
|
||||
/// </summary>
|
||||
internal static string SettingsEventCreatedChannel {
|
||||
get {
|
||||
return ResourceManager.GetString("SettingsEventCreatedChannel", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Role for event creation notifications.
|
||||
/// </summary>
|
||||
internal static string SettingsEventNotifyReceiverRole {
|
||||
get {
|
||||
return ResourceManager.GetString("SettingsEventNotifyReceiverRole", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Channel for event start notifications.
|
||||
/// </summary>
|
||||
internal static string SettingsEventStartedChannel {
|
||||
get {
|
||||
return ResourceManager.GetString("SettingsEventStartedChannel", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Event start notifications receivers.
|
||||
/// </summary>
|
||||
internal static string SettingsEventStartedReceivers {
|
||||
get {
|
||||
return ResourceManager.GetString("SettingsEventStartedReceivers", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to :(.
|
||||
/// </summary>
|
||||
internal static string SettingsFrowningFace {
|
||||
get {
|
||||
return ResourceManager.GetString("SettingsFrowningFace", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Language.
|
||||
/// </summary>
|
||||
internal static string SettingsLang {
|
||||
get {
|
||||
return ResourceManager.GetString("SettingsLang", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Mute role.
|
||||
/// </summary>
|
||||
internal static string SettingsMuteRole {
|
||||
get {
|
||||
return ResourceManager.GetString("SettingsMuteRole", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Nothing changed! `{0}` is already set to {1}.
|
||||
/// </summary>
|
||||
internal static string SettingsNothingChanged {
|
||||
get {
|
||||
return ResourceManager.GetString("SettingsNothingChanged", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Prefix.
|
||||
/// </summary>
|
||||
internal static string SettingsPrefix {
|
||||
get {
|
||||
return ResourceManager.GetString("SettingsPrefix", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Receive startup messages.
|
||||
/// </summary>
|
||||
internal static string SettingsReceiveStartupMessages {
|
||||
get {
|
||||
return ResourceManager.GetString("SettingsReceiveStartupMessages", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Remove roles on mute.
|
||||
/// </summary>
|
||||
internal static string SettingsRemoveRolesOnMute {
|
||||
get {
|
||||
return ResourceManager.GetString("SettingsRemoveRolesOnMute", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Send welcome messages.
|
||||
/// </summary>
|
||||
internal static string SettingsSendWelcomeMessages {
|
||||
get {
|
||||
return ResourceManager.GetString("SettingsSendWelcomeMessages", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Starter role.
|
||||
/// </summary>
|
||||
internal static string SettingsStarterRole {
|
||||
get {
|
||||
return ResourceManager.GetString("SettingsStarterRole", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Welcome message.
|
||||
/// </summary>
|
||||
internal static string SettingsWelcomeMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("SettingsWelcomeMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Message deleted in {0}, but I forgot what was there.
|
||||
/// </summary>
|
||||
internal static string UncachedMessageDeleted {
|
||||
get {
|
||||
|
@ -619,7 +808,7 @@ namespace Boyfriend {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Message edited from {0} in channel {1}, but I forgot what was there before the edit: .
|
||||
/// Looks up a localized string similar to Message edited from {0} in channel {1}, but I forgot what was there before the edit: {2}.
|
||||
/// </summary>
|
||||
internal static string UncachedMessageEdited {
|
||||
get {
|
||||
|
@ -628,20 +817,11 @@ namespace Boyfriend {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to :white_check_mark: Successfully unmuted {0} for {1}.
|
||||
/// Looks up a localized string similar to That user doesn't exist!.
|
||||
/// </summary>
|
||||
internal static string UnmuteResponse {
|
||||
internal static string UserDoesntExist {
|
||||
get {
|
||||
return ResourceManager.GetString("UnmuteResponse", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0} banned {1} for {2}{3}.
|
||||
/// </summary>
|
||||
internal static string UserBanned {
|
||||
get {
|
||||
return ResourceManager.GetString("UserBanned", resourceCulture);
|
||||
return ResourceManager.GetString("UserDoesntExist", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,19 +31,19 @@
|
|||
<value>{0}I'm ready! (C#)</value>
|
||||
</data>
|
||||
<data name="UncachedMessageDeleted" xml:space="preserve">
|
||||
<value>Deleted message in {0}, but I forgot what was there</value>
|
||||
<value>Message deleted in {0}, but I forgot what was there</value>
|
||||
</data>
|
||||
<data name="CachedMessageDeleted" xml:space="preserve">
|
||||
<value>Deleted message from {0} in channel </value>
|
||||
<value>Deleted message from {0} in channel {1}: {2}</value>
|
||||
</data>
|
||||
<data name="AutobanReason" xml:space="preserve">
|
||||
<value>Too many mentions in 1 message</value>
|
||||
</data>
|
||||
<data name="UncachedMessageEdited" xml:space="preserve">
|
||||
<value>Message edited from {0} in channel {1}, but I forgot what was there before the edit: </value>
|
||||
<value>Message edited from {0} in channel {1}, but I forgot what was there before the edit: {2}</value>
|
||||
</data>
|
||||
<data name="CachedMessageEdited" xml:space="preserve">
|
||||
<value>Message edited from {0} in channel {1}.{2}Before:{3}{4}{5}After:{6}{7}</value>
|
||||
<value>Edited message in channel {0}: {1} -> {2}</value>
|
||||
</data>
|
||||
<data name="DefaultWelcomeMessage" xml:space="preserve">
|
||||
<value>{0}, welcome to {1}</value>
|
||||
|
@ -84,9 +84,6 @@
|
|||
<data name="YouWereBanned" xml:space="preserve">
|
||||
<value>You were banned by {0} in guild {1} for {2}</value>
|
||||
</data>
|
||||
<data name="UserBanned" xml:space="preserve">
|
||||
<value>{0} banned {1} for {2}{3}</value>
|
||||
</data>
|
||||
<data name="PunishmentExpired" xml:space="preserve">
|
||||
<value>Punishment expired</value>
|
||||
</data>
|
||||
|
@ -96,21 +93,12 @@
|
|||
<data name="ClearAmountTooLarge" xml:space="preserve">
|
||||
<value>Too many messages specified!</value>
|
||||
</data>
|
||||
<data name="MessagesDeleted" xml:space="preserve">
|
||||
<value>{0} deleted {1} messages in channel {2}</value>
|
||||
</data>
|
||||
<data name="CommandHelp" xml:space="preserve">
|
||||
<value>Command help:{0}</value>
|
||||
<value>Command help:</value>
|
||||
</data>
|
||||
<data name="YouWereKicked" xml:space="preserve">
|
||||
<value>You were kicked by {0} in guild {1} for {2}</value>
|
||||
</data>
|
||||
<data name="MemberKicked" xml:space="preserve">
|
||||
<value>{0} kicked {1} for {2}</value>
|
||||
</data>
|
||||
<data name="MemberMuted" xml:space="preserve">
|
||||
<value>{0} muted {1} for {2}{3}</value>
|
||||
</data>
|
||||
<data name="Milliseconds" xml:space="preserve">
|
||||
<value>ms</value>
|
||||
</data>
|
||||
|
@ -124,41 +112,35 @@
|
|||
<value>Not specified</value>
|
||||
</data>
|
||||
<data name="CurrentSettings" xml:space="preserve">
|
||||
<value>Current settings:{0}</value>
|
||||
<value>Current settings:</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsLang" xml:space="preserve">
|
||||
<value>Language (`lang`): `{0}`{1}</value>
|
||||
<data name="SettingsLang" xml:space="preserve">
|
||||
<value>Language</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsPrefix" xml:space="preserve">
|
||||
<value>Prefix (`prefix`): `{0}`{1}</value>
|
||||
<data name="SettingsPrefix" xml:space="preserve">
|
||||
<value>Prefix</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsRemoveRoles" xml:space="preserve">
|
||||
<value>Remove roles on mute (`removeRolesOnMute`): {0}{1}</value>
|
||||
<data name="SettingsRemoveRolesOnMute" xml:space="preserve">
|
||||
<value>Remove roles on mute</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsUseSystemChannel" xml:space="preserve">
|
||||
<value>Use system channel for notifications (`useSystemChannel`): {0}{1}</value>
|
||||
<data name="SettingsSendWelcomeMessages" xml:space="preserve">
|
||||
<value>Send welcome messages</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsSendWelcomeMessages" xml:space="preserve">
|
||||
<value>Send welcome messages (`sendWelcomeMessages`): {0}{1}</value>
|
||||
<data name="SettingsStarterRole" xml:space="preserve">
|
||||
<value>Starter role</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsDefaultRole" xml:space="preserve">
|
||||
<value>Default role (`defaultRole`): {0}{1}</value>
|
||||
<data name="SettingsMuteRole" xml:space="preserve">
|
||||
<value>Mute role</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsMuteRole" xml:space="preserve">
|
||||
<value>Mute role (`muteRole`): {0}{1}</value>
|
||||
<data name="SettingsAdminLogChannel" xml:space="preserve">
|
||||
<value>Admin log channel</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsAdminLogChannel" xml:space="preserve">
|
||||
<value>Admin log channel (`adminLogChannel`): {0}{1}</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsBotLogChannel" xml:space="preserve">
|
||||
<value>Bot log channel (`botLogChannel`): {0}</value>
|
||||
<data name="SettingsBotLogChannel" xml:space="preserve">
|
||||
<value>Bot log channel</value>
|
||||
</data>
|
||||
<data name="LanguageNotSupported" xml:space="preserve">
|
||||
<value>Language not supported!</value>
|
||||
</data>
|
||||
<data name="SettingsUpdated" xml:space="preserve">
|
||||
<value>Settings successfully updated</value>
|
||||
</data>
|
||||
<data name="Yes" xml:space="preserve">
|
||||
<value>Yes</value>
|
||||
</data>
|
||||
|
@ -180,8 +162,8 @@
|
|||
<data name="UserUnbanned" xml:space="preserve">
|
||||
<value>{0} unbanned {1} for {2}</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsWelcomeMessage" xml:space="preserve">
|
||||
<value>Welcome message: `{0}`{1}</value>
|
||||
<data name="SettingsWelcomeMessage" xml:space="preserve">
|
||||
<value>Welcome message</value>
|
||||
</data>
|
||||
<data name="NotEnoughArguments" xml:space="preserve">
|
||||
<value>Not enough arguments! Needed: {0}, provided: {1}</value>
|
||||
|
@ -189,32 +171,17 @@
|
|||
<data name="ClearInvalidAmountSpecified" xml:space="preserve">
|
||||
<value>Invalid message amount specified!</value>
|
||||
</data>
|
||||
<data name="BanResponse" xml:space="preserve">
|
||||
<value>:white_check_mark: Successfully banned {0} for {1}</value>
|
||||
</data>
|
||||
<data name="KickResponse" xml:space="preserve">
|
||||
<value>:white_check_mark: Successfully kicked {0} for {1}</value>
|
||||
<data name="FeedbackUserBanned" xml:space="preserve">
|
||||
<value>Banned {0} for{1}: {2}</value>
|
||||
</data>
|
||||
<data name="UserNotInGuild" xml:space="preserve">
|
||||
<value>The specified user is not a member of this server!</value>
|
||||
</data>
|
||||
<data name="MuteResponse" xml:space="preserve">
|
||||
<value>:white_check_mark: Successfully muted {0} for {1}</value>
|
||||
</data>
|
||||
<data name="UnbanResponse" xml:space="preserve">
|
||||
<value>:white_check_mark: Successfully unbanned {0} for {1}</value>
|
||||
</data>
|
||||
<data name="UnmuteResponse" xml:space="preserve">
|
||||
<value>:white_check_mark: Successfully unmuted {0} for {1}</value>
|
||||
</data>
|
||||
<data name="SettingDoesntExist" xml:space="preserve">
|
||||
<value>That setting doesn't exist!</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsReceiveStartupMessages" xml:space="preserve">
|
||||
<value>Receive startup messages (`receiveStartupMessages`): {0}{1}</value>
|
||||
</data>
|
||||
<data name="PunishmentExpiresIn" xml:space="preserve">
|
||||
<value>{0}This punishment will expire <t:{1}:R></value>
|
||||
<data name="SettingsReceiveStartupMessages" xml:space="preserve">
|
||||
<value>Receive startup messages</value>
|
||||
</data>
|
||||
<data name="InvalidSettingValue" xml:space="preserve">
|
||||
<value>Invalid setting value specified!</value>
|
||||
|
@ -237,4 +204,97 @@
|
|||
<data name="CannotTimeOutBot" xml:space="preserve">
|
||||
<value>I cannot use time-outs on other bots! Try to set a mute role in settings</value>
|
||||
</data>
|
||||
<data name="EventCreated" xml:space="preserve">
|
||||
<value>{1}{2} created event {3}! It will take place in {4} and will start <t:{5}:R>!{0}{6}</value>
|
||||
</data>
|
||||
<data name="SettingsEventNotifyReceiverRole" xml:space="preserve">
|
||||
<value>Role for event creation notifications</value>
|
||||
</data>
|
||||
<data name="SettingsEventCreatedChannel" xml:space="preserve">
|
||||
<value>Channel for event creation notifications</value>
|
||||
</data>
|
||||
<data name="SettingsEventStartedChannel" xml:space="preserve">
|
||||
<value>Channel for event start notifications</value>
|
||||
</data>
|
||||
<data name="SettingsEventStartedReceivers" xml:space="preserve">
|
||||
<value>Event start notifications receivers</value>
|
||||
</data>
|
||||
<data name="EventStarted" xml:space="preserve">
|
||||
<value>{0}Event {1} is starting at {2}!</value>
|
||||
</data>
|
||||
<data name="SettingsFrowningFace" xml:space="preserve">
|
||||
<value>:(</value>
|
||||
</data>
|
||||
<data name="EventCancelled" xml:space="preserve">
|
||||
<value>Event {0} is cancelled!{1}</value>
|
||||
</data>
|
||||
<data name="SettingsEventCancelledChannel" xml:space="preserve">
|
||||
<value>Channel for event cancellation notifications</value>
|
||||
</data>
|
||||
<data name="SettingsEventCompletedChannel" xml:space="preserve">
|
||||
<value>Channel for event completion notifications</value>
|
||||
</data>
|
||||
<data name="EventCompleted" xml:space="preserve">
|
||||
<value>Event {0} has completed! Duration: {1}</value>
|
||||
</data>
|
||||
<data name="UserDoesntExist" xml:space="preserve">
|
||||
<value>That user doesn't exist!</value>
|
||||
</data>
|
||||
<data name="FeedbackFormat" xml:space="preserve">
|
||||
<value>*[{0}: {1}]*</value>
|
||||
</data>
|
||||
<data name="Ever" xml:space="preserve">
|
||||
<value>ever</value>
|
||||
</data>
|
||||
<data name="FeedbackMessagesCleared" xml:space="preserve">
|
||||
<value>Deleted {0} messages in {1}</value>
|
||||
</data>
|
||||
<data name="FeedbackMemberKicked" xml:space="preserve">
|
||||
<value>Kicked {0}: {1}</value>
|
||||
</data>
|
||||
<data name="FeedbackMemberMuted" xml:space="preserve">
|
||||
<value>Muted {0} for{1}: {2}</value>
|
||||
</data>
|
||||
<data name="FeedbackUserUnbanned" xml:space="preserve">
|
||||
<value>Unbanned {0}: {1}</value>
|
||||
</data>
|
||||
<data name="FeedbackMemberUnmuted" xml:space="preserve">
|
||||
<value>Unmuted {0}: {1}</value>
|
||||
</data>
|
||||
<data name="SettingsNothingChanged" xml:space="preserve">
|
||||
<value>Nothing changed! `{0}` is already set to {1}</value>
|
||||
</data>
|
||||
<data name="SettingNotDefined" xml:space="preserve">
|
||||
<value>Not specified</value>
|
||||
</data>
|
||||
<data name="FeedbackSettingsUpdated" xml:space="preserve">
|
||||
<value>Value of setting `{0}` is now set to {1}</value>
|
||||
</data>
|
||||
<data name="CommandDescriptionBan" xml:space="preserve">
|
||||
<value>Bans a user</value>
|
||||
</data>
|
||||
<data name="CommandDescriptionClear" xml:space="preserve">
|
||||
<value>Deletes a specified amount of messages in this channel</value>
|
||||
</data>
|
||||
<data name="CommandDescriptionHelp" xml:space="preserve">
|
||||
<value>Shows this message</value>
|
||||
</data>
|
||||
<data name="CommandDescriptionKick" xml:space="preserve">
|
||||
<value>Kicks a member</value>
|
||||
</data>
|
||||
<data name="CommandDescriptionMute" xml:space="preserve">
|
||||
<value>Mutes a member</value>
|
||||
</data>
|
||||
<data name="CommandDescriptionPing" xml:space="preserve">
|
||||
<value>Shows latency to Discord servers (not counting local processing time)</value>
|
||||
</data>
|
||||
<data name="CommandDescriptionSettings" xml:space="preserve">
|
||||
<value>Allows you to change certain preferences for this guild</value>
|
||||
</data>
|
||||
<data name="CommandDescriptionUnban" xml:space="preserve">
|
||||
<value>Unbans a user</value>
|
||||
</data>
|
||||
<data name="CommandDescriptionUnmute" xml:space="preserve">
|
||||
<value>Unmutes a member</value>
|
||||
</data>
|
||||
</root>
|
|
@ -25,16 +25,16 @@
|
|||
<value>Удалено сообщение в канале {0}, но я забыл что там было</value>
|
||||
</data>
|
||||
<data name="CachedMessageDeleted" xml:space="preserve">
|
||||
<value>Удалено сообщение от {0} в канале </value>
|
||||
<value>Удалено сообщение от {0} в канале {1}: {2}</value>
|
||||
</data>
|
||||
<data name="AutobanReason" xml:space="preserve">
|
||||
<value>Слишком много упоминаний в одном сообщении</value>
|
||||
</data>
|
||||
<data name="UncachedMessageEdited" xml:space="preserve">
|
||||
<value>Отредактировано сообщение от {0} в канале {1}, но я забыл что там было до редактирования: </value>
|
||||
<value>Отредактировано сообщение от {0} в канале {1}, но я забыл что там было до редактирования: {2}</value>
|
||||
</data>
|
||||
<data name="CachedMessageEdited" xml:space="preserve">
|
||||
<value>Отредактировано сообщение от {0} в канале {1}.{2}До:{3}{4}{5}После:{6}{7}</value>
|
||||
<value>Отредактировано сообщение в канале {0}: {1} -> {2}</value>
|
||||
</data>
|
||||
<data name="DefaultWelcomeMessage" xml:space="preserve">
|
||||
<value>{0}, добро пожаловать на сервер {1}</value>
|
||||
|
@ -75,9 +75,6 @@
|
|||
<data name="YouWereBanned" xml:space="preserve">
|
||||
<value>Тебя забанил {0} на сервере {1} за {2}</value>
|
||||
</data>
|
||||
<data name="UserBanned" xml:space="preserve">
|
||||
<value>{0} банит {1} за {2}{3}</value>
|
||||
</data>
|
||||
<data name="PunishmentExpired" xml:space="preserve">
|
||||
<value>Время наказания истекло</value>
|
||||
</data>
|
||||
|
@ -87,21 +84,12 @@
|
|||
<data name="ClearAmountTooLarge" xml:space="preserve">
|
||||
<value>Указано слишком много сообщений!</value>
|
||||
</data>
|
||||
<data name="MessagesDeleted" xml:space="preserve">
|
||||
<value>{0} удаляет {1} сообщений в канале {2}</value>
|
||||
</data>
|
||||
<data name="CommandHelp" xml:space="preserve">
|
||||
<value>Справка по командам:{0}</value>
|
||||
<value>Справка по командам:</value>
|
||||
</data>
|
||||
<data name="YouWereKicked" xml:space="preserve">
|
||||
<value>Тебя кикнул {0} на сервере {1} за {2}</value>
|
||||
</data>
|
||||
<data name="MemberKicked" xml:space="preserve">
|
||||
<value>{0} выгоняет {1} за {2}</value>
|
||||
</data>
|
||||
<data name="MemberMuted" xml:space="preserve">
|
||||
<value>{0} глушит {1} за {2}{3}</value>
|
||||
</data>
|
||||
<data name="Milliseconds" xml:space="preserve">
|
||||
<value>мс</value>
|
||||
</data>
|
||||
|
@ -115,41 +103,32 @@
|
|||
<value>Не указана</value>
|
||||
</data>
|
||||
<data name="CurrentSettings" xml:space="preserve">
|
||||
<value>Текущие настройки:{0}</value>
|
||||
<value>Текущие настройки:</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsLang" xml:space="preserve">
|
||||
<value>Язык (`lang`): `{0}`{1}</value>
|
||||
<data name="SettingsLang" xml:space="preserve">
|
||||
<value>Язык</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsPrefix" xml:space="preserve">
|
||||
<value>Префикс (`prefix`): `{0}`{1}</value>
|
||||
<data name="SettingsPrefix" xml:space="preserve">
|
||||
<value>Префикс</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsRemoveRoles" xml:space="preserve">
|
||||
<value>Удалять роли при муте (`removeRolesOnMute`): {0}{1}</value>
|
||||
<data name="SettingsRemoveRolesOnMute" xml:space="preserve">
|
||||
<value>Удалять роли при муте</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsUseSystemChannel" xml:space="preserve">
|
||||
<value>Использовать канал системных сообщений для уведомлений (`useSystemChannel`): {0}{1}</value>
|
||||
<data name="SettingsSendWelcomeMessages" xml:space="preserve">
|
||||
<value>Отправлять приветствия</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsSendWelcomeMessages" xml:space="preserve">
|
||||
<value>Отправлять приветствия (`sendWelcomeMessages`): {0}{1}</value>
|
||||
<data name="SettingsMuteRole" xml:space="preserve">
|
||||
<value>Роль мута</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsDefaultRole" xml:space="preserve">
|
||||
<value>Стандартная роль (`defaultRole`): {0}{1}</value>
|
||||
<data name="SettingsAdminLogChannel" xml:space="preserve">
|
||||
<value>Канал админ-уведомлений</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsMuteRole" xml:space="preserve">
|
||||
<value>Роль мута (`muteRole`): {0}{1}</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsAdminLogChannel" xml:space="preserve">
|
||||
<value>Канал админ-уведомлений (`adminLogChannel`): {0}{1}</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsBotLogChannel" xml:space="preserve">
|
||||
<value>Канал бот-уведомлений (`botLogChannel`): {0}</value>
|
||||
<data name="SettingsBotLogChannel" xml:space="preserve">
|
||||
<value>Канал бот-уведомлений</value>
|
||||
</data>
|
||||
<data name="LanguageNotSupported" xml:space="preserve">
|
||||
<value>Язык не поддерживается!</value>
|
||||
</data>
|
||||
<data name="SettingsUpdated" xml:space="preserve">
|
||||
<value>Настройки успешно обновлены!</value>
|
||||
</data>
|
||||
<data name="Yes" xml:space="preserve">
|
||||
<value>Да</value>
|
||||
</data>
|
||||
|
@ -171,8 +150,8 @@
|
|||
<data name="UserUnbanned" xml:space="preserve">
|
||||
<value>{0} возвращает из бана {1} за {2}</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsWelcomeMessage" xml:space="preserve">
|
||||
<value>Приветствие: `{0}`{1}</value>
|
||||
<data name="SettingsWelcomeMessage" xml:space="preserve">
|
||||
<value>Приветствие</value>
|
||||
</data>
|
||||
<data name="NotEnoughArguments" xml:space="preserve">
|
||||
<value>Недостаточно аргументов! Требуется: {0}, указано: {1}</value>
|
||||
|
@ -180,32 +159,17 @@
|
|||
<data name="ClearInvalidAmountSpecified" xml:space="preserve">
|
||||
<value>Указано неверное количество сообщений!</value>
|
||||
</data>
|
||||
<data name="BanResponse" xml:space="preserve">
|
||||
<value>:white_check_mark: Успешно забанен {0} за {1}</value>
|
||||
</data>
|
||||
<data name="KickResponse" xml:space="preserve">
|
||||
<value>:white_check_mark: Успешно выгнан {0} за {1}</value>
|
||||
<data name="FeedbackUserBanned" xml:space="preserve">
|
||||
<value>Забанен {0} на{1}: {2}</value>
|
||||
</data>
|
||||
<data name="UserNotInGuild" xml:space="preserve">
|
||||
<value>Указанный пользователь не является участником этого сервера!</value>
|
||||
</data>
|
||||
<data name="MuteResponse" xml:space="preserve">
|
||||
<value>:white_check_mark: Успешно заглушен {0} за {1}</value>
|
||||
</data>
|
||||
<data name="UnbanResponse" xml:space="preserve">
|
||||
<value>:white_check_mark: Успешно возвращён из бана {0} за {1}</value>
|
||||
</data>
|
||||
<data name="UnmuteResponse" xml:space="preserve">
|
||||
<value>:white_check_mark: Успешно возвращён из мута {0} за {1}</value>
|
||||
</data>
|
||||
<data name="SettingDoesntExist" xml:space="preserve">
|
||||
<value>Такая настройка не существует!</value>
|
||||
</data>
|
||||
<data name="CurrentSettingsReceiveStartupMessages" xml:space="preserve">
|
||||
<value>Получать сообщения о запуске (`receiveStartupMessages`): {0}{1}</value>
|
||||
</data>
|
||||
<data name="PunishmentExpiresIn" xml:space="preserve">
|
||||
<value>{0}Это наказание истечёт <t:{1}:R></value>
|
||||
<data name="SettingsReceiveStartupMessages" xml:space="preserve">
|
||||
<value>Получать сообщения о запуске</value>
|
||||
</data>
|
||||
<data name="InvalidSettingValue" xml:space="preserve">
|
||||
<value>Указано недействительное значение для настройки!</value>
|
||||
|
@ -228,4 +192,100 @@
|
|||
<data name="CannotTimeOutBot" xml:space="preserve">
|
||||
<value>Я не могу использовать тайм-ауты на других ботах! Попробуй указать роль мута в настройках</value>
|
||||
</data>
|
||||
<data name="SettingsStarterRole" xml:space="preserve">
|
||||
<value>Начальная роль</value>
|
||||
</data>
|
||||
<data name="EventCreated" xml:space="preserve">
|
||||
<value>{1}{2} создал событие {3}! Оно пройдёт в {4} и начнётся <t:{5}:R>!{0}{6}</value>
|
||||
</data>
|
||||
<data name="SettingsEventNotifyReceiverRole" xml:space="preserve">
|
||||
<value>Роль для уведомлений о создании событий</value>
|
||||
</data>
|
||||
<data name="SettingsEventCreatedChannel" xml:space="preserve">
|
||||
<value>Канал для уведомлений о создании событий</value>
|
||||
</data>
|
||||
<data name="SettingsEventStartedChannel" xml:space="preserve">
|
||||
<value>Канал для уведомлений о начале событий</value>
|
||||
</data>
|
||||
<data name="SettingsEventStartedReceivers" xml:space="preserve">
|
||||
<value>Получатели уведомлений о начале событий</value>
|
||||
</data>
|
||||
<data name="EventStarted" xml:space="preserve">
|
||||
<value>{0}Событие {1} начинается в {2}!</value>
|
||||
</data>
|
||||
<data name="SettingsFrowningFace" xml:space="preserve">
|
||||
<value>:( </value>
|
||||
</data>
|
||||
<data name="EventCancelled" xml:space="preserve">
|
||||
<value>Событие {0} отменено!{1}</value>
|
||||
</data>
|
||||
<data name="SettingsEventCancelledChannel" xml:space="preserve">
|
||||
<value>Канал для уведомлений о отмене событий</value>
|
||||
</data>
|
||||
<data name="SettingsEventCompletedChannel" xml:space="preserve">
|
||||
<value>Канал для уведомлений о завершении событий</value>
|
||||
</data>
|
||||
<data name="EventCompleted" xml:space="preserve">
|
||||
<value>Событие {0} завершено! Продолжительность: {1}</value>
|
||||
</data>
|
||||
<data name="UserDoesntExist" xml:space="preserve">
|
||||
<value>Такого пользователя не существует!</value>
|
||||
</data>
|
||||
<data name="FeedbackFormat" xml:space="preserve">
|
||||
<value>*[{0}: {1}]* </value>
|
||||
</data>
|
||||
<data name="Ever" xml:space="preserve">
|
||||
<value>всегда</value>
|
||||
</data>
|
||||
<data name="FeedbackMessagesCleared" xml:space="preserve">
|
||||
<value>Удалено {0} сообщений в {1}</value>
|
||||
</data>
|
||||
<data name="FeedbackMemberKicked" xml:space="preserve">
|
||||
<value>Выгнан {0}: {1}</value>
|
||||
</data>
|
||||
<data name="FeedbackMemberMuted" xml:space="preserve">
|
||||
<value>Заглушен {0} на{1}: {2}</value>
|
||||
</data>
|
||||
<data name="FeedbackUserUnbanned" xml:space="preserve">
|
||||
<value>Возвращён из бана {0}: {1}</value>
|
||||
</data>
|
||||
<data name="FeedbackMemberUnmuted" xml:space="preserve">
|
||||
<value>Разглушен {0}: {1}</value>
|
||||
</data>
|
||||
<data name="SettingsNothingChanged" xml:space="preserve">
|
||||
<value>Ничего не изменилось! Значение настройки `{0}` уже {1}</value>
|
||||
</data>
|
||||
<data name="SettingNotDefined" xml:space="preserve">
|
||||
<value>Не указано</value>
|
||||
</data>
|
||||
<data name="FeedbackSettingsUpdated" xml:space="preserve">
|
||||
<value>Значение настройки `{0}` теперь установлено на {1}</value>
|
||||
</data>
|
||||
<data name="CommandDescriptionBan" xml:space="preserve">
|
||||
<value>Банит пользователя</value>
|
||||
</data>
|
||||
<data name="CommandDescriptionClear" xml:space="preserve">
|
||||
<value>Удаляет указанное количество сообщений в этом канале</value>
|
||||
</data>
|
||||
<data name="CommandDescriptionHelp" xml:space="preserve">
|
||||
<value>Показывает эту справку</value>
|
||||
</data>
|
||||
<data name="CommandDescriptionKick" xml:space="preserve">
|
||||
<value>Выгоняет участника</value>
|
||||
</data>
|
||||
<data name="CommandDescriptionMute" xml:space="preserve">
|
||||
<value>Глушит участника</value>
|
||||
</data>
|
||||
<data name="CommandDescriptionPing" xml:space="preserve">
|
||||
<value>Показывает задержку до серверов Discord (не считая времени на локальные вычисления)</value>
|
||||
</data>
|
||||
<data name="CommandDescriptionSettings" xml:space="preserve">
|
||||
<value>Позволяет менять некоторые настройки под этот сервер</value>
|
||||
</data>
|
||||
<data name="CommandDescriptionUnban" xml:space="preserve">
|
||||
<value>Возвращает пользователя из бана</value>
|
||||
</data>
|
||||
<data name="CommandDescriptionUnmute" xml:space="preserve">
|
||||
<value>Разглушает участника</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1,11 +1,16 @@
|
|||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using Discord;
|
||||
using Discord.Net;
|
||||
using Discord.WebSocket;
|
||||
using Humanizer;
|
||||
using Humanizer.Localisation;
|
||||
|
||||
namespace Boyfriend;
|
||||
|
||||
public static class Utils {
|
||||
|
||||
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'",
|
||||
|
@ -14,65 +19,60 @@ public static class Utils {
|
|||
"%d'д'%s'с'", "%d'д'", "%h'ч'%m'м'%s'с'", "%h'ч'%m'м'", "%h'ч'%s'с'", "%h'ч'", "%m'м'%s'с'", "%m'м'", "%s'с'"
|
||||
};
|
||||
|
||||
public static string GetBeep(string cultureInfo, int i = -1) {
|
||||
Messages.Culture = new CultureInfo(cultureInfo);
|
||||
public static readonly Random Random = new();
|
||||
private static readonly Dictionary<string, string> ReflectionMessageCache = new();
|
||||
private static readonly Dictionary<string, CultureInfo> CultureInfoCache = new() {
|
||||
{"ru", new CultureInfo("ru-RU")},
|
||||
{"en", new CultureInfo("en-US")}
|
||||
};
|
||||
private static readonly Dictionary<ulong, SocketRole> MuteRoleCache = new();
|
||||
|
||||
var beeps = new[] {Messages.Beep1, Messages.Beep2, Messages.Beep3};
|
||||
return beeps[i < 0 ? new Random().Next(3) : i];
|
||||
private static readonly AllowedMentions AllowRoles = new() {
|
||||
AllowedTypes = AllowedMentionTypes.Roles
|
||||
};
|
||||
|
||||
public static string GetBeep(int i = -1) {
|
||||
return GetMessage($"Beep{(i < 0 ? Random.Next(3) + 1 : ++i)}");
|
||||
}
|
||||
|
||||
public static async Task<ITextChannel?> GetAdminLogChannel(IGuild guild) {
|
||||
var adminLogChannel = await ParseChannelNullable(Boyfriend.GetGuildConfig(guild).AdminLogChannel.ToString()!);
|
||||
return adminLogChannel as ITextChannel;
|
||||
public static SocketTextChannel? GetAdminLogChannel(ulong id) {
|
||||
return Boyfriend.Client.GetGuild(id)
|
||||
.GetTextChannel(ParseMention(Boyfriend.GetGuildConfig(id)["AdminLogChannel"]));
|
||||
}
|
||||
|
||||
public static string Wrap(string original) {
|
||||
public static string Wrap(string? original) {
|
||||
if (original == null) return "";
|
||||
var toReturn = original.Replace("```", "ˋˋˋ");
|
||||
return $"```{toReturn}{(toReturn.EndsWith("`") || toReturn.Trim().Equals("") ? " " : "")}```";
|
||||
}
|
||||
|
||||
public static string WrapInline(string original) {
|
||||
return $"`{original.Replace("`", "ˋ")}`";
|
||||
public static string? WrapInline(string? original) {
|
||||
return original == null ? null : $"`{original.Replace("`", "ˋ")}`";
|
||||
}
|
||||
|
||||
public static string? WrapAsNeeded(string? original) {
|
||||
if (original == null) return null;
|
||||
return original.Contains('\n') ? Wrap(original) : WrapInline(original);
|
||||
}
|
||||
|
||||
public static string MentionChannel(ulong id) {
|
||||
return $"<#{id}>";
|
||||
}
|
||||
|
||||
private static ulong ParseMention(string mention) {
|
||||
return Convert.ToUInt64(Regex.Replace(mention, "[^0-9]", ""));
|
||||
public static ulong ParseMention(string mention) {
|
||||
return ulong.TryParse(Regex.Replace(mention, "[^0-9]", ""), out var id) ? id : 0;
|
||||
}
|
||||
|
||||
private static ulong? ParseMentionNullable(string mention) {
|
||||
try {
|
||||
return ParseMention(mention) == 0 ? throw new FormatException() : ParseMention(mention);
|
||||
} catch (FormatException) {
|
||||
return null;
|
||||
}
|
||||
public static SocketUser? ParseUser(string mention) {
|
||||
var user = Boyfriend.Client.GetUser(ParseMention(mention));
|
||||
return user;
|
||||
}
|
||||
|
||||
public static async Task<IUser> ParseUser(string mention) {
|
||||
var user = Boyfriend.Client.GetUserAsync(ParseMention(mention));
|
||||
return await user;
|
||||
public static SocketGuildUser? ParseMember(SocketGuild guild, string mention) {
|
||||
return guild.GetUser(ParseMention(mention));
|
||||
}
|
||||
|
||||
public static async Task<IGuildUser> ParseMember(IGuild guild, string mention) {
|
||||
return await guild.GetUserAsync(ParseMention(mention));
|
||||
}
|
||||
|
||||
private static async Task<IChannel> ParseChannel(string mention) {
|
||||
return await Boyfriend.Client.GetChannelAsync(ParseMention(mention));
|
||||
}
|
||||
|
||||
private static async Task<IChannel?> ParseChannelNullable(string mention) {
|
||||
return ParseMentionNullable(mention) == null ? null : await ParseChannel(mention);
|
||||
}
|
||||
|
||||
public static IRole? ParseRole(IGuild guild, string mention) {
|
||||
return guild.GetRole(ParseMention(mention));
|
||||
}
|
||||
|
||||
public static async Task SendDirectMessage(IUser user, string toSend) {
|
||||
public static async Task SendDirectMessage(SocketUser user, string toSend) {
|
||||
try {
|
||||
await user.SendMessageAsync(toSend);
|
||||
} catch (HttpException e) {
|
||||
|
@ -81,33 +81,74 @@ public static class Utils {
|
|||
}
|
||||
}
|
||||
|
||||
public static IRole? GetMuteRole(IGuild guild) {
|
||||
var role = guild.Roles.FirstOrDefault(x => x.Id == Boyfriend.GetGuildConfig(guild).MuteRole);
|
||||
public static SocketRole? GetMuteRole(ref SocketGuild guild) {
|
||||
var id = ulong.Parse(Boyfriend.GetGuildConfig(guild.Id)["MuteRole"]);
|
||||
if (MuteRoleCache.ContainsKey(id)) return MuteRoleCache[id];
|
||||
SocketRole? role = null;
|
||||
foreach (var x in guild.Roles) {
|
||||
if (x.Id != id) continue;
|
||||
role = x;
|
||||
MuteRoleCache.Add(id, role);
|
||||
break;
|
||||
}
|
||||
return role;
|
||||
}
|
||||
|
||||
public static async Task SilentSendAsync(ITextChannel? channel, string text) {
|
||||
if (channel == null) return;
|
||||
public static async Task SilentSendAsync(SocketTextChannel? channel, string text, bool allowRoles = false) {
|
||||
if (channel == null || text.Length is 0 or > 2000) return;
|
||||
|
||||
try {
|
||||
await channel.SendMessageAsync(text, false, null, null, AllowedMentions.None);
|
||||
} catch (ArgumentException) {}
|
||||
await channel.SendMessageAsync(text, false, null, null, allowRoles ? AllowRoles : AllowedMentions.None);
|
||||
}
|
||||
public static TimeSpan GetTimeSpan(string from) {
|
||||
return TimeSpan.ParseExact(from.ToLowerInvariant(), Formats, CultureInfo.InvariantCulture);
|
||||
public static TimeSpan? GetTimeSpan(ref string from) {
|
||||
if (TimeSpan.TryParseExact(from.ToLowerInvariant(), Formats, CultureInfo.InvariantCulture, out var timeSpan))
|
||||
return timeSpan;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string JoinString(string[] args, int startIndex) {
|
||||
public static string JoinString(ref string[] args, int startIndex) {
|
||||
return string.Join(" ", args, startIndex, args.Length - startIndex);
|
||||
}
|
||||
|
||||
public static string GetNameAndDiscrim(IUser user) {
|
||||
return $"{user.Username}#{user.Discriminator}";
|
||||
}
|
||||
|
||||
public static RequestOptions GetRequestOptions(string reason) {
|
||||
var options = RequestOptions.Default;
|
||||
options.AuditLogReason = reason;
|
||||
return options;
|
||||
}
|
||||
|
||||
public static string GetMessage(string name) {
|
||||
var propertyName = name;
|
||||
name = $"{Messages.Culture}/{name}";
|
||||
if (ReflectionMessageCache.ContainsKey(name)) return ReflectionMessageCache[name];
|
||||
|
||||
var toReturn =
|
||||
typeof(Messages).GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Static)?.GetValue(null)
|
||||
?.ToString()! ?? throw new Exception($"Could not find localized property: {name}");
|
||||
ReflectionMessageCache.Add(name, toReturn);
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
public static async Task SendFeedback(string feedback, ulong guildId, string mention, bool sendPublic = false) {
|
||||
var adminChannel = GetAdminLogChannel(guildId);
|
||||
var systemChannel = Boyfriend.Client.GetGuild(guildId).SystemChannel;
|
||||
var toSend = string.Format(Messages.FeedbackFormat, mention, feedback);
|
||||
if (adminChannel != null)
|
||||
await SilentSendAsync(adminChannel, toSend);
|
||||
if (sendPublic && systemChannel != null)
|
||||
await SilentSendAsync(systemChannel, toSend);
|
||||
}
|
||||
|
||||
public static void StackFeedback(ref string feedback, ref string mention, bool isPublic) {
|
||||
var toAppend = string.Format(Messages.FeedbackFormat, mention, feedback);
|
||||
CommandHandler.StackedPrivateFeedback.AppendLine(toAppend);
|
||||
if (isPublic) CommandHandler.StackedPublicFeedback.AppendLine(toAppend);
|
||||
}
|
||||
|
||||
public static string GetHumanizedTimeOffset(ref TimeSpan span) {
|
||||
return span.TotalSeconds > 0 ? $" {span.Humanize(minUnit: TimeUnit.Second, culture: Messages.Culture)}"
|
||||
: Messages.Ever;
|
||||
}
|
||||
|
||||
public static void SetCurrentLanguage(ulong guildId) {
|
||||
Messages.Culture = CultureInfoCache[Boyfriend.GetGuildConfig(guildId)["Lang"]];
|
||||
}
|
||||
}
|
BIN
UpgradeLog.htm
Normal file
BIN
UpgradeLog.htm
Normal file
Binary file not shown.
Loading…
Reference in a new issue