Improved logging and minor fixes

This commit is contained in:
Noi 2022-07-28 19:33:49 -07:00
parent 0ef78a53dc
commit e9178bc149
6 changed files with 14 additions and 39 deletions

View file

@ -33,26 +33,23 @@ internal class AutoResponder : RegexbotModule {
var definitions = GetGuildState<IEnumerable<Definition>>(ch.Guild.Id); var definitions = GetGuildState<IEnumerable<Definition>>(ch.Guild.Id);
if (definitions == null) return; // No configuration in this guild; do no further processing if (definitions == null) return; // No configuration in this guild; do no further processing
var tasks = new List<Task>();
foreach (var def in definitions) { foreach (var def in definitions) {
tasks.Add(Task.Run(async () => await ProcessMessageAsync(arg, def))); await ProcessMessageAsync(arg, def, ch);
}
} }
await Task.WhenAll(tasks); private async Task ProcessMessageAsync(SocketMessage msg, Definition def, SocketTextChannel ch) {
}
private async Task ProcessMessageAsync(SocketMessage msg, Definition def) {
if (!def.Match(msg)) return; if (!def.Match(msg)) return;
Log(ch.Guild, $"Definition '{def.Label}' triggered by {msg.Author}.");
if (def.Command == null) { if (def.Command == null) {
await msg.Channel.SendMessageAsync(def.GetResponse()); await msg.Channel.SendMessageAsync(def.GetResponse());
} else { } else {
var ch = (SocketGuildChannel)msg.Channel;
var cmdline = def.Command.Split(new char[] { ' ' }, 2); var cmdline = def.Command.Split(new char[] { ' ' }, 2);
var ps = new ProcessStartInfo() { var ps = new ProcessStartInfo() {
FileName = cmdline[0], FileName = cmdline[0],
Arguments = (cmdline.Length == 2 ? cmdline[1] : ""), Arguments = cmdline.Length == 2 ? cmdline[1] : "",
UseShellExecute = false, // ??? UseShellExecute = false, // ???
CreateNoWindow = true, CreateNoWindow = true,
RedirectStandardOutput = true RedirectStandardOutput = true

View file

@ -1,7 +1,6 @@
using RegexBot.Common; using RegexBot.Common;
namespace RegexBot.Modules.EntryRole; namespace RegexBot.Modules.EntryRole;
/// <summary> /// <summary>
/// Contains configuration data as well as per-guild timers for those awaiting role assignment. /// Contains configuration data as well as per-guild timers for those awaiting role assignment.
/// </summary> /// </summary>

View file

@ -19,7 +19,7 @@ class Ban : BanKick {
await msg.Channel.SendMessageAsync($"{SuccessMessage}\n{result.GetResultString(Module.Bot)}"); await msg.Channel.SendMessageAsync($"{SuccessMessage}\n{result.GetResultString(Module.Bot)}");
} else { } else {
// TODO custom fail message? // TODO custom fail message?
await msg.Channel.SendMessageAsync(SuccessMessage); await msg.Channel.SendMessageAsync(result.GetResultString(Module.Bot));
} }
} else { } else {
await msg.Channel.SendMessageAsync(result.GetResultString(Module.Bot)); await msg.Channel.SendMessageAsync(result.GetResultString(Module.Bot));

View file

@ -41,9 +41,9 @@ internal class ModCommands : RegexbotModule {
if (cfg.Commands.TryGetValue(cmdchk, out var c)) { if (cfg.Commands.TryGetValue(cmdchk, out var c)) {
try { try {
await c.Invoke(g, arg); await c.Invoke(g, arg);
Log($"[{g.Name}] {c.Command} invoked by {arg.Author} in #{arg.Channel.Name}."); Log(g, $"{c.Command} invoked by {arg.Author} in #{arg.Channel.Name}.");
} catch (Exception ex) { } catch (Exception ex) {
Log($"Unhandled exception while processing '{c.Label}':\n" + ex.ToString()); Log(g, $"Unhandled exception while processing '{c.Label}':\n" + ex.ToString());
await arg.Channel.SendMessageAsync($":x: An error occurred during processing ({ex.GetType().FullName}). " + await arg.Channel.SendMessageAsync($":x: An error occurred during processing ({ex.GetType().FullName}). " +
"Check the console for details."); "Check the console for details.");
} }

View file

@ -46,29 +46,15 @@ internal class RegexModerator : RegexbotModule {
var defs = GetGuildState<IEnumerable<ConfDefinition>>(ch.Guild.Id); var defs = GetGuildState<IEnumerable<ConfDefinition>>(ch.Guild.Id);
if (defs == null) return; if (defs == null) return;
// Send further processing to thread pool. // Matching and response processing
// Match checking is a CPU-intensive task, thus very little checking is done here.
var msgProcessingTasks = new List<Task>();
foreach (var item in defs) { foreach (var item in defs) {
// Need to check sender's moderator status here. Definition can't access mod list. // Need to check sender's moderator status here. Definition can't access mod list.
var isMod = GetModerators(ch.Guild.Id).IsListMatch(msg, true); var isMod = GetModerators(ch.Guild.Id).IsListMatch(msg, true);
var match = item.IsMatch(msg, isMod); if (!item.IsMatch(msg, isMod)) continue;
msgProcessingTasks.Add(Task.Run(async () => await ProcessMessage(item, ch.Guild, msg, isMod))); Log(ch.Guild, $"Rule '{item.Label}' triggered by {msg.Author}.");
} var exec = new ResponseExecutor(item, Bot, msg, (string logLine) => Log(ch.Guild, logLine));
await Task.WhenAll(msgProcessingTasks); await exec.Execute();
} }
/// <summary>
/// Does further message checking and response execution.
/// Invocations of this method are meant to be placed onto a thread separate from the caller.
/// </summary>
private async Task ProcessMessage(ConfDefinition def, SocketGuild g, SocketMessage msg, bool isMod) {
if (!def.IsMatch(msg, isMod)) return;
// TODO logging options for match result; handle here?
var executor = new ResponseExecutor(def, Bot, msg, (string logLine) => Log(g, logLine));
await executor.Execute();
} }
} }

View file

@ -22,7 +22,8 @@ class ModuleStateService : Service {
} }
private async Task RefreshGuildState(SocketGuild arg) { private async Task RefreshGuildState(SocketGuild arg) {
if (await ProcessConfiguration(arg)) Log($"Configuration refreshed for '{arg.Name}'."); if (await ProcessConfiguration(arg)) Log($"'{arg.Name}': Configuration refreshed.");
else Log($"'{arg.Name}': Configuration refresh failed. Retaining existing configuration and state, if any.");
} }
private Task RemoveGuildData(SocketGuild arg) { private Task RemoveGuildData(SocketGuild arg) {
@ -52,14 +53,6 @@ class ModuleStateService : Service {
} }
} }
/// <summary>
/// Configuration is loaded from database, and appropriate sections dispatched to their
/// respective methods for further processing.
/// </summary>
/// <remarks>
/// This takes an all-or-nothing approach. Should there be a single issue in processing
/// configuration, all existing state data is kept.
/// </remarks>
private async Task<bool> ProcessConfiguration(SocketGuild guild) { private async Task<bool> ProcessConfiguration(SocketGuild guild) {
var jstr = await LoadConfigFile(guild); var jstr = await LoadConfigFile(guild);
JObject guildConf; JObject guildConf;