Many small changes/fixes, and switching autoreporting to webhook

This commit is contained in:
Noikoio 2018-04-05 15:46:15 -07:00
parent 6f2ba92009
commit f4ba54e39b
4 changed files with 49 additions and 39 deletions

View file

@ -1,6 +1,9 @@
using Newtonsoft.Json.Linq; using Discord;
using Discord.Webhook;
using Newtonsoft.Json.Linq;
using Noikoio.RegexBot.ConfigItem; using Noikoio.RegexBot.ConfigItem;
using System; using System;
using System.Text.RegularExpressions;
namespace Noikoio.RegexBot.Module.ModLogs namespace Noikoio.RegexBot.Module.ModLogs
{ {
@ -10,16 +13,21 @@ namespace Noikoio.RegexBot.Module.ModLogs
class GuildState class GuildState
{ {
// Event reporting // Event reporting
private readonly EntityName _rptTarget; private DiscordWebhookClient _rptTarget;
private LogEntry.LogType _rptTypes; private LogEntry.LogType _rptTypes;
private ulong _rptIgnore;
/// <summary> /// <summary>
/// Target reporting channel. /// Webhook for log reporting.
/// </summary> /// </summary>
public EntityName? RptTarget => _rptTarget; public DiscordWebhookClient RptTarget => _rptTarget;
/// <summary> /// <summary>
/// Event types to send to the reporting channel. /// Event types to send to the reporting channel.
/// </summary> /// </summary>
public LogEntry.LogType RptTypes => _rptTypes; public LogEntry.LogType RptTypes => _rptTypes;
/// <summary>
/// Channel for AutoReporting to ignore.
/// </summary>
public ulong RptIgnore => _rptIgnore;
// Query command // Query command
private readonly string _qCmd; // command name private readonly string _qCmd; // command name
@ -45,19 +53,21 @@ namespace Noikoio.RegexBot.Module.ModLogs
var arcfg = cfgRoot["AutoReporting"]; var arcfg = cfgRoot["AutoReporting"];
if (arcfg == null) if (arcfg == null)
{ {
_rptTarget = default(EntityName); // NOTE: Change this if EntityName becomes a class later _rptTarget = null;
_rptTypes = LogEntry.LogType.None; _rptTypes = LogEntry.LogType.None;
_rptIgnore = 0;
} }
else if (arcfg.Type == JTokenType.Object) else if (arcfg.Type == JTokenType.Object)
{ {
string chval = arcfg["Channel"]?.Value<string>(); string whurl = arcfg["WebhookUrl"]?.Value<string>();
if (chval == null) throw new RuleImportException("Reporting channel is not defined."); if (whurl == null) throw new RuleImportException("Webhook URL for log reporting is not specified.");
if (!string.IsNullOrWhiteSpace(chval) && chval[0] == '#') var wrx = WebhookUrlParts.Match(whurl);
_rptTarget = new EntityName(chval.Substring(1, chval.Length-1), EntityType.Channel); if (!wrx.Success) throw new RuleImportException("Webhook URL for log reporting is not valid.");
else var wid = ulong.Parse(wrx.Groups[1].Value);
throw new RuleImportException("Reporting channel is not properly defined."); var wtk = wrx.Groups[2].Value;
// Require the channel's ID for now. _rptTarget = new DiscordWebhookClient(wid, wtk,
if (!_rptTarget.Id.HasValue) throw new RuleImportException("Reporting channel's ID must be specified."); new Discord.Rest.DiscordRestConfig() { DefaultRetryMode = RetryMode.RetryRatelimit });
// TODO figure out how to hook up the webhook client's log event
// TODO make optional // TODO make optional
string rpval = arcfg["Events"]?.Value<string>(); string rpval = arcfg["Events"]?.Value<string>();
@ -69,6 +79,13 @@ namespace Noikoio.RegexBot.Module.ModLogs
{ {
throw new RuleImportException(ex.Message); throw new RuleImportException(ex.Message);
} }
var ignoreId = arcfg["CacheIgnore"]?.Value<string>();
if (string.IsNullOrWhiteSpace(ignoreId)) _rptIgnore = 0;
else if (!ulong.TryParse(ignoreId, out _rptIgnore))
{
throw new RuleImportException("CacheIgnore was not set to a valid channel ID.");
}
} }
else else
{ {
@ -112,5 +129,8 @@ namespace Noikoio.RegexBot.Module.ModLogs
throw new RuleImportException("Section for QueryCommand is not correctly defined."); throw new RuleImportException("Section for QueryCommand is not correctly defined.");
} }
} }
private static Regex WebhookUrlParts =
new Regex(@"https?:\/\/discordapp.com\/api\/webhooks\/(\d+)\/([^/]+)?", RegexOptions.Compiled);
} }
} }

View file

@ -38,7 +38,8 @@ namespace Noikoio.RegexBot.Module.ModLogs
#region Event handling #region Event handling
private async Task Client_MessageReceived(SocketMessage arg) private async Task Client_MessageReceived(SocketMessage arg)
{ {
if (arg.Author.IsBot) return; if (arg.Author.IsWebhook) return;
if (arg.Channel is IDMChannel) return; // No DMs
await AddOrUpdateCacheItemAsync(arg); await AddOrUpdateCacheItemAsync(arg);
} }
@ -46,13 +47,11 @@ namespace Noikoio.RegexBot.Module.ModLogs
private async Task Client_MessageUpdated( private async Task Client_MessageUpdated(
Cacheable<IMessage, ulong> before, SocketMessage after, ISocketMessageChannel channel) Cacheable<IMessage, ulong> before, SocketMessage after, ISocketMessageChannel channel)
{ {
if (after.Author.IsBot) return; if (after.Author.IsWebhook) return;
// We only want channel messages // We only want channel messages
if (after is SocketUserMessage afterMsg && !(afterMsg is IDMChannel)) if (after is SocketUserMessage afterMsg && !(afterMsg is IDMChannel))
{ {
if (after.Author.IsBot) return;
// We're not interested in all message updates, only those that leave a timestamp. // We're not interested in all message updates, only those that leave a timestamp.
if (!afterMsg.EditedTimestamp.HasValue) return; if (!afterMsg.EditedTimestamp.HasValue) return;
} }
@ -88,11 +87,9 @@ namespace Noikoio.RegexBot.Module.ModLogs
// Check if this feature is enabled before doing anything else. // Check if this feature is enabled before doing anything else.
var cfg = _outGetConfig(guildId); var cfg = _outGetConfig(guildId);
if (cfg == null) return; if (cfg == null) return;
if (isDelete && (cfg.RptTypes & LogEntry.LogType.MsgDelete) == 0) return; if (cfg.RptIgnore != 0 && ch.Id == cfg.RptIgnore) return; // ignored channel
if (!isDelete && (cfg.RptTypes & LogEntry.LogType.MsgEdit) == 0) return; if (isDelete && (cfg.RptTypes & LogEntry.LogType.MsgDelete) == 0) return; // not reporting deletions
if (!isDelete && (cfg.RptTypes & LogEntry.LogType.MsgEdit) == 0) return; // not reporting edits
// Ignore if it's a message being deleted withing the reporting channel.
if (isDelete && cfg.RptTarget.Value.Id.Value == ch.Id) return;
// Regardless of delete or edit, it is necessary to get the equivalent database information. // Regardless of delete or edit, it is necessary to get the equivalent database information.
EntityCache.CacheUser ucd = null; EntityCache.CacheUser ucd = null;
@ -131,16 +128,9 @@ namespace Noikoio.RegexBot.Module.ModLogs
cacheMsg = "**Database error. See log.**"; cacheMsg = "**Database error. See log.**";
} }
// Find target channel, prepare and send out message // Prepare and send out message
var g = _dClient.GetGuild(guildId);
var rptTargetChannel = g?.GetTextChannel(cfg.RptTarget.Value.Id.Value);
if (rptTargetChannel == null)
{
await _outLog($"WARNING: Reporting channel {cfg.RptTarget.Value.ToString()} could not be determined.");
return;
}
var em = CreateReportEmbed(isDelete, ucd, messageId, ch, (cacheMsg, editMsg)); var em = CreateReportEmbed(isDelete, ucd, messageId, ch, (cacheMsg, editMsg));
await rptTargetChannel.SendMessageAsync("", embed: em); await cfg.RptTarget.SendMessageAsync("", embeds: new Embed[] { em });
} }
const int ReportCutoffLength = 500; const int ReportCutoffLength = 500;
@ -173,8 +163,7 @@ namespace Noikoio.RegexBot.Module.ModLogs
Fields = new System.Collections.Generic.List<EmbedFieldBuilder>(), Fields = new System.Collections.Generic.List<EmbedFieldBuilder>(),
Footer = new EmbedFooterBuilder() Footer = new EmbedFooterBuilder()
{ {
Text = "User ID: " + ucd?.UserId.ToString() ?? "Unknown", Text = "User ID: " + ucd?.UserId.ToString() ?? "Unknown"
IconUrl = _dClient.CurrentUser.GetAvatarUrl()
}, },
Timestamp = DateTimeOffset.UtcNow Timestamp = DateTimeOffset.UtcNow
}; };

View file

@ -40,8 +40,7 @@ namespace Noikoio.RegexBot.Module.ModLogs
} }
var conf = new GuildState((JObject)configSection); var conf = new GuildState((JObject)configSection);
if (conf.RptTypes != LogEntry.LogType.None) if (conf.RptTypes != LogEntry.LogType.None) await Log("Enabled event autoreporting.");
await Log("Enabled event autoreporting to " + conf.RptTarget);
return conf; return conf;
} }

View file

@ -8,7 +8,8 @@ Sample within a [server definition](serverdef.html):
"ModLogs": { "ModLogs": {
"AutoReporting": { "AutoReporting": {
"Channel": "#99999999:mod-events", "Channel": "#99999999:mod-events",
"Events": "msgedit,msgdelete" "Events": "msgedit,msgdelete",
"CacheIgnore": 1230000000000
} }
} }
``` ```
@ -24,9 +25,10 @@ The following values can be defined within the `ModLogs` object:
As its name implies, the `AutoReporting` section allows the bot operator to configure automatic reporting of one or more events as they occur to a designated reporting channel. Omitting this section in configuration disables this function. As its name implies, the `AutoReporting` section allows the bot operator to configure automatic reporting of one or more events as they occur to a designated reporting channel. Omitting this section in configuration disables this function.
The following values are accepted within this object: The following values are accepted within this object:
* Channel (*string*) - **Required.** The channel name in which to report events. * WebhookUrl (*string*) - **Required.** A webhook URL to be used by the bot for sending events.
* The channel ID is currently required to be specified (see [EntityList](entitylist.html)). This limitation will be removed in a future update. * Events (*string*) - **Required** at the moment. A comma-separated list of event types to be sent to the reporting channel.
* Events (*string*) - **Required** for now. A comma-separated list of event types to be sent to the reporting channel. * CacheIgnore (*number*) - Channel (ID) to ignore for MsgEdit and MsgDelete autoreporting. (Optional.)
* It is **highly recommended** that the reporting channel be specified, otherwise deleting a report within it will cause another report to appear.
#### Event types #### Event types
All events fall into one of a number of categories. All events fall into one of a number of categories.