2022-12-05 00:30:50 +00:00
|
|
|
|
using RegexBot.Common;
|
2022-03-29 05:03:01 +00:00
|
|
|
|
|
|
|
|
|
namespace RegexBot.Services.ModuleState;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Implements per-module storage and retrieval of guild-specific state data, most typically but not limited to configuration data.
|
|
|
|
|
/// </summary>
|
|
|
|
|
class ModuleStateService : Service {
|
|
|
|
|
private readonly Dictionary<ulong, EntityList> _moderators;
|
|
|
|
|
private readonly Dictionary<ulong, Dictionary<Type, object?>> _stateData;
|
2022-12-05 00:30:50 +00:00
|
|
|
|
private readonly JObject _serverConfs;
|
2022-03-29 05:03:01 +00:00
|
|
|
|
|
2022-12-05 00:30:50 +00:00
|
|
|
|
public ModuleStateService(RegexbotClient bot, JObject servers) : base(bot) {
|
2022-03-29 05:03:01 +00:00
|
|
|
|
_moderators = new();
|
|
|
|
|
_stateData = new();
|
2022-12-05 00:30:50 +00:00
|
|
|
|
_serverConfs = servers;
|
2022-03-29 05:03:01 +00:00
|
|
|
|
|
|
|
|
|
bot.DiscordClient.GuildAvailable += RefreshGuildState;
|
|
|
|
|
bot.DiscordClient.JoinedGuild += RefreshGuildState;
|
|
|
|
|
bot.DiscordClient.LeftGuild += RemoveGuildData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task RefreshGuildState(SocketGuild arg) {
|
2022-07-29 02:33:49 +00:00
|
|
|
|
if (await ProcessConfiguration(arg)) Log($"'{arg.Name}': Configuration refreshed.");
|
|
|
|
|
else Log($"'{arg.Name}': Configuration refresh failed. Retaining existing configuration and state, if any.");
|
2022-03-29 05:03:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Task RemoveGuildData(SocketGuild arg) {
|
2022-12-05 00:30:50 +00:00
|
|
|
|
_stateData.Remove(arg.Id);
|
|
|
|
|
_moderators.Remove(arg.Id);
|
2022-03-29 05:03:01 +00:00
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Hooked
|
|
|
|
|
public T? DoGetStateObj<T>(ulong guildId, Type t) {
|
2022-12-05 00:30:50 +00:00
|
|
|
|
if (_stateData.ContainsKey(guildId) && _stateData[guildId].ContainsKey(t)) {
|
|
|
|
|
// Leave handling of potential InvalidCastException to caller.
|
|
|
|
|
return (T?)_stateData[guildId][t];
|
2022-03-29 05:03:01 +00:00
|
|
|
|
}
|
2022-12-05 00:30:50 +00:00
|
|
|
|
return default;
|
2022-03-29 05:03:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Hooked
|
|
|
|
|
public EntityList DoGetModlist(ulong guildId) {
|
2022-12-05 00:30:50 +00:00
|
|
|
|
if (_moderators.TryGetValue(guildId, out var mods)) return mods;
|
|
|
|
|
else return new EntityList();
|
2022-03-29 05:03:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-07-28 21:08:23 +00:00
|
|
|
|
private async Task<bool> ProcessConfiguration(SocketGuild guild) {
|
2022-12-05 00:30:50 +00:00
|
|
|
|
var guildConf = _serverConfs[guild.Id.ToString()]?.Value<JObject>();
|
|
|
|
|
if (guildConf == null) {
|
|
|
|
|
Log($"{guild.Name} ({guild.Id}) has no configuration. Add config or consider removing bot from server.");
|
|
|
|
|
return true;
|
2022-03-29 05:03:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Load moderator list
|
2022-08-23 02:25:48 +00:00
|
|
|
|
var mods = new EntityList(guildConf["Moderators"]!);
|
2022-03-29 05:03:01 +00:00
|
|
|
|
|
|
|
|
|
// Create guild state objects for all existing modules
|
|
|
|
|
var newStates = new Dictionary<Type, object?>();
|
2022-05-20 00:03:03 +00:00
|
|
|
|
foreach (var module in BotClient.Modules) {
|
|
|
|
|
var t = module.GetType();
|
2022-03-29 05:03:01 +00:00
|
|
|
|
try {
|
2022-10-23 00:47:23 +00:00
|
|
|
|
var state = await module.CreateGuildStateAsync(guild.Id, guildConf[module.Name]);
|
2022-05-20 00:03:03 +00:00
|
|
|
|
newStates.Add(t, state);
|
2022-03-29 05:03:01 +00:00
|
|
|
|
} catch (ModuleLoadException ex) {
|
2022-08-09 03:44:20 +00:00
|
|
|
|
Log($"{module.Name} failed to read configuration for {guild.Name}: {ex.Message}");
|
2022-05-20 00:03:03 +00:00
|
|
|
|
return false;
|
2022-08-09 03:44:20 +00:00
|
|
|
|
} catch (Exception ex) {
|
|
|
|
|
Log($"Unhandled exception from {module.Name} while creating guild state for {guild.Name}:\n{ex}");
|
2022-03-29 05:03:01 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-12-05 00:30:50 +00:00
|
|
|
|
_moderators[guild.Id] = mods;
|
|
|
|
|
_stateData[guild.Id] = newStates;
|
2022-03-29 05:03:01 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|