mirror of
https://github.com/TeamOctolings/Octobot.git
synced 2025-04-20 00:43:36 +03:00
Continue adapting code to new guild data storage
This commit is contained in:
parent
163e3ac46b
commit
fe2cfb3b3c
10 changed files with 145 additions and 94 deletions
|
@ -1,5 +1,6 @@
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Boyfriend.Commands;
|
using Boyfriend.Commands;
|
||||||
|
using Boyfriend.Data;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
@ -12,7 +13,8 @@ public sealed class CommandProcessor {
|
||||||
public static readonly ICommand[] Commands = {
|
public static readonly ICommand[] Commands = {
|
||||||
new BanCommand(), new ClearCommand(), new HelpCommand(),
|
new BanCommand(), new ClearCommand(), new HelpCommand(),
|
||||||
new KickCommand(), new MuteCommand(), new PingCommand(),
|
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();
|
private readonly StringBuilder _stackedPrivateFeedback = new();
|
||||||
|
@ -30,11 +32,10 @@ public sealed class CommandProcessor {
|
||||||
|
|
||||||
public async Task HandleCommandAsync() {
|
public async Task HandleCommandAsync() {
|
||||||
var guild = Context.Guild;
|
var guild = Context.Guild;
|
||||||
var config = Boyfriend.GetGuildConfig(guild.Id);
|
var data = GuildData.FromSocketGuild(guild);
|
||||||
var muteRole = Utils.GetMuteRole(guild);
|
Utils.SetCurrentLanguage(guild);
|
||||||
Utils.SetCurrentLanguage(guild.Id);
|
|
||||||
|
|
||||||
if (GetMember().Roles.Contains(muteRole)) {
|
if (GetMember().Roles.Contains(data.MuteRole)) {
|
||||||
_ = Context.Message.ReplyAsync(Messages.UserCannotUnmuteThemselves);
|
_ = Context.Message.ReplyAsync(Messages.UserCannotUnmuteThemselves);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -42,7 +43,7 @@ public sealed class CommandProcessor {
|
||||||
var list = Context.Message.Content.Split("\n");
|
var list = Context.Message.Content.Split("\n");
|
||||||
var cleanList = Context.Message.CleanContent.Split("\n");
|
var cleanList = Context.Message.CleanContent.Split("\n");
|
||||||
for (var i = 0; i < list.Length; i++)
|
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) {
|
try { Task.WaitAll(_tasks.ToArray()); } catch (AggregateException e) {
|
||||||
foreach (var ex in e.InnerExceptions)
|
foreach (var ex in e.InnerExceptions)
|
||||||
|
@ -52,7 +53,7 @@ public sealed class CommandProcessor {
|
||||||
|
|
||||||
_tasks.Clear();
|
_tasks.Clear();
|
||||||
|
|
||||||
if (ConfigWriteScheduled) await Boyfriend.WriteGuildConfigAsync(guild.Id);
|
if (ConfigWriteScheduled) await data.Save(true);
|
||||||
|
|
||||||
SendFeedbacks();
|
SendFeedbacks();
|
||||||
}
|
}
|
||||||
|
@ -80,7 +81,7 @@ public sealed class CommandProcessor {
|
||||||
public void Audit(string action, bool isPublic = true) {
|
public void Audit(string action, bool isPublic = true) {
|
||||||
var format = $"*[{Context.User.Mention}: {action}]*";
|
var format = $"*[{Context.User.Mention}: {action}]*";
|
||||||
if (isPublic) Utils.SafeAppendToBuilder(_stackedPublicFeedback, format, Context.Guild.SystemChannel);
|
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);
|
if (_tasks.Count is 0) SendFeedbacks(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +89,7 @@ public sealed class CommandProcessor {
|
||||||
if (reply && _stackedReplyMessage.Length > 0)
|
if (reply && _stackedReplyMessage.Length > 0)
|
||||||
_ = Context.Message.ReplyAsync(_stackedReplyMessage.ToString(), false, null, AllowedMentions.None);
|
_ = 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;
|
var systemChannel = Context.Guild.SystemChannel;
|
||||||
if (_stackedPrivateFeedback.Length > 0 && adminChannel is not null &&
|
if (_stackedPrivateFeedback.Length > 0 && adminChannel is not null &&
|
||||||
adminChannel.Id != Context.Message.Channel.Id) {
|
adminChannel.Id != Context.Message.Channel.Id) {
|
||||||
|
|
|
@ -28,12 +28,14 @@ public sealed class BanCommand : ICommand {
|
||||||
var guildBanMessage = $"({author}) {reason}";
|
var guildBanMessage = $"({author}) {reason}";
|
||||||
await guild.AddBanAsync(toBan, 0, guildBanMessage);
|
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,
|
var feedback = string.Format(Messages.FeedbackUserBanned, toBan.Mention,
|
||||||
Utils.GetHumanizedTimeOffset(duration), Utils.Wrap(reason));
|
Utils.GetHumanizedTimeOffset(duration), Utils.Wrap(reason));
|
||||||
cmd.Reply(feedback, ReplyEmojis.Banned);
|
cmd.Reply(feedback, ReplyEmojis.Banned);
|
||||||
cmd.Audit(feedback);
|
cmd.Audit(feedback);
|
||||||
|
|
||||||
GuildData.FromSocketGuild(guild).MemberData[toBan.Id].BannedUntil
|
|
||||||
= DateTimeOffset.Now.Add(duration).ToUnixTimeSeconds();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using Boyfriend.Data;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
|
||||||
|
@ -22,6 +23,8 @@ public sealed class KickCommand : ICommand {
|
||||||
string.Format(Messages.YouWereKicked, cmd.Context.User.Mention, cmd.Context.Guild.Name,
|
string.Format(Messages.YouWereKicked, cmd.Context.User.Mention, cmd.Context.Guild.Name,
|
||||||
Utils.Wrap(reason)));
|
Utils.Wrap(reason)));
|
||||||
|
|
||||||
|
GuildData.FromSocketGuild(cmd.Context.Guild).MemberData[toKick.Id].Roles.Clear();
|
||||||
|
|
||||||
await toKick.KickAsync(guildKickMessage);
|
await toKick.KickAsync(guildKickMessage);
|
||||||
var format = string.Format(Messages.FeedbackMemberKicked, toKick.Mention, Utils.Wrap(reason));
|
var format = string.Format(Messages.FeedbackMemberKicked, toKick.Mention, Utils.Wrap(reason));
|
||||||
cmd.Reply(format, ReplyEmojis.Kicked);
|
cmd.Reply(format, ReplyEmojis.Kicked);
|
||||||
|
|
|
@ -36,7 +36,8 @@ public sealed class MuteCommand : ICommand {
|
||||||
var hasDuration = duration.TotalSeconds > 0;
|
var hasDuration = duration.TotalSeconds > 0;
|
||||||
|
|
||||||
if (role is not null) {
|
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);
|
await toMute.AddRoleAsync(role, requestOptions);
|
||||||
|
|
||||||
|
|
19
Boyfriend/Commands/RemindCommand.cs
Normal file
19
Boyfriend/Commands/RemindCommand.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ public sealed class SettingsCommand : ICommand {
|
||||||
if (args.Length is 0) {
|
if (args.Length is 0) {
|
||||||
var currentSettings = Boyfriend.StringBuilder.AppendLine(Messages.CurrentSettings);
|
var currentSettings = Boyfriend.StringBuilder.AppendLine(Messages.CurrentSettings);
|
||||||
|
|
||||||
foreach (var setting in GuildData.DefaultConfiguration) {
|
foreach (var setting in GuildData.DefaultPreferences) {
|
||||||
var format = "{0}";
|
var format = "{0}";
|
||||||
var currentValue = config[setting.Key] is "default"
|
var currentValue = config[setting.Key] is "default"
|
||||||
? Messages.DefaultWelcomeMessage
|
? Messages.DefaultWelcomeMessage
|
||||||
|
@ -47,7 +47,7 @@ public sealed class SettingsCommand : ICommand {
|
||||||
var exists = false;
|
var exists = false;
|
||||||
// ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator
|
// ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator
|
||||||
// Too many allocations
|
// Too many allocations
|
||||||
foreach (var setting in GuildData.DefaultConfiguration.Keys) {
|
foreach (var setting in GuildData.DefaultPreferences.Keys) {
|
||||||
if (selectedSetting != setting.ToLower()) continue;
|
if (selectedSetting != setting.ToLower()) continue;
|
||||||
selectedSetting = setting;
|
selectedSetting = setting;
|
||||||
exists = true;
|
exists = true;
|
||||||
|
@ -74,7 +74,7 @@ public sealed class SettingsCommand : ICommand {
|
||||||
}
|
}
|
||||||
} else { value = "reset"; }
|
} else { value = "reset"; }
|
||||||
|
|
||||||
if (IsBool(GuildData.DefaultConfiguration[selectedSetting]) && !IsBool(value)) {
|
if (IsBool(GuildData.DefaultPreferences[selectedSetting]) && !IsBool(value)) {
|
||||||
value = value switch {
|
value = value switch {
|
||||||
"y" or "yes" or "д" or "да" => "true",
|
"y" or "yes" or "д" or "да" => "true",
|
||||||
"n" or "no" or "н" or "нет" => "false",
|
"n" or "no" or "н" or "нет" => "false",
|
||||||
|
@ -99,14 +99,14 @@ public sealed class SettingsCommand : ICommand {
|
||||||
|
|
||||||
var formattedValue = selectedSetting switch {
|
var formattedValue = selectedSetting switch {
|
||||||
"WelcomeMessage" => Utils.Wrap(Messages.DefaultWelcomeMessage),
|
"WelcomeMessage" => Utils.Wrap(Messages.DefaultWelcomeMessage),
|
||||||
"EventStartedReceivers" => Utils.Wrap(GuildData.DefaultConfiguration[selectedSetting])!,
|
"EventStartedReceivers" => Utils.Wrap(GuildData.DefaultPreferences[selectedSetting])!,
|
||||||
_ => value is "reset" or "default" ? Messages.SettingNotDefined
|
_ => value is "reset" or "default" ? Messages.SettingNotDefined
|
||||||
: IsBool(value) ? YesOrNo(value is "true")
|
: IsBool(value) ? YesOrNo(value is "true")
|
||||||
: string.Format(formatting, value)
|
: string.Format(formatting, value)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (value is "reset" or "default") {
|
if (value is "reset" or "default") {
|
||||||
config[selectedSetting] = GuildData.DefaultConfiguration[selectedSetting];
|
config[selectedSetting] = GuildData.DefaultPreferences[selectedSetting];
|
||||||
} else {
|
} else {
|
||||||
if (value == config[selectedSetting]) {
|
if (value == config[selectedSetting]) {
|
||||||
cmd.Reply(string.Format(Messages.SettingsNothingChanged, localizedSelectedSetting, formattedValue),
|
cmd.Reply(string.Format(Messages.SettingsNothingChanged, localizedSelectedSetting, formattedValue),
|
||||||
|
@ -139,7 +139,7 @@ public sealed class SettingsCommand : ICommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedSetting is "Lang") {
|
if (selectedSetting is "Lang") {
|
||||||
Utils.SetCurrentLanguage(guild.Id);
|
Utils.SetCurrentLanguage(guild);
|
||||||
localizedSelectedSetting = Utils.GetMessage($"Settings{selectedSetting}");
|
localizedSelectedSetting = Utils.GetMessage($"Settings{selectedSetting}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,12 @@ public sealed class UnmuteCommand : ICommand {
|
||||||
public static async Task UnmuteMemberAsync(CommandProcessor cmd, SocketGuildUser toUnmute,
|
public static async Task UnmuteMemberAsync(CommandProcessor cmd, SocketGuildUser toUnmute,
|
||||||
string reason) {
|
string reason) {
|
||||||
var requestOptions = Utils.GetRequestOptions($"({cmd.Context.User}) {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)) {
|
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 {
|
} else {
|
||||||
if (toUnmute.TimedOutUntil is null || toUnmute.TimedOutUntil.Value.ToUnixTimeSeconds() <
|
if (toUnmute.TimedOutUntil is null || toUnmute.TimedOutUntil.Value.ToUnixTimeSeconds() <
|
||||||
DateTimeOffset.Now.ToUnixTimeSeconds()) {
|
DateTimeOffset.Now.ToUnixTimeSeconds()) {
|
||||||
|
@ -31,7 +33,7 @@ public sealed class UnmuteCommand : ICommand {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await toUnmute.RemoveTimeOutAsync();
|
await toUnmute.RemoveTimeOutAsync(requestOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
var feedback = string.Format(Messages.FeedbackMemberUnmuted, toUnmute.Mention, Utils.Wrap(reason));
|
var feedback = string.Format(Messages.FeedbackMemberUnmuted, toUnmute.Mention, Utils.Wrap(reason));
|
||||||
|
|
|
@ -5,7 +5,7 @@ using Discord.WebSocket;
|
||||||
namespace Boyfriend.Data;
|
namespace Boyfriend.Data;
|
||||||
|
|
||||||
public record GuildData {
|
public record GuildData {
|
||||||
public static readonly Dictionary<string, string> DefaultConfiguration = new() {
|
public static readonly Dictionary<string, string> DefaultPreferences = new() {
|
||||||
{ "Prefix", "!" },
|
{ "Prefix", "!" },
|
||||||
{ "Lang", "en" },
|
{ "Lang", "en" },
|
||||||
{ "ReceiveStartupMessages", "false" },
|
{ "ReceiveStartupMessages", "false" },
|
||||||
|
@ -21,6 +21,7 @@ public record GuildData {
|
||||||
{ "EventNotificationRole", "0" },
|
{ "EventNotificationRole", "0" },
|
||||||
{ "EventNotificationChannel", "0" },
|
{ "EventNotificationChannel", "0" },
|
||||||
{ "EventEarlyNotificationOffset", "0" }
|
{ "EventEarlyNotificationOffset", "0" }
|
||||||
|
// TODO: { "AutoStartEvents", "false" }
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly Dictionary<ulong, GuildData> GuildDataDictionary = new();
|
private static readonly Dictionary<ulong, GuildData> GuildDataDictionary = new();
|
||||||
|
@ -36,52 +37,49 @@ public record GuildData {
|
||||||
[SuppressMessage("Performance", "CA1853:Unnecessary call to \'Dictionary.ContainsKey(key)\'")]
|
[SuppressMessage("Performance", "CA1853:Unnecessary call to \'Dictionary.ContainsKey(key)\'")]
|
||||||
// https://github.com/dotnet/roslyn-analyzers/issues/6377
|
// https://github.com/dotnet/roslyn-analyzers/issues/6377
|
||||||
private GuildData(SocketGuild guild) {
|
private GuildData(SocketGuild guild) {
|
||||||
var id = guild.Id;
|
if (!Directory.Exists($"{_id}")) Directory.CreateDirectory($"{_id}");
|
||||||
if (!Directory.Exists($"{id}")) Directory.CreateDirectory($"{id}");
|
if (!Directory.Exists($"{_id}/MemberData")) Directory.CreateDirectory($"{_id}/MemberData");
|
||||||
if (!Directory.Exists($"{id}/MemberData")) Directory.CreateDirectory($"{id}/MemberData");
|
if (!File.Exists($"{_id}/Configuration.json")) File.Create($"{_id}/Configuration.json").Dispose();
|
||||||
if (!File.Exists($"{id}/Configuration.json")) File.Create($"{id}/Configuration.json").Dispose();
|
|
||||||
Preferences
|
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>();
|
new Dictionary<string, string>();
|
||||||
|
|
||||||
// ReSharper disable twice ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator
|
// ReSharper disable twice ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator
|
||||||
if (Preferences.Keys.Count < DefaultConfiguration.Keys.Count)
|
if (Preferences.Keys.Count < DefaultPreferences.Keys.Count)
|
||||||
foreach (var key in DefaultConfiguration.Keys)
|
foreach (var key in DefaultPreferences.Keys)
|
||||||
if (!Preferences.ContainsKey(key))
|
if (!Preferences.ContainsKey(key))
|
||||||
Preferences.Add(key, DefaultConfiguration[key]);
|
Preferences.Add(key, DefaultPreferences[key]);
|
||||||
if (Preferences.Keys.Count > DefaultConfiguration.Keys.Count)
|
if (Preferences.Keys.Count > DefaultPreferences.Keys.Count)
|
||||||
foreach (var key in Preferences.Keys)
|
foreach (var key in Preferences.Keys)
|
||||||
if (!DefaultConfiguration.ContainsKey(key))
|
if (!DefaultPreferences.ContainsKey(key))
|
||||||
Preferences.Remove(key);
|
Preferences.Remove(key);
|
||||||
Preferences.TrimExcess();
|
Preferences.TrimExcess();
|
||||||
|
|
||||||
MemberData = new Dictionary<ulong, MemberData>();
|
MemberData = new Dictionary<ulong, MemberData>();
|
||||||
foreach (var data in Directory.GetFiles($"{id}/MemberData")) {
|
foreach (var data in Directory.GetFiles($"{_id}/MemberData")) {
|
||||||
var deserialised = JsonSerializer.Deserialize<MemberData>(File.ReadAllText($"{id}/MemberData/{data}.json"));
|
var deserialised
|
||||||
|
= JsonSerializer.Deserialize<MemberData>(File.ReadAllText($"{_id}/MemberData/{data}.json"));
|
||||||
MemberData.Add(deserialised!.Id, deserialised);
|
MemberData.Add(deserialised!.Id, deserialised);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (guild.MemberCount > MemberData.Count)
|
|
||||||
foreach (var member in guild.Users) {
|
foreach (var member in guild.Users) {
|
||||||
if (MemberData.TryGetValue(member.Id, out var memberData)) {
|
if (MemberData.TryGetValue(member.Id, out var memberData)) {
|
||||||
if (!memberData.IsInGuild &&
|
if (!memberData.IsInGuild &&
|
||||||
DateTimeOffset.Now.ToUnixTimeSeconds() -
|
DateTimeOffset.Now.ToUnixTimeSeconds() -
|
||||||
Math.Max(memberData.LeftAt.Last(), memberData.BannedUntil) >
|
Math.Max(memberData.LeftAt.Last(), memberData.BannedUntil) >
|
||||||
60 * 60 * 24 * 30) {
|
60 * 60 * 24 * 30) {
|
||||||
File.Delete($"{id}/MemberData/{memberData.Id}.json");
|
File.Delete($"{_id}/MemberData/{memberData.Id}.json");
|
||||||
MemberData.Remove(memberData.Id);
|
MemberData.Remove(memberData.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var data = new MemberData(member);
|
MemberData.Add(member.Id, new MemberData(member));
|
||||||
MemberData.Add(member.Id, data);
|
|
||||||
File.WriteAllText($"{id}/MemberData/{data.Id}.json",
|
|
||||||
JsonSerializer.Serialize(data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GuildDataDictionary.Add(id, this);
|
MemberData.TrimExcess();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SocketRole? MuteRole {
|
public SocketRole? MuteRole {
|
||||||
|
@ -98,4 +96,14 @@ public record GuildData {
|
||||||
GuildDataDictionary.Add(guild.Id, newData);
|
GuildDataDictionary.Add(guild.Id, newData);
|
||||||
return 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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
using System.Diagnostics;
|
||||||
|
using Boyfriend.Data;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Rest;
|
using Discord.Rest;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
@ -26,9 +28,9 @@ public static class EventHandler {
|
||||||
var i = Random.Shared.Next(3);
|
var i = Random.Shared.Next(3);
|
||||||
|
|
||||||
foreach (var guild in Client.Guilds) {
|
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"]));
|
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;
|
if (config["ReceiveStartupMessages"] is not "true" || channel is null) continue;
|
||||||
_ = channel.SendMessageAsync(string.Format(Messages.Ready, Utils.GetBeep(i)));
|
_ = channel.SendMessageAsync(string.Format(Messages.Ready, Utils.GetBeep(i)));
|
||||||
|
@ -46,7 +48,7 @@ public static class EventHandler {
|
||||||
|
|
||||||
var guild = gChannel.Guild;
|
var guild = gChannel.Guild;
|
||||||
|
|
||||||
Utils.SetCurrentLanguage(guild.Id);
|
Utils.SetCurrentLanguage(guild);
|
||||||
|
|
||||||
var mention = msg.Author.Mention;
|
var mention = msg.Author.Mention;
|
||||||
|
|
||||||
|
@ -58,7 +60,7 @@ public static class EventHandler {
|
||||||
|
|
||||||
await Utils.SendFeedbackAsync(string.Format(Messages.CachedMessageDeleted, msg.Author.Mention,
|
await Utils.SendFeedbackAsync(string.Format(Messages.CachedMessageDeleted, msg.Author.Mention,
|
||||||
Utils.MentionChannel(channel.Id),
|
Utils.MentionChannel(channel.Id),
|
||||||
Utils.Wrap(msg.CleanContent)), guild.Id, mention);
|
Utils.Wrap(msg.CleanContent)), guild, mention);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Task MessageReceivedEvent(IDeletable messageParam) {
|
private static Task MessageReceivedEvent(IDeletable messageParam) {
|
||||||
|
@ -82,19 +84,20 @@ public static class EventHandler {
|
||||||
msg.CleanContent == messageSocket.CleanContent || msg.Author.IsBot) return;
|
msg.CleanContent == messageSocket.CleanContent || msg.Author.IsBot) return;
|
||||||
|
|
||||||
var guild = gChannel.Guild;
|
var guild = gChannel.Guild;
|
||||||
Utils.SetCurrentLanguage(guild.Id);
|
Utils.SetCurrentLanguage(guild);
|
||||||
|
|
||||||
var isLimitedSpace = msg.CleanContent.Length + messageSocket.CleanContent.Length < 1940;
|
var isLimitedSpace = msg.CleanContent.Length + messageSocket.CleanContent.Length < 1940;
|
||||||
|
|
||||||
await Utils.SendFeedbackAsync(string.Format(Messages.CachedMessageEdited, Utils.MentionChannel(channel.Id),
|
await Utils.SendFeedbackAsync(string.Format(Messages.CachedMessageEdited, Utils.MentionChannel(channel.Id),
|
||||||
Utils.Wrap(msg.CleanContent, isLimitedSpace), Utils.Wrap(messageSocket.CleanContent, isLimitedSpace)),
|
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) {
|
private static async Task UserJoinedEvent(SocketGuildUser user) {
|
||||||
var guild = user.Guild;
|
var guild = user.Guild;
|
||||||
var config = Boyfriend.GetGuildConfig(guild.Id);
|
var data = GuildData.FromSocketGuild(guild);
|
||||||
Utils.SetCurrentLanguage(guild.Id);
|
var config = data.Preferences;
|
||||||
|
Utils.SetCurrentLanguage(guild);
|
||||||
|
|
||||||
if (config["SendWelcomeMessages"] is "true")
|
if (config["SendWelcomeMessages"] is "true")
|
||||||
await Utils.SilentSendAsync(guild.SystemChannel,
|
await Utils.SilentSendAsync(guild.SystemChannel,
|
||||||
|
@ -103,27 +106,42 @@ public static class EventHandler {
|
||||||
: config["WelcomeMessage"], user.Mention, guild.Name));
|
: config["WelcomeMessage"], user.Mention, guild.Name));
|
||||||
|
|
||||||
if (config["StarterRole"] is not "0") await user.AddRoleAsync(ulong.Parse(config["StarterRole"]));
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task UserLeftEvent(SocketGuildUser user) {
|
if (memberData.MutedUntil < DateTimeOffset.Now.ToUnixTimeSeconds()) {
|
||||||
var guild = user.Guild;
|
if (data.MuteRole is not null)
|
||||||
var config = Boyfriend.GetGuildConfig(guild.Id);
|
await user.AddRoleAsync(data.MuteRole);
|
||||||
Utils.SetCurrentLanguage(guild.Id);
|
else
|
||||||
|
await user.SetTimeOutAsync(
|
||||||
|
TimeSpan.FromSeconds(DateTimeOffset.Now.ToUnixTimeSeconds() - memberData.MutedUntil));
|
||||||
|
|
||||||
if (config["SendWelcomeMessages"] is "true")
|
if (config["RemoveRolesOnMute"] is "false" && config["ReturnRolesOnRejoin"] is "true")
|
||||||
await Utils.SilentSendAsync(guild.SystemChannel,
|
await user.AddRolesAsync(memberData.Roles);
|
||||||
string.Format(config["WelcomeMessage"] is "default"
|
} else if (config["ReturnRolesOnRejoin"] is "true") { await user.AddRolesAsync(memberData.Roles); }
|
||||||
? 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) {
|
private static async Task ScheduledEventCreatedEvent(SocketGuildEvent scheduledEvent) {
|
||||||
var guild = scheduledEvent.Guild;
|
var guild = scheduledEvent.Guild;
|
||||||
var eventConfig = Boyfriend.GetGuildConfig(guild.Id);
|
var eventConfig = GuildData.FromSocketGuild(guild).Preferences;
|
||||||
var channel = Utils.GetEventNotificationChannel(guild);
|
var channel = Utils.GetEventNotificationChannel(guild);
|
||||||
Utils.SetCurrentLanguage(guild.Id);
|
Utils.SetCurrentLanguage(guild);
|
||||||
|
|
||||||
if (channel is not null) {
|
if (channel is not null) {
|
||||||
var role = guild.GetRole(ulong.Parse(eventConfig["EventNotificationRole"]));
|
var role = guild.GetRole(ulong.Parse(eventConfig["EventNotificationRole"]));
|
||||||
|
@ -141,17 +159,13 @@ public static class EventHandler {
|
||||||
scheduledEvent.StartTime.ToUnixTimeSeconds().ToString(), descAndLink),
|
scheduledEvent.StartTime.ToUnixTimeSeconds().ToString(), descAndLink),
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eventConfig["EventEarlyNotificationOffset"] is not "0")
|
|
||||||
_ = Utils.SendEarlyEventStartNotificationAsync(channel, scheduledEvent,
|
|
||||||
int.Parse(eventConfig["EventEarlyNotificationOffset"]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task ScheduledEventCancelledEvent(SocketGuildEvent scheduledEvent) {
|
private static async Task ScheduledEventCancelledEvent(SocketGuildEvent scheduledEvent) {
|
||||||
var guild = scheduledEvent.Guild;
|
var guild = scheduledEvent.Guild;
|
||||||
var eventConfig = Boyfriend.GetGuildConfig(guild.Id);
|
var eventConfig = GuildData.FromSocketGuild(guild).Preferences;
|
||||||
var channel = Utils.GetEventNotificationChannel(guild);
|
var channel = Utils.GetEventNotificationChannel(guild);
|
||||||
Utils.SetCurrentLanguage(guild.Id);
|
Utils.SetCurrentLanguage(guild);
|
||||||
if (channel is not null)
|
if (channel is not null)
|
||||||
await channel.SendMessageAsync(string.Format(Messages.EventCancelled, Utils.Wrap(scheduledEvent.Name),
|
await channel.SendMessageAsync(string.Format(Messages.EventCancelled, Utils.Wrap(scheduledEvent.Name),
|
||||||
eventConfig["FrowningFace"] is "true" ? $" {Messages.SettingsFrowningFace}" : ""));
|
eventConfig["FrowningFace"] is "true" ? $" {Messages.SettingsFrowningFace}" : ""));
|
||||||
|
@ -159,9 +173,9 @@ public static class EventHandler {
|
||||||
|
|
||||||
private static async Task ScheduledEventStartedEvent(SocketGuildEvent scheduledEvent) {
|
private static async Task ScheduledEventStartedEvent(SocketGuildEvent scheduledEvent) {
|
||||||
var guild = scheduledEvent.Guild;
|
var guild = scheduledEvent.Guild;
|
||||||
var eventConfig = Boyfriend.GetGuildConfig(guild.Id);
|
var eventConfig = GuildData.FromSocketGuild(guild).Preferences;
|
||||||
var channel = Utils.GetEventNotificationChannel(guild);
|
var channel = Utils.GetEventNotificationChannel(guild);
|
||||||
Utils.SetCurrentLanguage(guild.Id);
|
Utils.SetCurrentLanguage(guild);
|
||||||
|
|
||||||
if (channel is not null) {
|
if (channel is not null) {
|
||||||
var receivers = eventConfig["EventStartedReceivers"];
|
var receivers = eventConfig["EventStartedReceivers"];
|
||||||
|
@ -183,7 +197,7 @@ public static class EventHandler {
|
||||||
private static async Task ScheduledEventCompletedEvent(SocketGuildEvent scheduledEvent) {
|
private static async Task ScheduledEventCompletedEvent(SocketGuildEvent scheduledEvent) {
|
||||||
var guild = scheduledEvent.Guild;
|
var guild = scheduledEvent.Guild;
|
||||||
var channel = Utils.GetEventNotificationChannel(guild);
|
var channel = Utils.GetEventNotificationChannel(guild);
|
||||||
Utils.SetCurrentLanguage(guild.Id);
|
Utils.SetCurrentLanguage(guild);
|
||||||
if (channel is not null)
|
if (channel is not null)
|
||||||
await channel.SendMessageAsync(string.Format(Messages.EventCompleted, Utils.Wrap(scheduledEvent.Name),
|
await channel.SendMessageAsync(string.Format(Messages.EventCompleted, Utils.Wrap(scheduledEvent.Name),
|
||||||
Utils.GetHumanizedTimeOffset(DateTimeOffset.Now.Subtract(scheduledEvent.StartTime))));
|
Utils.GetHumanizedTimeOffset(DateTimeOffset.Now.Subtract(scheduledEvent.StartTime))));
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Globalization;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using Boyfriend.Data;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Net;
|
using Discord.Net;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
@ -28,9 +29,8 @@ public static partial class Utils {
|
||||||
return GetMessage($"Beep{(i < 0 ? Random.Shared.Next(3) + 1 : ++i)}");
|
return GetMessage($"Beep{(i < 0 ? Random.Shared.Next(3) + 1 : ++i)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SocketTextChannel? GetBotLogChannel(ulong id) {
|
public static SocketTextChannel? GetBotLogChannel(SocketGuild guild) {
|
||||||
return Boyfriend.Client.GetGuild(id)
|
return guild.GetTextChannel(ParseMention(GuildData.FromSocketGuild(guild).Preferences["BotLogChannel"]));
|
||||||
.GetTextChannel(ParseMention(Boyfriend.GetGuildConfig(id)["BotLogChannel"]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string? Wrap(string? original, bool limitedSpace = false) {
|
public static string? Wrap(string? original, bool limitedSpace = false) {
|
||||||
|
@ -91,22 +91,22 @@ public static partial class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task
|
public static async Task
|
||||||
SendFeedbackAsync(string feedback, ulong guildId, string mention, bool sendPublic = false) {
|
SendFeedbackAsync(string feedback, SocketGuild guild, string mention, bool sendPublic = false) {
|
||||||
var adminChannel = GetBotLogChannel(guildId);
|
var adminChannel = GetBotLogChannel(guild);
|
||||||
var systemChannel = Boyfriend.Client.GetGuild(guildId).SystemChannel;
|
var systemChannel = guild.SystemChannel;
|
||||||
var toSend = $"*[{mention}: {feedback}]*";
|
var toSend = $"*[{mention}: {feedback}]*";
|
||||||
if (adminChannel is not null) await SilentSendAsync(adminChannel, toSend);
|
if (adminChannel is not null) await SilentSendAsync(adminChannel, toSend);
|
||||||
if (sendPublic && systemChannel is not null) await SilentSendAsync(systemChannel, toSend);
|
if (sendPublic && systemChannel is not null) await SilentSendAsync(systemChannel, toSend);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetHumanizedTimeOffset(TimeSpan span) {
|
public static string GetHumanizedTimeOffset(TimeSpan span) {
|
||||||
return span.TotalSeconds > 0
|
return span.TotalSeconds < 1
|
||||||
? $" {span.Humanize(2, minUnit: TimeUnit.Second, maxUnit: TimeUnit.Month, culture: Messages.Culture.Name.Contains("RU") ? CultureInfoCache["ru"] : Messages.Culture)}"
|
? Messages.Ever
|
||||||
: 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) {
|
public static void SetCurrentLanguage(SocketGuild guild) {
|
||||||
Messages.Culture = CultureInfoCache[Boyfriend.GetGuildConfig(guildId)["Lang"]];
|
Messages.Culture = CultureInfoCache[GuildData.FromSocketGuild(guild).Preferences["Lang"]];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SafeAppendToBuilder(StringBuilder appendTo, string appendWhat, SocketTextChannel? channel) {
|
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) {
|
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]")]
|
[GeneratedRegex("[^0-9]")]
|
||||||
|
|
Loading…
Add table
Reference in a new issue