Remove guild cache from BirthdayBot

Guild information no longer loaded on join, but instead on command
invocation. This information is to be passed on directly to the command
handler.
This commit is contained in:
Noi 2020-07-16 12:23:40 -07:00
parent f71552c46d
commit 7ac15e21a1
2 changed files with 25 additions and 38 deletions

View file

@ -5,8 +5,8 @@ using Discord.Net;
using Discord.Webhook; using Discord.Webhook;
using Discord.WebSocket; using Discord.WebSocket;
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using static BirthdayBot.UserInterface.CommandsCommon; using static BirthdayBot.UserInterface.CommandsCommon;
@ -20,20 +20,20 @@ namespace BirthdayBot
private readonly HelpInfoCommands _cmdsHelp; private readonly HelpInfoCommands _cmdsHelp;
private readonly ManagerCommands _cmdsMods; private readonly ManagerCommands _cmdsMods;
private BackgroundServiceRunner _worker; private readonly BackgroundServiceRunner _worker;
internal Configuration Config { get; } internal Configuration Config { get; }
internal DiscordShardedClient DiscordClient { get; } internal DiscordShardedClient DiscordClient { get; }
// TODO consider removal of the guild cache
internal ConcurrentDictionary<ulong, GuildStateInformation> GuildCache { get; }
internal DiscordWebhookClient LogWebhook { get; } internal DiscordWebhookClient LogWebhook { get; }
/// <summary>
/// Prepares the bot connection and all its event handlers
/// </summary>
public BirthdayBot(Configuration conf, DiscordShardedClient dc) public BirthdayBot(Configuration conf, DiscordShardedClient dc)
{ {
Config = conf; Config = conf;
DiscordClient = dc; DiscordClient = dc;
LogWebhook = new DiscordWebhookClient(conf.LogWebhook); LogWebhook = new DiscordWebhookClient(conf.LogWebhook);
GuildCache = new ConcurrentDictionary<ulong, GuildStateInformation>();
_worker = new BackgroundServiceRunner(this); _worker = new BackgroundServiceRunner(this);
@ -49,15 +49,17 @@ namespace BirthdayBot
foreach (var item in _cmdsMods.Commands) _dispatchCommands.Add(item.Item1, item.Item2); foreach (var item in _cmdsMods.Commands) _dispatchCommands.Add(item.Item1, item.Item2);
// Register event handlers // Register event handlers
DiscordClient.JoinedGuild += LoadGuild;
DiscordClient.GuildAvailable += LoadGuild;
DiscordClient.LeftGuild += DiscardGuild;
DiscordClient.ShardConnected += SetStatus; DiscordClient.ShardConnected += SetStatus;
DiscordClient.MessageReceived += Dispatch; DiscordClient.MessageReceived += Dispatch;
} }
/// <summary>
/// Does some more basic initialization and then connects to Discord
/// </summary>
public async Task Start() public async Task Start()
{ {
await Database.DoInitialDatabaseSetupAsync();
await DiscordClient.LoginAsync(TokenType.Bot, Config.BotToken); await DiscordClient.LoginAsync(TokenType.Bot, Config.BotToken);
await DiscordClient.StartAsync(); await DiscordClient.StartAsync();
@ -76,21 +78,6 @@ namespace BirthdayBot
DiscordClient.Dispose(); DiscordClient.Dispose();
} }
private async Task LoadGuild(SocketGuild g)
{
if (!GuildCache.ContainsKey(g.Id))
{
var gi = await GuildStateInformation.LoadSettingsAsync(Config.DatabaseSettings, g.Id);
GuildCache.TryAdd(g.Id, gi);
}
}
private Task DiscardGuild(SocketGuild g)
{
GuildCache.TryRemove(g.Id, out _);
return Task.CompletedTask;
}
private async Task SetStatus(DiscordSocketClient shard) => await shard.SetGameAsync(CommandPrefix + "help"); private async Task SetStatus(DiscordSocketClient shard) => await shard.SetGameAsync(CommandPrefix + "help");
public async Task PushErrorLog(string source, string message) public async Task PushErrorLog(string source, string message)
@ -114,9 +101,10 @@ namespace BirthdayBot
private async Task Dispatch(SocketMessage msg) private async Task Dispatch(SocketMessage msg)
{ {
if (msg.Channel is IDMChannel) return; if (!(msg.Channel is SocketTextChannel channel)) return;
if (msg.Author.IsBot) return; if (msg.Author.IsBot || msg.Author.IsWebhook) return;
// TODO determine message type (pin, join, etc) if (((IMessage)msg).Type != MessageType.Default) return;
var author = (SocketGuildUser)msg.Author;
// Limit 3: // Limit 3:
// For all cases: base command, 2 parameters. // For all cases: base command, 2 parameters.
@ -124,27 +112,25 @@ namespace BirthdayBot
var csplit = msg.Content.Split(" ", 3, StringSplitOptions.RemoveEmptyEntries); var csplit = msg.Content.Split(" ", 3, StringSplitOptions.RemoveEmptyEntries);
if (csplit.Length > 0 && csplit[0].StartsWith(CommandPrefix, StringComparison.OrdinalIgnoreCase)) if (csplit.Length > 0 && csplit[0].StartsWith(CommandPrefix, StringComparison.OrdinalIgnoreCase))
{ {
var channel = (SocketTextChannel)msg.Channel;
var author = (SocketGuildUser)msg.Author;
// Determine if it's something we're listening for. // Determine if it's something we're listening for.
// Doing this first before the block check because a block check triggers a database query. // Doing this first before the block check because a block check triggers a database query.
CommandHandler command = null; if (!_dispatchCommands.TryGetValue(csplit[0].Substring(CommandPrefix.Length), out CommandHandler command)) return;
if (!_dispatchCommands.TryGetValue(csplit[0].Substring(CommandPrefix.Length), out command)) return;
// Load guild information here
var gconf = await GuildConfiguration.LoadAsync(channel.Guild.Id);
// Ban check // Ban check
var gi = GuildCache[channel.Guild.Id]; bool isMod = gconf.ModeratorRole.HasValue && author.Roles.Any(r => r.Id == gconf.ModeratorRole.Value);
// Skip ban check if user is a manager if (!isMod) // skip check if user is a moderator
if (!gi.IsUserModerator(author))
{ {
if (gi.IsUserBlockedAsync(author.Id).GetAwaiter().GetResult()) return; if (await gconf.IsUserBlockedAsync(author.Id)) return; // silently ignore
} }
// Execute the command // Execute the command
try try
{ {
Program.Log("Command", $"{channel.Guild.Name}/{author.Username}#{author.Discriminator}: {msg.Content}"); Program.Log("Command", $"{channel.Guild.Name}/{author.Username}#{author.Discriminator}: {msg.Content}");
await command(csplit, channel, author); await command(csplit, gconf, channel, author);
} }
catch (Exception ex) catch (Exception ex)
{ {

View file

@ -1,4 +1,5 @@
using Discord.WebSocket; using BirthdayBot.Data;
using Discord.WebSocket;
using NodaTime; using NodaTime;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -22,7 +23,7 @@ namespace BirthdayBot.UserInterface
public const string NoParameterError = ":x: This command does not accept any parameters."; public const string NoParameterError = ":x: This command does not accept any parameters.";
public const string InternalError = ":x: An internal bot error occurred. The bot maintainer has been notified of the issue."; public const string InternalError = ":x: An internal bot error occurred. The bot maintainer has been notified of the issue.";
public delegate Task CommandHandler(string[] param, SocketTextChannel reqChannel, SocketGuildUser reqUser); public delegate Task CommandHandler(string[] param, GuildConfiguration gconf, SocketTextChannel reqChannel, SocketGuildUser reqUser);
protected static Dictionary<string, string> TzNameMap { protected static Dictionary<string, string> TzNameMap {
get { get {