Edit logging message filters

Additionally, remove unneeded usings and update style and nullable in affected files
This commit is contained in:
Noi 2021-11-21 13:21:42 -08:00
parent 9509f38d28
commit 67f78e068e
3 changed files with 155 additions and 185 deletions

View file

@ -1,10 +1,6 @@
using Discord.WebSocket; using Npgsql;
using Npgsql;
using NpgsqlTypes; using NpgsqlTypes;
using System;
using System.Data.Common; using System.Data.Common;
using System.Linq;
using System.Threading.Tasks;
namespace BirthdayBot.Data; namespace BirthdayBot.Data;
@ -170,6 +166,7 @@ class GuildConfiguration {
/// not exist in the database. /// not exist in the database.
/// </param> /// </param>
public static async Task<GuildConfiguration?> LoadAsync(ulong guildId, bool nullIfUnknown) { public static async Task<GuildConfiguration?> LoadAsync(ulong guildId, bool nullIfUnknown) {
// TODO nullable static analysis problem: how to indicate non-null return when nullIfUnknown parameter is true?
using (var db = await Database.OpenConnectionAsync().ConfigureAwait(false)) { using (var db = await Database.OpenConnectionAsync().ConfigureAwait(false)) {
using (var c = db.CreateCommand()) { using (var c = db.CreateCommand()) {
// Take note of ordinals for the constructor // Take note of ordinals for the constructor

View file

@ -1,20 +1,14 @@
using BirthdayBot.BackgroundServices; using BirthdayBot.BackgroundServices;
using BirthdayBot.Data; using BirthdayBot.Data;
using Discord;
using Discord.Net; using Discord.Net;
using Discord.WebSocket;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using static BirthdayBot.UserInterface.CommandsCommon; using static BirthdayBot.UserInterface.CommandsCommon;
namespace BirthdayBot namespace BirthdayBot;
{
/// <summary> /// <summary>
/// Single shard instance for Birthday Bot. This shard independently handles all input and output to Discord. /// Single shard instance for Birthday Bot. This shard independently handles all input and output to Discord.
/// </summary> /// </summary>
class ShardInstance : IDisposable class ShardInstance : IDisposable {
{
private readonly ShardManager _manager; private readonly ShardManager _manager;
private readonly ShardBackgroundWorker _background; private readonly ShardBackgroundWorker _background;
private readonly Dictionary<string, CommandHandler> _dispatchCommands; private readonly Dictionary<string, CommandHandler> _dispatchCommands;
@ -28,14 +22,13 @@ namespace BirthdayBot
/// <summary> /// <summary>
/// Returns the name of the background service currently in execution. /// Returns the name of the background service currently in execution.
/// </summary> /// </summary>
public string CurrentExecutingService => _background.CurrentExecutingService; public string? CurrentExecutingService => _background.CurrentExecutingService;
public Configuration Config => _manager.Config; public Configuration Config => _manager.Config;
/// <summary> /// <summary>
/// Prepares and configures the shard instances, but does not yet start its connection. /// Prepares and configures the shard instances, but does not yet start its connection.
/// </summary> /// </summary>
public ShardInstance(ShardManager manager, DiscordSocketClient client, Dictionary<string, CommandHandler> commands) public ShardInstance(ShardManager manager, DiscordSocketClient client, Dictionary<string, CommandHandler> commands) {
{
_manager = manager; _manager = manager;
_dispatchCommands = commands; _dispatchCommands = commands;
@ -51,8 +44,7 @@ namespace BirthdayBot
/// <summary> /// <summary>
/// Starts up this shard's connection to Discord and background task handling associated with it. /// Starts up this shard's connection to Discord and background task handling associated with it.
/// </summary> /// </summary>
public async Task StartAsync() public async Task StartAsync() {
{
await DiscordClient.LoginAsync(TokenType.Bot, Config.BotToken).ConfigureAwait(false); await DiscordClient.LoginAsync(TokenType.Bot, Config.BotToken).ConfigureAwait(false);
await DiscordClient.StartAsync().ConfigureAwait(false); await DiscordClient.StartAsync().ConfigureAwait(false);
} }
@ -61,30 +53,23 @@ namespace BirthdayBot
/// Does all necessary steps to stop this shard. This method may block for a few seconds as it waits /// Does all necessary steps to stop this shard. This method may block for a few seconds as it waits
/// for the process to finish, but will force its disposal after at most 30 seconds. /// for the process to finish, but will force its disposal after at most 30 seconds.
/// </summary> /// </summary>
public void Dispose() public void Dispose() {
{
// Unsubscribe from own events // Unsubscribe from own events
DiscordClient.Log -= Client_Log; DiscordClient.Log -= Client_Log;
DiscordClient.Ready -= Client_Ready; DiscordClient.Ready -= Client_Ready;
DiscordClient.MessageReceived -= Client_MessageReceived; DiscordClient.MessageReceived -= Client_MessageReceived;
_background.Dispose(); _background.Dispose();
try try {
{
if (!DiscordClient.LogoutAsync().Wait(15000)) if (!DiscordClient.LogoutAsync().Wait(15000))
Log("Instance", "Warning: Client has not yet logged out. Continuing cleanup."); Log("Instance", "Warning: Client has not yet logged out. Continuing cleanup.");
} } catch (Exception ex) {
catch (Exception ex)
{
Log("Instance", "Warning: Client threw an exception when logging out: " + ex.Message); Log("Instance", "Warning: Client threw an exception when logging out: " + ex.Message);
} }
try try {
{
if (!DiscordClient.StopAsync().Wait(5000)) if (!DiscordClient.StopAsync().Wait(5000))
Log("Instance", "Warning: Client has not yet stopped. Continuing cleanup."); Log("Instance", "Warning: Client has not yet stopped. Continuing cleanup.");
} } catch (Exception ex) {
catch (Exception ex)
{
Log("Instance", "Warning: Client threw an exception when stopping: " + ex.Message); Log("Instance", "Warning: Client threw an exception when stopping: " + ex.Message);
} }
@ -95,15 +80,12 @@ namespace BirthdayBot
public void Log(string source, string message) => Program.Log($"Shard {ShardId:00}] [{source}", message); public void Log(string source, string message) => Program.Log($"Shard {ShardId:00}] [{source}", message);
public void RequestDownloadUsers(ulong guildId) => _background.UserDownloader.RequestDownload(guildId);
#region Event handling #region Event handling
private Task Client_Log(LogMessage arg) private Task Client_Log(LogMessage arg) {
{ // TODO revise this some time, filters might need to be modified by now
// Suppress certain messages // Suppress certain messages
if (arg.Message != null) if (arg.Message != null) {
{ if (arg.Message.StartsWith("Unknown Dispatch ") || arg.Message.StartsWith("Missing Channel")) return Task.CompletedTask;
if (arg.Message.StartsWith("Unknown Dispatch ")) return Task.CompletedTask;
switch (arg.Message) // Connection status messages replaced by ShardManager's output switch (arg.Message) // Connection status messages replaced by ShardManager's output
{ {
case "Connecting": case "Connecting":
@ -117,12 +99,11 @@ namespace BirthdayBot
case "Server requested a reconnect": case "Server requested a reconnect":
return Task.CompletedTask; return Task.CompletedTask;
} }
if (arg.Message == "Heartbeat Errored") //if (arg.Message == "Heartbeat Errored") {
{ // // Replace this with a custom message; do not show stack trace
// Replace this with a custom message; do not show stack trace // Log("Discord.Net", $"{arg.Severity}: {arg.Message} - {arg.Exception.Message}");
Log("Discord.Net", $"{arg.Severity}: {arg.Message} - {arg.Exception.Message}"); // return Task.CompletedTask;
return Task.CompletedTask; //}
}
Log("Discord.Net", $"{arg.Severity}: {arg.Message}"); Log("Discord.Net", $"{arg.Severity}: {arg.Message}");
} }
@ -140,8 +121,7 @@ namespace BirthdayBot
/// <summary> /// <summary>
/// Determines if the incoming message is an incoming command, and dispatches to the appropriate handler if necessary. /// Determines if the incoming message is an incoming command, and dispatches to the appropriate handler if necessary.
/// </summary> /// </summary>
private async Task Client_MessageReceived(SocketMessage msg) private async Task Client_MessageReceived(SocketMessage msg) {
{
if (msg.Channel is not SocketTextChannel channel) return; if (msg.Channel is not SocketTextChannel channel) return;
if (msg.Author.IsBot || msg.Author.IsWebhook) return; if (msg.Author.IsBot || msg.Author.IsWebhook) return;
if (((IMessage)msg).Type != MessageType.Default) return; if (((IMessage)msg).Type != MessageType.Default) return;
@ -151,39 +131,32 @@ namespace BirthdayBot
// For all cases: base command, 2 parameters. // For all cases: base command, 2 parameters.
// Except this case: "bb.config", subcommand name, subcommand parameters in a single string // Except this case: "bb.config", subcommand name, subcommand parameters in a single string
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)) {
{
// Determine if it's something we're listening for. // Determine if it's something we're listening for.
if (!_dispatchCommands.TryGetValue(csplit[0][CommandPrefix.Length..], out CommandHandler command)) return; if (!_dispatchCommands.TryGetValue(csplit[0][CommandPrefix.Length..], out CommandHandler? command)) return;
// Load guild information here // Load guild information here
var gconf = await GuildConfiguration.LoadAsync(channel.Guild.Id, false); var gconf = await GuildConfiguration.LoadAsync(channel.Guild.Id, false);
// Ban check // Ban check
if (!gconf.IsBotModerator(author)) // skip check if user is a moderator if (!gconf!.IsBotModerator(author)) // skip check if user is a moderator
{ {
if (await gconf.IsUserBlockedAsync(author.Id)) return; // silently ignore if (await gconf.IsUserBlockedAsync(author.Id)) return; // silently ignore
} }
// Execute the command // Execute the command
try try {
{
Log("Command", $"{channel.Guild.Name}/{author.Username}#{author.Discriminator}: {msg.Content}"); Log("Command", $"{channel.Guild.Name}/{author.Username}#{author.Discriminator}: {msg.Content}");
await command(this, gconf, csplit, channel, author); await command(this, gconf, csplit, channel, author);
} } catch (Exception ex) {
catch (Exception ex)
{
if (ex is HttpException) return; if (ex is HttpException) return;
Log("Command", ex.ToString()); Log("Command", ex.ToString());
try try {
{
channel.SendMessageAsync(":x: An unknown error occurred. It has been reported to the bot owner.").Wait(); channel.SendMessageAsync(":x: An unknown error occurred. It has been reported to the bot owner.").Wait();
// TODO webhook report // TODO webhook report
} } catch (HttpException) { } // Fail silently
catch (HttpException) { } // Fail silently
} }
} }
} }
#endregion #endregion
}
} }

View file

@ -41,7 +41,7 @@ class ShardManager : IDisposable {
/// a key's corresponding value will temporarily become null instead of the key/value /// a key's corresponding value will temporarily become null instead of the key/value
/// pair being removed. /// pair being removed.
/// </summary> /// </summary>
private readonly Dictionary<int, ShardInstance> _shards; private readonly Dictionary<int, ShardInstance?> _shards;
private readonly Dictionary<string, CommandHandler> _dispatchCommands; private readonly Dictionary<string, CommandHandler> _dispatchCommands;
private readonly UserCommands _cmdsUser; private readonly UserCommands _cmdsUser;
@ -73,7 +73,7 @@ class ShardManager : IDisposable {
foreach (var item in _cmdsMods.Commands) _dispatchCommands.Add(item.Item1, item.Item2); foreach (var item in _cmdsMods.Commands) _dispatchCommands.Add(item.Item1, item.Item2);
// Allocate shards based on configuration // Allocate shards based on configuration
_shards = new Dictionary<int, ShardInstance>(); _shards = new Dictionary<int, ShardInstance?>();
for (int i = Config.ShardStart; i < (Config.ShardStart + Config.ShardAmount); i++) { for (int i = Config.ShardStart; i < (Config.ShardStart + Config.ShardAmount); i++) {
_shards.Add(i, null); _shards.Add(i, null);
} }
@ -203,7 +203,7 @@ class ShardManager : IDisposable {
// Remove dead shards // Remove dead shards
foreach (var dead in deadShards) { foreach (var dead in deadShards) {
_shards[dead].Dispose(); _shards[dead]!.Dispose();
_shards[dead] = null; _shards[dead] = null;
_destroyedShards++; _destroyedShards++;
} }