1
0
Fork 1
mirror of https://github.com/TeamOctolings/Octobot.git synced 2025-04-19 16:33:36 +03:00

Continue adapting code to new guild data storage

This commit is contained in:
Octol1ttle 2022-12-30 18:34:48 +05:00
parent 163e3ac46b
commit fe2cfb3b3c
Signed by: Octol1ttle
GPG key ID: B77C34313AEE1FFF
10 changed files with 145 additions and 94 deletions

View file

@ -1,5 +1,6 @@
using System.Text;
using Boyfriend.Commands;
using Boyfriend.Data;
using Discord;
using Discord.Commands;
using Discord.WebSocket;
@ -12,7 +13,8 @@ public sealed class CommandProcessor {
public static readonly ICommand[] Commands = {
new BanCommand(), new ClearCommand(), new HelpCommand(),
new KickCommand(), new MuteCommand(), new PingCommand(),
new SettingsCommand(), new UnbanCommand(), new UnmuteCommand()
new SettingsCommand(), new UnbanCommand(), new UnmuteCommand(),
new RemindCommand()
};
private readonly StringBuilder _stackedPrivateFeedback = new();
@ -30,11 +32,10 @@ public sealed class CommandProcessor {
public async Task HandleCommandAsync() {
var guild = Context.Guild;
var config = Boyfriend.GetGuildConfig(guild.Id);
var muteRole = Utils.GetMuteRole(guild);
Utils.SetCurrentLanguage(guild.Id);
var data = GuildData.FromSocketGuild(guild);
Utils.SetCurrentLanguage(guild);
if (GetMember().Roles.Contains(muteRole)) {
if (GetMember().Roles.Contains(data.MuteRole)) {
_ = Context.Message.ReplyAsync(Messages.UserCannotUnmuteThemselves);
return;
}
@ -42,7 +43,7 @@ public sealed class CommandProcessor {
var list = Context.Message.Content.Split("\n");
var cleanList = Context.Message.CleanContent.Split("\n");
for (var i = 0; i < list.Length; i++)
_tasks.Add(RunCommandOnLine(list[i], cleanList[i], config["Prefix"]));
_tasks.Add(RunCommandOnLine(list[i], cleanList[i], data.Preferences["Prefix"]));
try { Task.WaitAll(_tasks.ToArray()); } catch (AggregateException e) {
foreach (var ex in e.InnerExceptions)
@ -52,7 +53,7 @@ public sealed class CommandProcessor {
_tasks.Clear();
if (ConfigWriteScheduled) await Boyfriend.WriteGuildConfigAsync(guild.Id);
if (ConfigWriteScheduled) await data.Save(true);
SendFeedbacks();
}
@ -80,7 +81,7 @@ public sealed class CommandProcessor {
public void Audit(string action, bool isPublic = true) {
var format = $"*[{Context.User.Mention}: {action}]*";
if (isPublic) Utils.SafeAppendToBuilder(_stackedPublicFeedback, format, Context.Guild.SystemChannel);
Utils.SafeAppendToBuilder(_stackedPrivateFeedback, format, Utils.GetBotLogChannel(Context.Guild.Id));
Utils.SafeAppendToBuilder(_stackedPrivateFeedback, format, Utils.GetBotLogChannel(Context.Guild));
if (_tasks.Count is 0) SendFeedbacks(false);
}
@ -88,7 +89,7 @@ public sealed class CommandProcessor {
if (reply && _stackedReplyMessage.Length > 0)
_ = Context.Message.ReplyAsync(_stackedReplyMessage.ToString(), false, null, AllowedMentions.None);
var adminChannel = Utils.GetBotLogChannel(Context.Guild.Id);
var adminChannel = Utils.GetBotLogChannel(Context.Guild);
var systemChannel = Context.Guild.SystemChannel;
if (_stackedPrivateFeedback.Length > 0 && adminChannel is not null &&
adminChannel.Id != Context.Message.Channel.Id) {

View file

@ -28,12 +28,14 @@ public sealed class BanCommand : ICommand {
var guildBanMessage = $"({author}) {reason}";
await guild.AddBanAsync(toBan, 0, guildBanMessage);
var memberData = GuildData.FromSocketGuild(guild).MemberData[toBan.Id];
memberData.BannedUntil
= duration.TotalSeconds < 1 ? -1 : DateTimeOffset.Now.Add(duration).ToUnixTimeSeconds();
memberData.Roles.Clear();
var feedback = string.Format(Messages.FeedbackUserBanned, toBan.Mention,
Utils.GetHumanizedTimeOffset(duration), Utils.Wrap(reason));
cmd.Reply(feedback, ReplyEmojis.Banned);
cmd.Audit(feedback);
GuildData.FromSocketGuild(guild).MemberData[toBan.Id].BannedUntil
= DateTimeOffset.Now.Add(duration).ToUnixTimeSeconds();
}
}

View file

@ -1,3 +1,4 @@
using Boyfriend.Data;
using Discord;
using Discord.WebSocket;
@ -22,6 +23,8 @@ public sealed class KickCommand : ICommand {
string.Format(Messages.YouWereKicked, cmd.Context.User.Mention, cmd.Context.Guild.Name,
Utils.Wrap(reason)));
GuildData.FromSocketGuild(cmd.Context.Guild).MemberData[toKick.Id].Roles.Clear();
await toKick.KickAsync(guildKickMessage);
var format = string.Format(Messages.FeedbackMemberKicked, toKick.Mention, Utils.Wrap(reason));
cmd.Reply(format, ReplyEmojis.Kicked);

View file

@ -36,7 +36,8 @@ public sealed class MuteCommand : ICommand {
var hasDuration = duration.TotalSeconds > 0;
if (role is not null) {
if (data.Preferences["RemoveRolesOnMute"] is "true") await toMute.RemoveRolesAsync(toMute.Roles);
if (data.Preferences["RemoveRolesOnMute"] is "true")
await toMute.RemoveRolesAsync(toMute.Roles, requestOptions);
await toMute.AddRoleAsync(role, requestOptions);

View file

@ -0,0 +1,19 @@
using Boyfriend.Data;
namespace Boyfriend.Commands;
public sealed class RemindCommand : ICommand {
public string[] Aliases { get; } = { "remind", "reminder", "remindme", "напомни", "напомнить", "напоминание" };
public Task RunAsync(CommandProcessor cmd, string[] args, string[] cleanArgs) {
var remindIn = CommandProcessor.GetTimeSpan(args, 0);
var reminderText = cmd.GetRemaining(args, 1, "ReminderText");
if (reminderText is not null)
GuildData.FromSocketGuild(cmd.Context.Guild).MemberData[cmd.Context.User.Id].Reminders.Add(new Reminder {
RemindAt = DateTimeOffset.Now.Add(remindIn).ToUnixTimeSeconds(),
ReminderText = reminderText
});
return Task.CompletedTask;
}
}

View file

@ -16,7 +16,7 @@ public sealed class SettingsCommand : ICommand {
if (args.Length is 0) {
var currentSettings = Boyfriend.StringBuilder.AppendLine(Messages.CurrentSettings);
foreach (var setting in GuildData.DefaultConfiguration) {
foreach (var setting in GuildData.DefaultPreferences) {
var format = "{0}";
var currentValue = config[setting.Key] is "default"
? Messages.DefaultWelcomeMessage
@ -47,7 +47,7 @@ public sealed class SettingsCommand : ICommand {
var exists = false;
// ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator
// Too many allocations
foreach (var setting in GuildData.DefaultConfiguration.Keys) {
foreach (var setting in GuildData.DefaultPreferences.Keys) {
if (selectedSetting != setting.ToLower()) continue;
selectedSetting = setting;
exists = true;
@ -74,7 +74,7 @@ public sealed class SettingsCommand : ICommand {
}
} else { value = "reset"; }
if (IsBool(GuildData.DefaultConfiguration[selectedSetting]) && !IsBool(value)) {
if (IsBool(GuildData.DefaultPreferences[selectedSetting]) && !IsBool(value)) {
value = value switch {
"y" or "yes" or "д" or "да" => "true",
"n" or "no" or "н" or "нет" => "false",
@ -99,14 +99,14 @@ public sealed class SettingsCommand : ICommand {
var formattedValue = selectedSetting switch {
"WelcomeMessage" => Utils.Wrap(Messages.DefaultWelcomeMessage),
"EventStartedReceivers" => Utils.Wrap(GuildData.DefaultConfiguration[selectedSetting])!,
"EventStartedReceivers" => Utils.Wrap(GuildData.DefaultPreferences[selectedSetting])!,
_ => value is "reset" or "default" ? Messages.SettingNotDefined
: IsBool(value) ? YesOrNo(value is "true")
: string.Format(formatting, value)
};
if (value is "reset" or "default") {
config[selectedSetting] = GuildData.DefaultConfiguration[selectedSetting];
config[selectedSetting] = GuildData.DefaultPreferences[selectedSetting];
} else {
if (value == config[selectedSetting]) {
cmd.Reply(string.Format(Messages.SettingsNothingChanged, localizedSelectedSetting, formattedValue),
@ -139,7 +139,7 @@ public sealed class SettingsCommand : ICommand {
}
if (selectedSetting is "Lang") {
Utils.SetCurrentLanguage(guild.Id);
Utils.SetCurrentLanguage(guild);
localizedSelectedSetting = Utils.GetMessage($"Settings{selectedSetting}");
}

View file

@ -20,10 +20,12 @@ public sealed class UnmuteCommand : ICommand {
public static async Task UnmuteMemberAsync(CommandProcessor cmd, SocketGuildUser toUnmute,
string reason) {
var requestOptions = Utils.GetRequestOptions($"({cmd.Context.User}) {reason}");
var role = GuildData.FromSocketGuild(cmd.Context.Guild).MuteRole;
var data = GuildData.FromSocketGuild(cmd.Context.Guild);
var role = data.MuteRole;
if (role is not null && toUnmute.Roles.Contains(role)) {
// TODO: Return roles
await toUnmute.AddRolesAsync(data.MemberData[toUnmute.Id].Roles, requestOptions);
await toUnmute.RemoveRoleAsync(role, requestOptions);
} else {
if (toUnmute.TimedOutUntil is null || toUnmute.TimedOutUntil.Value.ToUnixTimeSeconds() <
DateTimeOffset.Now.ToUnixTimeSeconds()) {
@ -31,7 +33,7 @@ public sealed class UnmuteCommand : ICommand {
return;
}
await toUnmute.RemoveTimeOutAsync();
await toUnmute.RemoveTimeOutAsync(requestOptions);
}
var feedback = string.Format(Messages.FeedbackMemberUnmuted, toUnmute.Mention, Utils.Wrap(reason));

View file

@ -5,7 +5,7 @@ using Discord.WebSocket;
namespace Boyfriend.Data;
public record GuildData {
public static readonly Dictionary<string, string> DefaultConfiguration = new() {
public static readonly Dictionary<string, string> DefaultPreferences = new() {
{ "Prefix", "!" },
{ "Lang", "en" },
{ "ReceiveStartupMessages", "false" },
@ -21,6 +21,7 @@ public record GuildData {
{ "EventNotificationRole", "0" },
{ "EventNotificationChannel", "0" },
{ "EventEarlyNotificationOffset", "0" }
// TODO: { "AutoStartEvents", "false" }
};
private static readonly Dictionary<ulong, GuildData> GuildDataDictionary = new();
@ -36,52 +37,49 @@ public record GuildData {
[SuppressMessage("Performance", "CA1853:Unnecessary call to \'Dictionary.ContainsKey(key)\'")]
// https://github.com/dotnet/roslyn-analyzers/issues/6377
private GuildData(SocketGuild guild) {
var id = guild.Id;
if (!Directory.Exists($"{id}")) Directory.CreateDirectory($"{id}");
if (!Directory.Exists($"{id}/MemberData")) Directory.CreateDirectory($"{id}/MemberData");
if (!File.Exists($"{id}/Configuration.json")) File.Create($"{id}/Configuration.json").Dispose();
if (!Directory.Exists($"{_id}")) Directory.CreateDirectory($"{_id}");
if (!Directory.Exists($"{_id}/MemberData")) Directory.CreateDirectory($"{_id}/MemberData");
if (!File.Exists($"{_id}/Configuration.json")) File.Create($"{_id}/Configuration.json").Dispose();
Preferences
= JsonSerializer.Deserialize<Dictionary<string, string>>(File.ReadAllText($"{id}/Configuration.json")) ??
= JsonSerializer.Deserialize<Dictionary<string, string>>(File.ReadAllText($"{_id}/Configuration.json")) ??
new Dictionary<string, string>();
// ReSharper disable twice ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator
if (Preferences.Keys.Count < DefaultConfiguration.Keys.Count)
foreach (var key in DefaultConfiguration.Keys)
if (Preferences.Keys.Count < DefaultPreferences.Keys.Count)
foreach (var key in DefaultPreferences.Keys)
if (!Preferences.ContainsKey(key))
Preferences.Add(key, DefaultConfiguration[key]);
if (Preferences.Keys.Count > DefaultConfiguration.Keys.Count)
Preferences.Add(key, DefaultPreferences[key]);
if (Preferences.Keys.Count > DefaultPreferences.Keys.Count)
foreach (var key in Preferences.Keys)
if (!DefaultConfiguration.ContainsKey(key))
if (!DefaultPreferences.ContainsKey(key))
Preferences.Remove(key);
Preferences.TrimExcess();
MemberData = new Dictionary<ulong, MemberData>();
foreach (var data in Directory.GetFiles($"{id}/MemberData")) {
var deserialised = JsonSerializer.Deserialize<MemberData>(File.ReadAllText($"{id}/MemberData/{data}.json"));
foreach (var data in Directory.GetFiles($"{_id}/MemberData")) {
var deserialised
= JsonSerializer.Deserialize<MemberData>(File.ReadAllText($"{_id}/MemberData/{data}.json"));
MemberData.Add(deserialised!.Id, deserialised);
}
if (guild.MemberCount > MemberData.Count)
foreach (var member in guild.Users) {
if (MemberData.TryGetValue(member.Id, out var memberData)) {
if (!memberData.IsInGuild &&
DateTimeOffset.Now.ToUnixTimeSeconds() -
Math.Max(memberData.LeftAt.Last(), memberData.BannedUntil) >
60 * 60 * 24 * 30) {
File.Delete($"{id}/MemberData/{memberData.Id}.json");
MemberData.Remove(memberData.Id);
}
continue;
foreach (var member in guild.Users) {
if (MemberData.TryGetValue(member.Id, out var memberData)) {
if (!memberData.IsInGuild &&
DateTimeOffset.Now.ToUnixTimeSeconds() -
Math.Max(memberData.LeftAt.Last(), memberData.BannedUntil) >
60 * 60 * 24 * 30) {
File.Delete($"{_id}/MemberData/{memberData.Id}.json");
MemberData.Remove(memberData.Id);
}
var data = new MemberData(member);
MemberData.Add(member.Id, data);
File.WriteAllText($"{id}/MemberData/{data.Id}.json",
JsonSerializer.Serialize(data));
continue;
}
GuildDataDictionary.Add(id, this);
MemberData.Add(member.Id, new MemberData(member));
}
MemberData.TrimExcess();
}
public SocketRole? MuteRole {
@ -98,4 +96,14 @@ public record GuildData {
GuildDataDictionary.Add(guild.Id, newData);
return newData;
}
public async Task Save(bool saveMemberData) {
Preferences.TrimExcess();
await File.WriteAllTextAsync($"{_id}/Configuration.json",
JsonSerializer.Serialize(Preferences));
if (saveMemberData)
foreach (var data in MemberData.Values)
await File.WriteAllTextAsync($"{_id}/MemberData/{data.Id}.json",
JsonSerializer.Serialize(data));
}
}

View file

@ -1,3 +1,5 @@
using System.Diagnostics;
using Boyfriend.Data;
using Discord;
using Discord.Rest;
using Discord.WebSocket;
@ -26,9 +28,9 @@ public static class EventHandler {
var i = Random.Shared.Next(3);
foreach (var guild in Client.Guilds) {
var config = Boyfriend.GetGuildConfig(guild.Id);
var config = GuildData.FromSocketGuild(guild).Preferences;
var channel = guild.GetTextChannel(Utils.ParseMention(config["BotLogChannel"]));
Utils.SetCurrentLanguage(guild.Id);
Utils.SetCurrentLanguage(guild);
if (config["ReceiveStartupMessages"] is not "true" || channel is null) continue;
_ = channel.SendMessageAsync(string.Format(Messages.Ready, Utils.GetBeep(i)));
@ -46,7 +48,7 @@ public static class EventHandler {
var guild = gChannel.Guild;
Utils.SetCurrentLanguage(guild.Id);
Utils.SetCurrentLanguage(guild);
var mention = msg.Author.Mention;
@ -58,7 +60,7 @@ public static class EventHandler {
await Utils.SendFeedbackAsync(string.Format(Messages.CachedMessageDeleted, msg.Author.Mention,
Utils.MentionChannel(channel.Id),
Utils.Wrap(msg.CleanContent)), guild.Id, mention);
Utils.Wrap(msg.CleanContent)), guild, mention);
}
private static Task MessageReceivedEvent(IDeletable messageParam) {
@ -82,19 +84,20 @@ public static class EventHandler {
msg.CleanContent == messageSocket.CleanContent || msg.Author.IsBot) return;
var guild = gChannel.Guild;
Utils.SetCurrentLanguage(guild.Id);
Utils.SetCurrentLanguage(guild);
var isLimitedSpace = msg.CleanContent.Length + messageSocket.CleanContent.Length < 1940;
await Utils.SendFeedbackAsync(string.Format(Messages.CachedMessageEdited, Utils.MentionChannel(channel.Id),
Utils.Wrap(msg.CleanContent, isLimitedSpace), Utils.Wrap(messageSocket.CleanContent, isLimitedSpace)),
guild.Id, msg.Author.Mention);
guild, msg.Author.Mention);
}
private static async Task UserJoinedEvent(SocketGuildUser user) {
var guild = user.Guild;
var config = Boyfriend.GetGuildConfig(guild.Id);
Utils.SetCurrentLanguage(guild.Id);
var data = GuildData.FromSocketGuild(guild);
var config = data.Preferences;
Utils.SetCurrentLanguage(guild);
if (config["SendWelcomeMessages"] is "true")
await Utils.SilentSendAsync(guild.SystemChannel,
@ -103,27 +106,42 @@ public static class EventHandler {
: config["WelcomeMessage"], user.Mention, guild.Name));
if (config["StarterRole"] is not "0") await user.AddRoleAsync(ulong.Parse(config["StarterRole"]));
if (!data.MemberData.ContainsKey(user.Id)) data.MemberData.Add(user.Id, new MemberData(user));
var memberData = data.MemberData[user.Id];
memberData.IsInGuild = true;
memberData.BannedUntil = 0;
if (memberData.LeftAt.Count > 0) {
if (memberData.JoinedAt.Contains(user.JoinedAt!.Value.ToUnixTimeSeconds()))
throw new UnreachableException();
memberData.JoinedAt.Add(user.JoinedAt!.Value.ToUnixTimeSeconds());
}
if (memberData.MutedUntil < DateTimeOffset.Now.ToUnixTimeSeconds()) {
if (data.MuteRole is not null)
await user.AddRoleAsync(data.MuteRole);
else
await user.SetTimeOutAsync(
TimeSpan.FromSeconds(DateTimeOffset.Now.ToUnixTimeSeconds() - memberData.MutedUntil));
if (config["RemoveRolesOnMute"] is "false" && config["ReturnRolesOnRejoin"] is "true")
await user.AddRolesAsync(memberData.Roles);
} else if (config["ReturnRolesOnRejoin"] is "true") { await user.AddRolesAsync(memberData.Roles); }
}
private static async Task UserLeftEvent(SocketGuildUser user) {
var guild = user.Guild;
var config = Boyfriend.GetGuildConfig(guild.Id);
Utils.SetCurrentLanguage(guild.Id);
if (config["SendWelcomeMessages"] is "true")
await Utils.SilentSendAsync(guild.SystemChannel,
string.Format(config["WelcomeMessage"] is "default"
? Messages.DefaultWelcomeMessage
: config["WelcomeMessage"], user.Mention, guild.Name));
if (config["StarterRole"] is not "0") await user.AddRoleAsync(ulong.Parse(config["StarterRole"]));
private static Task UserLeftEvent(SocketGuild guild, SocketUser user) {
var data = GuildData.FromSocketGuild(guild).MemberData[user.Id];
data.IsInGuild = false;
data.LeftAt.Add(DateTimeOffset.Now.ToUnixTimeSeconds());
return Task.CompletedTask;
}
// TODO: store data about event (early) notifications
private static async Task ScheduledEventCreatedEvent(SocketGuildEvent scheduledEvent) {
var guild = scheduledEvent.Guild;
var eventConfig = Boyfriend.GetGuildConfig(guild.Id);
var eventConfig = GuildData.FromSocketGuild(guild).Preferences;
var channel = Utils.GetEventNotificationChannel(guild);
Utils.SetCurrentLanguage(guild.Id);
Utils.SetCurrentLanguage(guild);
if (channel is not null) {
var role = guild.GetRole(ulong.Parse(eventConfig["EventNotificationRole"]));
@ -141,17 +159,13 @@ public static class EventHandler {
scheduledEvent.StartTime.ToUnixTimeSeconds().ToString(), descAndLink),
true);
}
if (eventConfig["EventEarlyNotificationOffset"] is not "0")
_ = Utils.SendEarlyEventStartNotificationAsync(channel, scheduledEvent,
int.Parse(eventConfig["EventEarlyNotificationOffset"]));
}
private static async Task ScheduledEventCancelledEvent(SocketGuildEvent scheduledEvent) {
var guild = scheduledEvent.Guild;
var eventConfig = Boyfriend.GetGuildConfig(guild.Id);
var eventConfig = GuildData.FromSocketGuild(guild).Preferences;
var channel = Utils.GetEventNotificationChannel(guild);
Utils.SetCurrentLanguage(guild.Id);
Utils.SetCurrentLanguage(guild);
if (channel is not null)
await channel.SendMessageAsync(string.Format(Messages.EventCancelled, Utils.Wrap(scheduledEvent.Name),
eventConfig["FrowningFace"] is "true" ? $" {Messages.SettingsFrowningFace}" : ""));
@ -159,9 +173,9 @@ public static class EventHandler {
private static async Task ScheduledEventStartedEvent(SocketGuildEvent scheduledEvent) {
var guild = scheduledEvent.Guild;
var eventConfig = Boyfriend.GetGuildConfig(guild.Id);
var eventConfig = GuildData.FromSocketGuild(guild).Preferences;
var channel = Utils.GetEventNotificationChannel(guild);
Utils.SetCurrentLanguage(guild.Id);
Utils.SetCurrentLanguage(guild);
if (channel is not null) {
var receivers = eventConfig["EventStartedReceivers"];
@ -183,7 +197,7 @@ public static class EventHandler {
private static async Task ScheduledEventCompletedEvent(SocketGuildEvent scheduledEvent) {
var guild = scheduledEvent.Guild;
var channel = Utils.GetEventNotificationChannel(guild);
Utils.SetCurrentLanguage(guild.Id);
Utils.SetCurrentLanguage(guild);
if (channel is not null)
await channel.SendMessageAsync(string.Format(Messages.EventCompleted, Utils.Wrap(scheduledEvent.Name),
Utils.GetHumanizedTimeOffset(DateTimeOffset.Now.Subtract(scheduledEvent.StartTime))));

View file

@ -3,6 +3,7 @@ using System.Globalization;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using Boyfriend.Data;
using Discord;
using Discord.Net;
using Discord.WebSocket;
@ -28,9 +29,8 @@ public static partial class Utils {
return GetMessage($"Beep{(i < 0 ? Random.Shared.Next(3) + 1 : ++i)}");
}
public static SocketTextChannel? GetBotLogChannel(ulong id) {
return Boyfriend.Client.GetGuild(id)
.GetTextChannel(ParseMention(Boyfriend.GetGuildConfig(id)["BotLogChannel"]));
public static SocketTextChannel? GetBotLogChannel(SocketGuild guild) {
return guild.GetTextChannel(ParseMention(GuildData.FromSocketGuild(guild).Preferences["BotLogChannel"]));
}
public static string? Wrap(string? original, bool limitedSpace = false) {
@ -91,22 +91,22 @@ public static partial class Utils {
}
public static async Task
SendFeedbackAsync(string feedback, ulong guildId, string mention, bool sendPublic = false) {
var adminChannel = GetBotLogChannel(guildId);
var systemChannel = Boyfriend.Client.GetGuild(guildId).SystemChannel;
SendFeedbackAsync(string feedback, SocketGuild guild, string mention, bool sendPublic = false) {
var adminChannel = GetBotLogChannel(guild);
var systemChannel = guild.SystemChannel;
var toSend = $"*[{mention}: {feedback}]*";
if (adminChannel is not null) await SilentSendAsync(adminChannel, toSend);
if (sendPublic && systemChannel is not null) await SilentSendAsync(systemChannel, toSend);
}
public static string GetHumanizedTimeOffset(TimeSpan span) {
return span.TotalSeconds > 0
? $" {span.Humanize(2, minUnit: TimeUnit.Second, maxUnit: TimeUnit.Month, culture: Messages.Culture.Name.Contains("RU") ? CultureInfoCache["ru"] : Messages.Culture)}"
: Messages.Ever;
return span.TotalSeconds < 1
? Messages.Ever
: $" {span.Humanize(2, minUnit: TimeUnit.Second, maxUnit: TimeUnit.Month, culture: Messages.Culture.Name.Contains("RU") ? CultureInfoCache["ru"] : Messages.Culture)}";
}
public static void SetCurrentLanguage(ulong guildId) {
Messages.Culture = CultureInfoCache[Boyfriend.GetGuildConfig(guildId)["Lang"]];
public static void SetCurrentLanguage(SocketGuild guild) {
Messages.Culture = CultureInfoCache[GuildData.FromSocketGuild(guild).Preferences["Lang"]];
}
public static void SafeAppendToBuilder(StringBuilder appendTo, string appendWhat, SocketTextChannel? channel) {
@ -129,7 +129,8 @@ public static partial class Utils {
}
public static SocketTextChannel? GetEventNotificationChannel(SocketGuild guild) {
return guild.GetTextChannel(ParseMention(Boyfriend.GetGuildConfig(guild.Id)["EventNotificationChannel"]));
return guild.GetTextChannel(ParseMention(GuildData.FromSocketGuild(guild)
.Preferences["EventNotificationChannel"]));
}
[GeneratedRegex("[^0-9]")]