Several fixes after a round of testing
Fixed the following compilation errors: -Moderators collection not initialized -Outdated method signatures for ban and kick in ModuleBase -Update author name in manifests -Fixed incorrect method signature in AutoScriptResponder Minor improvements: -Updated external dependencies -Remove unused variables in ConfDefinition of RegexModerator -Improve parallel execution of matches? -Send exception message on logging failure to reporting channel -Slightly change ModuleLoader logging output -Add Discord.Net unhandled exception output to logging -Updated link to Github -Changed GuildState exception handling message for conciseness Fixes: -SQL index creation in LoggingService -SQL view creation in UserCacheService -Add casts from ulong to long in SQL inserts -External modules no longer loaded twice -Non-Info messages from Discord.Net will now be reported -User data had not been recorded at proper times -Some modules had been returning null instead of Task with null -Guild state exception handling should not have handled config errors
This commit is contained in:
parent
2319c91fc7
commit
ffa5b5754b
14 changed files with 63 additions and 69 deletions
|
@ -46,7 +46,7 @@ namespace Kerobot
|
||||||
// Everything's ready to go. Print the welcome message here.
|
// Everything's ready to go. Print the welcome message here.
|
||||||
var ver = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
|
var ver = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
|
||||||
InstanceLogAsync(false, "Kerobot",
|
InstanceLogAsync(false, "Kerobot",
|
||||||
$"This is Kerobot v{ver.ToString(3)}. https://github.com/Noikoio/Kerobot").Wait();
|
$"This is Kerobot v{ver.ToString(3)}. https://github.com/Noiiko/Kerobot").Wait();
|
||||||
|
|
||||||
// We return to Program.cs at this point.
|
// We return to Program.cs at this point.
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
<StartupObject>Kerobot.Program</StartupObject>
|
<StartupObject>Kerobot.Program</StartupObject>
|
||||||
<AssemblyVersion>0.0.1</AssemblyVersion>
|
<Authors>Noiiko</Authors>
|
||||||
<Authors>Noikoio</Authors>
|
|
||||||
<Company />
|
<Company />
|
||||||
<Description>Advanced and flexible Discord moderation bot.</Description>
|
<Description>Advanced and flexible Discord moderation bot.</Description>
|
||||||
<FileVersion>0.0.1</FileVersion>
|
|
||||||
<Version>0.0.1</Version>
|
<Version>0.0.1</Version>
|
||||||
<LangVersion>7.2</LangVersion>
|
<LangVersion>7.2</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
@ -27,10 +25,10 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CommandLineParser" Version="2.4.3" />
|
<PackageReference Include="CommandLineParser" Version="2.5.0" />
|
||||||
<PackageReference Include="Discord.Net" Version="2.0.1" />
|
<PackageReference Include="Discord.Net" Version="2.1.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||||
<PackageReference Include="Npgsql" Version="4.0.5" />
|
<PackageReference Include="Npgsql" Version="4.0.7" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -88,23 +88,20 @@ namespace Kerobot
|
||||||
/// <param name="targetUser">The user which to perform the action to.</param>
|
/// <param name="targetUser">The user which to perform the action to.</param>
|
||||||
/// <param name="purgeDays">Number of days of prior post history to delete on ban. Must be between 0-7.</param>
|
/// <param name="purgeDays">Number of days of prior post history to delete on ban. Must be between 0-7.</param>
|
||||||
/// <param name="reason">Reason for the action. Sent to the Audit Log and user (if specified).</param>
|
/// <param name="reason">Reason for the action. Sent to the Audit Log and user (if specified).</param>
|
||||||
/// <param name="dmMsg">
|
/// <param name="sendDMToTarget">Specify whether to send a direct message to the target user informing them of the action being taken.</param>
|
||||||
/// Message to DM the target user. Set null to disable. Instances of "%s" are replaced with the guild name
|
protected Task<BanKickResult> BanAsync(SocketGuild guild, string source, ulong targetUser, int purgeDays, string reason, bool sendDMToTarget)
|
||||||
/// and instances of "%r" are replaced with the reason.
|
=> Kerobot.BanOrKickAsync(RemovalType.Ban, guild, source, targetUser, purgeDays, reason, sendDMToTarget);
|
||||||
/// </param>
|
|
||||||
protected Task<BanKickResult> BanAsync(SocketGuild guild, string source, ulong targetUser, int purgeDays, string reason, string dmMsg)
|
|
||||||
=> Kerobot.BanOrKickAsync(RemovalType.Ban, guild, source, targetUser, purgeDays, reason, dmMsg);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Similar to <see cref="BanAsync(SocketGuild, string, ulong, int, string, string)"/>, but making use of an
|
/// Similar to <see cref="BanAsync(SocketGuild, string, ulong, int, string, bool)"/>, but making use of an
|
||||||
/// EntityCache lookup to determine the target.
|
/// EntityCache lookup to determine the target.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="targetSearch">The EntityCache search string.</param>
|
/// <param name="targetSearch">The EntityCache search string.</param>
|
||||||
protected async Task<BanKickResult> BanAsync(SocketGuild guild, string source, string targetSearch, int purgeDays, string reason, string dmMsg)
|
protected async Task<BanKickResult> BanAsync(SocketGuild guild, string source, string targetSearch, int purgeDays, string reason, bool sendDMToTarget)
|
||||||
{
|
{
|
||||||
var result = await Kerobot.EcQueryUser(guild.Id, targetSearch);
|
var result = await Kerobot.EcQueryUser(guild.Id, targetSearch);
|
||||||
if (result == null) return new BanKickResult(null, false, true);
|
if (result == null) return new BanKickResult(null, false, true);
|
||||||
return await BanAsync(guild, source, result.UserID, purgeDays, reason, dmMsg);
|
return await BanAsync(guild, source, result.UserID, purgeDays, reason, sendDMToTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -117,23 +114,20 @@ namespace Kerobot
|
||||||
/// <param name="source">The user, if any, which requested the action to be taken.</param>
|
/// <param name="source">The user, if any, which requested the action to be taken.</param>
|
||||||
/// <param name="targetUser">The user which to perform the action to.</param>
|
/// <param name="targetUser">The user which to perform the action to.</param>
|
||||||
/// <param name="reason">Reason for the action. Sent to the Audit Log and user (if specified).</param>
|
/// <param name="reason">Reason for the action. Sent to the Audit Log and user (if specified).</param>
|
||||||
/// <param name="dmMsg">
|
/// <param name="sendDMToTarget">Specify whether to send a direct message to the target user informing them of the action being taken.</param>
|
||||||
/// Message to DM the target user. Set null to disable. Instances of "%s" are replaced with the guild name
|
protected Task<BanKickResult> KickAsync(SocketGuild guild, string source, ulong targetUser, string reason, bool sendDMToTarget)
|
||||||
/// and instances of "%r" are replaced with the reason.
|
=> Kerobot.BanOrKickAsync(RemovalType.Ban, guild, source, targetUser, 0, reason, sendDMToTarget);
|
||||||
/// </param>
|
|
||||||
protected Task<BanKickResult> KickAsync(SocketGuild guild, string source, ulong targetUser, string reason, string dmMsg)
|
|
||||||
=> Kerobot.BanOrKickAsync(RemovalType.Ban, guild, source, targetUser, 0, reason, dmMsg);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Similar to <see cref="KickAsync(SocketGuild, string, ulong, string, string)"/>, but making use of an
|
/// Similar to <see cref="KickAsync(SocketGuild, string, ulong, string, bool)"/>, but making use of an
|
||||||
/// EntityCache lookup to determine the target.
|
/// EntityCache lookup to determine the target.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="targetSearch">The EntityCache search string.</param>
|
/// <param name="targetSearch">The EntityCache search string.</param>
|
||||||
protected async Task<BanKickResult> KickAsync(SocketGuild guild, string source, string targetSearch, string reason, string dmMsg)
|
protected async Task<BanKickResult> KickAsync(SocketGuild guild, string source, string targetSearch, string reason, bool sendDMToTarget)
|
||||||
{
|
{
|
||||||
var result = await Kerobot.EcQueryUser(guild.Id, targetSearch);
|
var result = await Kerobot.EcQueryUser(guild.Id, targetSearch);
|
||||||
if (result == null) return new BanKickResult(null, false, true);
|
if (result == null) return new BanKickResult(null, false, true);
|
||||||
return await KickAsync(guild, source, result.UserID, reason, dmMsg);
|
return await KickAsync(guild, source, result.UserID, reason, sendDMToTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -45,7 +45,7 @@ namespace Kerobot
|
||||||
Console.WriteLine(ex.ToString());
|
Console.WriteLine(ex.ToString());
|
||||||
Environment.Exit(2);
|
Environment.Exit(2);
|
||||||
}
|
}
|
||||||
modules.AddRange(LoadModulesFromAssembly(a, k));
|
modules.AddRange(amods);
|
||||||
}
|
}
|
||||||
return modules.AsReadOnly();
|
return modules.AsReadOnly();
|
||||||
}
|
}
|
||||||
|
@ -56,15 +56,14 @@ namespace Kerobot
|
||||||
where !type.IsAssignableFrom(typeof(ModuleBase))
|
where !type.IsAssignableFrom(typeof(ModuleBase))
|
||||||
where type.GetCustomAttribute<KerobotModuleAttribute>() != null
|
where type.GetCustomAttribute<KerobotModuleAttribute>() != null
|
||||||
select type;
|
select type;
|
||||||
k.InstanceLogAsync(false, LogName,
|
k.InstanceLogAsync(false, LogName, $"Scanning {asm.GetName().Name}");
|
||||||
$"{asm.GetName().Name} has {eligibleTypes.Count()} usable types");
|
|
||||||
|
|
||||||
var newmods = new List<ModuleBase>();
|
var newmods = new List<ModuleBase>();
|
||||||
foreach (var t in eligibleTypes)
|
foreach (var t in eligibleTypes)
|
||||||
{
|
{
|
||||||
var mod = Activator.CreateInstance(t, k);
|
var mod = Activator.CreateInstance(t, k);
|
||||||
k.InstanceLogAsync(false, LogName,
|
k.InstanceLogAsync(false, LogName,
|
||||||
$"---> Instance created: {t.FullName}");
|
$"---> Loading module {t.FullName}");
|
||||||
newmods.Add((ModuleBase)mod);
|
newmods.Add((ModuleBase)mod);
|
||||||
}
|
}
|
||||||
return newmods;
|
return newmods;
|
||||||
|
|
|
@ -66,7 +66,7 @@ namespace Kerobot.Services.EntityCache
|
||||||
c.CommandText = $"create or replace view {UserView} as " +
|
c.CommandText = $"create or replace view {UserView} as " +
|
||||||
$"select {GlobalUserTable}.user_id, {GuildUserTable}.guild_id, {GuildUserTable}.first_seen, " +
|
$"select {GlobalUserTable}.user_id, {GuildUserTable}.guild_id, {GuildUserTable}.first_seen, " +
|
||||||
$"{GuildUserTable}.cache_update_time, " +
|
$"{GuildUserTable}.cache_update_time, " +
|
||||||
$"{GlobalUserTable}.username, {GlobalUserTable}.discriminator, {GlobalUserTable}.nickname, " +
|
$"{GlobalUserTable}.username, {GlobalUserTable}.discriminator, {GuildUserTable}.nickname, " +
|
||||||
$"{GlobalUserTable}.avatar_url " +
|
$"{GlobalUserTable}.avatar_url " +
|
||||||
$"from {GlobalUserTable} join {GuildUserTable} on {GlobalUserTable}.user_id = {GuildUserTable}.user_id";
|
$"from {GlobalUserTable} join {GuildUserTable} on {GlobalUserTable}.user_id = {GuildUserTable}.user_id";
|
||||||
await c.ExecuteNonQueryAsync();
|
await c.ExecuteNonQueryAsync();
|
||||||
|
@ -90,7 +90,7 @@ namespace Kerobot.Services.EntityCache
|
||||||
"on conflict (user_id) do update " +
|
"on conflict (user_id) do update " +
|
||||||
"set cache_update_time = EXCLUDED.cache_update_time, username = EXCLUDED.username, " +
|
"set cache_update_time = EXCLUDED.cache_update_time, username = EXCLUDED.username, " +
|
||||||
"discriminator = EXCLUDED.discriminator, avatar_url = EXCLUDED.avatar_url";
|
"discriminator = EXCLUDED.discriminator, avatar_url = EXCLUDED.avatar_url";
|
||||||
c.Parameters.Add("@Uid", NpgsqlDbType.Bigint).Value = current.Id;
|
c.Parameters.Add("@Uid", NpgsqlDbType.Bigint).Value = (long)current.Id;
|
||||||
c.Parameters.Add("@Uname", NpgsqlDbType.Text).Value = current.Username;
|
c.Parameters.Add("@Uname", NpgsqlDbType.Text).Value = current.Username;
|
||||||
c.Parameters.Add("@Disc", NpgsqlDbType.Text).Value = current.Discriminator;
|
c.Parameters.Add("@Disc", NpgsqlDbType.Text).Value = current.Discriminator;
|
||||||
var aurl = c.Parameters.Add("@Aurl", NpgsqlDbType.Text);
|
var aurl = c.Parameters.Add("@Aurl", NpgsqlDbType.Text);
|
||||||
|
@ -106,6 +106,9 @@ namespace Kerobot.Services.EntityCache
|
||||||
|
|
||||||
private async Task DiscordClient_GuildMemberUpdated(SocketGuildUser old, SocketGuildUser current)
|
private async Task DiscordClient_GuildMemberUpdated(SocketGuildUser old, SocketGuildUser current)
|
||||||
{
|
{
|
||||||
|
// Also update user data here, in case it's unknown (avoid foreign key constraint violation)
|
||||||
|
await DiscordClient_UserUpdated(old, current);
|
||||||
|
|
||||||
using (var db = await _kb.GetOpenNpgsqlConnectionAsync())
|
using (var db = await _kb.GetOpenNpgsqlConnectionAsync())
|
||||||
{
|
{
|
||||||
using (var c = db.CreateCommand())
|
using (var c = db.CreateCommand())
|
||||||
|
@ -113,11 +116,10 @@ namespace Kerobot.Services.EntityCache
|
||||||
c.CommandText = $"insert into {GuildUserTable} " +
|
c.CommandText = $"insert into {GuildUserTable} " +
|
||||||
"(user_id, guild_id, cache_update_time, nickname) values " +
|
"(user_id, guild_id, cache_update_time, nickname) values " +
|
||||||
"(@Uid, @Gid, now(), @Nname) " +
|
"(@Uid, @Gid, now(), @Nname) " +
|
||||||
"on conflict (user_id) do update " +
|
"on conflict (user_id, guild_id) do update " +
|
||||||
"set cache_update_time = EXCLUDED.cache_update_time, username = EXCLUDED.username, " +
|
"set cache_update_time = EXCLUDED.cache_update_time, nickname = EXCLUDED.nickname";
|
||||||
"discriminator = EXCLUDED.discriminator, avatar_url = EXCLUDED.avatar_url";
|
c.Parameters.Add("@Uid", NpgsqlDbType.Bigint).Value = (long)current.Id;
|
||||||
c.Parameters.Add("@Uid", NpgsqlDbType.Bigint).Value = current.Id;
|
c.Parameters.Add("@Gid", NpgsqlDbType.Bigint).Value = (long)current.Guild.Id;
|
||||||
c.Parameters.Add("@Gid", NpgsqlDbType.Bigint).Value = current.Guild.Id;
|
|
||||||
var nname = c.Parameters.Add("@Nname", NpgsqlDbType.Text);
|
var nname = c.Parameters.Add("@Nname", NpgsqlDbType.Text);
|
||||||
if (current.Nickname != null) nname.Value = current.Nickname;
|
if (current.Nickname != null) nname.Value = current.Nickname;
|
||||||
else nname.Value = DBNull.Value;
|
else nname.Value = DBNull.Value;
|
||||||
|
@ -130,7 +132,7 @@ namespace Kerobot.Services.EntityCache
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Querying
|
#region Querying
|
||||||
private static Regex DiscriminatorSearch = new Regex(@"(.+)#(\d{4}(?!\d))", RegexOptions.Compiled);
|
private static readonly Regex DiscriminatorSearch = new Regex(@"(.+)#(\d{4}(?!\d))", RegexOptions.Compiled);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// See <see cref="Kerobot.EcQueryUser(ulong, string)"/>.
|
/// See <see cref="Kerobot.EcQueryUser(ulong, string)"/>.
|
||||||
|
@ -174,12 +176,12 @@ namespace Kerobot.Services.EntityCache
|
||||||
var c = db.CreateCommand();
|
var c = db.CreateCommand();
|
||||||
c.CommandText = $"select * from {UserView} " +
|
c.CommandText = $"select * from {UserView} " +
|
||||||
"where guild_id = @Gid";
|
"where guild_id = @Gid";
|
||||||
c.Parameters.Add("@Gid", NpgsqlDbType.Bigint).Value = guildId;
|
c.Parameters.Add("@Gid", NpgsqlDbType.Bigint).Value = (long)guildId;
|
||||||
|
|
||||||
if (sID.HasValue)
|
if (sID.HasValue)
|
||||||
{
|
{
|
||||||
c.CommandText += " and user_id = @Uid";
|
c.CommandText += " and user_id = @Uid";
|
||||||
c.Parameters.Add("@Uid", NpgsqlDbType.Bigint).Value = sID.Value;
|
c.Parameters.Add("@Uid", NpgsqlDbType.Bigint).Value = (long)sID.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sName != null)
|
if (sName != null)
|
||||||
|
|
|
@ -149,15 +149,15 @@ namespace Kerobot.Services.GuildState
|
||||||
var tn = t.Name;
|
var tn = t.Name;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
object state;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
state = await mod.CreateGuildStateAsync(guildId, guildConf[tn]); // can be null
|
var state = await mod.CreateGuildStateAsync(guildId, guildConf[tn]); // can be null
|
||||||
|
newStates.Add(t, new StateInfo(state, jstrHash));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex) when (!(ex is ModuleLoadException))
|
||||||
{
|
{
|
||||||
Log("Encountered unhandled exception during guild state initialization:\n" +
|
Log("Unhandled exception while initializing guild state for module:\n" +
|
||||||
$"Module: {tn}\n" +
|
$"Module: {tn} | " +
|
||||||
$"Guild: {guildId} ({Kerobot.DiscordClient.GetGuild(guildId)?.Name ?? "unknown name"})\n" +
|
$"Guild: {guildId} ({Kerobot.DiscordClient.GetGuild(guildId)?.Name ?? "unknown name"})\n" +
|
||||||
$"```\n{ex.ToString()}\n```", true).Wait();
|
$"```\n{ex.ToString()}\n```", true).Wait();
|
||||||
Kerobot.GuildLogAsync(guildId, GuildLogSource,
|
Kerobot.GuildLogAsync(guildId, GuildLogSource,
|
||||||
|
@ -165,7 +165,6 @@ namespace Kerobot.Services.GuildState
|
||||||
"The bot owner has been notified.").Wait();
|
"The bot owner has been notified.").Wait();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
newStates.Add(t, new StateInfo(state, jstrHash));
|
|
||||||
}
|
}
|
||||||
catch (ModuleLoadException ex)
|
catch (ModuleLoadException ex)
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,10 +35,10 @@ namespace Kerobot.Services.Logging
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task DiscordClient_Log(LogMessage arg)
|
private async Task DiscordClient_Log(LogMessage arg)
|
||||||
{
|
{
|
||||||
var ts = DateTimeOffset.UtcNow;
|
bool important = arg.Severity != LogSeverity.Info;
|
||||||
bool important = arg.Severity > LogSeverity.Info;
|
|
||||||
string msg = $"[{Enum.GetName(typeof(LogSeverity), arg.Severity)}] {arg.Message}";
|
string msg = $"[{Enum.GetName(typeof(LogSeverity), arg.Severity)}] {arg.Message}";
|
||||||
const string logSource = "Discord.Net";
|
const string logSource = "Discord.Net";
|
||||||
|
if (arg.Exception != null) msg += "\n```\n" + arg.Exception.ToString() + "\n```";
|
||||||
|
|
||||||
if (important) await DoInstanceLogAsync(true, logSource, msg);
|
if (important) await DoInstanceLogAsync(true, logSource, msg);
|
||||||
else FormatToConsole(DateTimeOffset.UtcNow, logSource, msg);
|
else FormatToConsole(DateTimeOffset.UtcNow, logSource, msg);
|
||||||
|
@ -64,7 +64,7 @@ namespace Kerobot.Services.Logging
|
||||||
using (var c = db.CreateCommand())
|
using (var c = db.CreateCommand())
|
||||||
{
|
{
|
||||||
c.CommandText = "create index if not exists " +
|
c.CommandText = "create index if not exists " +
|
||||||
$"{TableLog}_guildid_idx on {TableLog} guild_id";
|
$"{TableLog}_guild_id_idx on {TableLog} (guild_id)";
|
||||||
await c.ExecuteNonQueryAsync();
|
await c.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,8 +78,8 @@ namespace Kerobot.Services.Logging
|
||||||
{
|
{
|
||||||
c.CommandText = $"insert into {TableLog} (guild_id, log_timestamp, log_source, message) values"
|
c.CommandText = $"insert into {TableLog} (guild_id, log_timestamp, log_source, message) values"
|
||||||
+ "(@Gid, @Ts, @Src, @Msg)";
|
+ "(@Gid, @Ts, @Src, @Msg)";
|
||||||
c.Parameters.Add("@Gid", NpgsqlDbType.Bigint).Value = guildId;
|
c.Parameters.Add("@Gid", NpgsqlDbType.Bigint).Value = (long)guildId;
|
||||||
c.Parameters.Add("@Ts", NpgsqlDbType.TimestampTZ).Value = timestamp;
|
c.Parameters.Add("@Ts", NpgsqlDbType.TimestampTz).Value = timestamp;
|
||||||
c.Parameters.Add("@Src", NpgsqlDbType.Text).Value = source;
|
c.Parameters.Add("@Src", NpgsqlDbType.Text).Value = source;
|
||||||
c.Parameters.Add("@Msg", NpgsqlDbType.Text).Value = message;
|
c.Parameters.Add("@Msg", NpgsqlDbType.Text).Value = message;
|
||||||
c.Prepare();
|
c.Prepare();
|
||||||
|
@ -126,6 +126,7 @@ namespace Kerobot.Services.Logging
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report to logging channel if necessary and possible
|
// Report to logging channel if necessary and possible
|
||||||
|
// TODO replace with webhook?
|
||||||
var (g, c) = Kerobot.Config.InstanceLogReportTarget;
|
var (g, c) = Kerobot.Config.InstanceLogReportTarget;
|
||||||
if ((insertException != null || report) &&
|
if ((insertException != null || report) &&
|
||||||
g != 0 && c != 0 && Kerobot.DiscordClient.ConnectionState == ConnectionState.Connected)
|
g != 0 && c != 0 && Kerobot.DiscordClient.ConnectionState == ConnectionState.Connected)
|
||||||
|
@ -142,7 +143,8 @@ namespace Kerobot.Services.Logging
|
||||||
{
|
{
|
||||||
Footer = new EmbedFooterBuilder() { Text = Name },
|
Footer = new EmbedFooterBuilder() { Text = Name },
|
||||||
Timestamp = DateTimeOffset.UtcNow,
|
Timestamp = DateTimeOffset.UtcNow,
|
||||||
Description = "Error during recording to instance log.\nCheck the console.",
|
Description = "Error during recording to instance log: `" +
|
||||||
|
insertException.Message + "`\nCheck the console.",
|
||||||
Color = Color.DarkRed
|
Color = Color.DarkRed
|
||||||
};
|
};
|
||||||
await ch.SendMessageAsync("", embed: e.Build());
|
await ch.SendMessageAsync("", embed: e.Build());
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace Kerobot.Modules.AutoResponder
|
||||||
public override Task<object> CreateGuildStateAsync(ulong guild, JToken config)
|
public override Task<object> CreateGuildStateAsync(ulong guild, JToken config)
|
||||||
{
|
{
|
||||||
// Guild state is a read-only IEnumerable<Definition>
|
// Guild state is a read-only IEnumerable<Definition>
|
||||||
if (config == null) return null;
|
if (config == null) return Task.FromResult<object>(null);
|
||||||
var guildDefs = new List<Definition>();
|
var guildDefs = new List<Definition>();
|
||||||
foreach (var defconf in config.Children<JProperty>())
|
foreach (var defconf in config.Children<JProperty>())
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
<Authors>Noikoio</Authors>
|
<Authors>Noiiko</Authors>
|
||||||
<Company>Noikoio</Company>
|
|
||||||
<Product>Kerobot</Product>
|
<Product>Kerobot</Product>
|
||||||
<Version>0.0.1</Version>
|
<Version>0.0.1</Version>
|
||||||
<Description>Essential functions for Kerobot which are available in the public bot instance.</Description>
|
<Description>Essential functions for Kerobot which are available in the public bot instance.</Description>
|
||||||
|
|
|
@ -18,8 +18,6 @@ namespace Kerobot.Modules.RegexModerator
|
||||||
class ConfDefinition
|
class ConfDefinition
|
||||||
{
|
{
|
||||||
public string Label { get; }
|
public string Label { get; }
|
||||||
readonly RegexModerator _module; // TODO is this needed?
|
|
||||||
readonly ulong _guild; // corresponding guild, for debug purposes. (is this needed?)
|
|
||||||
|
|
||||||
// Matching settings
|
// Matching settings
|
||||||
readonly IEnumerable<Regex> _regex;
|
readonly IEnumerable<Regex> _regex;
|
||||||
|
@ -40,10 +38,8 @@ namespace Kerobot.Modules.RegexModerator
|
||||||
public bool RemovalSendUserNotification; // send ban/kick notification to user?
|
public bool RemovalSendUserNotification; // send ban/kick notification to user?
|
||||||
public bool DeleteMessage { get; }
|
public bool DeleteMessage { get; }
|
||||||
|
|
||||||
public ConfDefinition(RegexModerator instance, JObject def, ulong guildId)
|
public ConfDefinition(JObject def)
|
||||||
{
|
{
|
||||||
_module = instance;
|
|
||||||
|
|
||||||
Label = def["Label"].Value<string>();
|
Label = def["Label"].Value<string>();
|
||||||
if (string.IsNullOrWhiteSpace(Label))
|
if (string.IsNullOrWhiteSpace(Label))
|
||||||
throw new ModuleLoadException("A rule does not have a label defined.");
|
throw new ModuleLoadException("A rule does not have a label defined.");
|
||||||
|
|
|
@ -23,8 +23,9 @@ namespace Kerobot.Modules.RegexModerator
|
||||||
if (config == null) return Task.FromResult<object>(null);
|
if (config == null) return Task.FromResult<object>(null);
|
||||||
var defs = new List<ConfDefinition>();
|
var defs = new List<ConfDefinition>();
|
||||||
|
|
||||||
|
// TODO better error reporting during this process
|
||||||
foreach (var def in config.Children<JObject>())
|
foreach (var def in config.Children<JObject>())
|
||||||
defs.Add(new ConfDefinition(this, def, guildID));
|
defs.Add(new ConfDefinition(def));
|
||||||
|
|
||||||
if (defs.Count == 0) return Task.FromResult<object>(null);
|
if (defs.Count == 0) return Task.FromResult<object>(null);
|
||||||
return Task.FromResult<object>(defs.AsReadOnly());
|
return Task.FromResult<object>(defs.AsReadOnly());
|
||||||
|
@ -49,19 +50,23 @@ namespace Kerobot.Modules.RegexModerator
|
||||||
|
|
||||||
// Send further processing to thread pool.
|
// Send further processing to thread pool.
|
||||||
// Match checking is a CPU-intensive task, thus very little checking is done here.
|
// 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);
|
var match = item.IsMatch(msg, isMod);
|
||||||
await Task.Run(async () => await ProcessMessage(item, msg, isMod));
|
msgProcessingTasks.Add(Task.Run(async () => await ProcessMessage(item, msg, isMod)));
|
||||||
}
|
}
|
||||||
|
await Task.WhenAll(msgProcessingTasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Does further message checking and response execution.
|
/// Does further message checking and response execution.
|
||||||
/// Invocations of this method are meant to be on the thread pool.
|
/// Invocations of this method are meant to be placed onto a thread separate from the caller.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task ProcessMessage(ConfDefinition def, SocketMessage msg, bool isMod)
|
private async Task ProcessMessage(ConfDefinition def, SocketMessage msg, bool isMod)
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,10 +37,10 @@ namespace Kerobot.Modules.AutoScriptResponder
|
||||||
await Task.WhenAll(tasks);
|
await Task.WhenAll(tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task<object> CreateGuildStateAsync(JToken config)
|
public override Task<object> CreateGuildStateAsync(ulong guild, JToken config)
|
||||||
{
|
{
|
||||||
// Guild state is a read-only IEnumerable<Definition>
|
// Guild state is a read-only IEnumerable<Definition>
|
||||||
if (config == null) return null;
|
if (config == null) return Task.FromResult<object>(null);
|
||||||
var guildDefs = new List<Definition>();
|
var guildDefs = new List<Definition>();
|
||||||
foreach (var defconf in config.Children<JProperty>())
|
foreach (var defconf in config.Children<JProperty>())
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace Kerobot.Modules.EntryRole
|
||||||
|
|
||||||
public override Task<object> CreateGuildStateAsync(ulong guildID, JToken config)
|
public override Task<object> CreateGuildStateAsync(ulong guildID, JToken config)
|
||||||
{
|
{
|
||||||
if (config == null) return null;
|
if (config == null) return Task.FromResult<object>(null);
|
||||||
|
|
||||||
if (config.Type != JTokenType.Object)
|
if (config.Type != JTokenType.Object)
|
||||||
throw new ModuleLoadException("Configuration is not properly defined.");
|
throw new ModuleLoadException("Configuration is not properly defined.");
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
<Authors>Noikoio</Authors>
|
<Authors>Noiiko</Authors>
|
||||||
<Product>Kerobot</Product>
|
<Product>Kerobot</Product>
|
||||||
<Version>0.0.1</Version>
|
<Version>0.0.1</Version>
|
||||||
<Description>Kerobot modules with more specific purposes that may not work well in a public instance, but are manageable in self-hosted bot instances.</Description>
|
<Description>Kerobot modules with more specific purposes that may not work well in a public instance, but are manageable in self-hosted bot instances.</Description>
|
||||||
|
|
Loading…
Reference in a new issue