Many small changes/fixes, and switching autoreporting to webhook
This commit is contained in:
parent
6f2ba92009
commit
f4ba54e39b
4 changed files with 49 additions and 39 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in a new issue