commit
fe72cd2cdb
21 changed files with 109 additions and 108 deletions
|
@ -66,36 +66,6 @@ public static class Utilities {
|
|||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds and returns an embed which displays this log entry.
|
||||
/// </summary>
|
||||
public static Embed BuildEmbed(this Data.ModLogEntry entry, RegexbotClient bot) {
|
||||
var issuedDisplay = TryFromEntityNameString(entry.IssuedBy, bot);
|
||||
string targetDisplay;
|
||||
var targetq = bot.EcQueryUser(entry.UserId.ToString());
|
||||
if (targetq != null) targetDisplay = $"<@{targetq.UserId}> - {targetq.Username}#{targetq.Discriminator} `{targetq.UserId}`";
|
||||
else targetDisplay = $"User with ID `{entry.UserId}`";
|
||||
|
||||
var logEmbed = new EmbedBuilder()
|
||||
.WithTitle(Enum.GetName(typeof(ModLogType), entry.LogType) + " logged:")
|
||||
.WithTimestamp(entry.Timestamp)
|
||||
.WithFooter($"Log #{entry.LogId}", bot.DiscordClient.CurrentUser.GetAvatarUrl()); // Escaping '#' not necessary here
|
||||
if (entry.Message != null) {
|
||||
logEmbed.Description = entry.Message;
|
||||
}
|
||||
|
||||
var contextStr = new StringBuilder();
|
||||
contextStr.AppendLine($"User: {targetDisplay}");
|
||||
contextStr.AppendLine($"Logged by: {issuedDisplay}");
|
||||
|
||||
logEmbed.AddField(new EmbedFieldBuilder() {
|
||||
Name = "Context",
|
||||
Value = contextStr.ToString()
|
||||
});
|
||||
|
||||
return logEmbed.Build();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a representation of this entity that can be parsed by the <seealso cref="EntityName"/> constructor.
|
||||
/// </summary>
|
||||
|
|
|
@ -12,7 +12,7 @@ internal class AutoResponder : RegexbotModule {
|
|||
DiscordClient.MessageReceived += DiscordClient_MessageReceived;
|
||||
}
|
||||
|
||||
public override Task<object?> CreateGuildStateAsync(ulong guildID, JToken config) {
|
||||
public override Task<object?> CreateGuildStateAsync(ulong guildID, JToken? config) {
|
||||
if (config == null) return Task.FromResult<object?>(null);
|
||||
var defs = new List<Definition>();
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ internal sealed class EntryRole : RegexbotModule, IDisposable {
|
|||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task<object?> CreateGuildStateAsync(ulong guildID, JToken config) {
|
||||
public override Task<object?> CreateGuildStateAsync(ulong guildID, JToken? config) {
|
||||
if (config == null) return Task.FromResult<object?>(null);
|
||||
|
||||
if (config.Type != JTokenType.Object)
|
||||
|
|
|
@ -65,10 +65,10 @@ abstract class NoteWarn : CommandConfig {
|
|||
var targetUser = g.GetUser(targetId);
|
||||
|
||||
// Go to specific action
|
||||
try {
|
||||
if (targetUser == null) {
|
||||
await msg.Channel.SendMessageAsync(":x: Unable to find the specified user.");
|
||||
} else {
|
||||
await ContinueInvoke(g, msg, logMessage, targetUser);
|
||||
} catch (Discord.Net.HttpException ex) when (ex.HttpCode == System.Net.HttpStatusCode.Forbidden) {
|
||||
await msg.Channel.SendMessageAsync(":x: " + Messages.ForbiddenGenericError);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ internal class ModCommands : RegexbotModule {
|
|||
}
|
||||
}
|
||||
|
||||
public override Task<object?> CreateGuildStateAsync(ulong guildID, JToken config) {
|
||||
public override Task<object?> CreateGuildStateAsync(ulong guildID, JToken? config) {
|
||||
if (config == null) return Task.FromResult<object?>(null);
|
||||
|
||||
var conf = new ModuleConfig(this, config);
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace RegexBot.Modules.ModLogs;
|
|||
[RegexbotModule]
|
||||
internal partial class ModLogs : RegexbotModule {
|
||||
// TODO consider resurrecting 2.x idea of logging actions to db, making it searchable?
|
||||
// TODO more robust channel filtering. define channels in config array, add check to it out here.
|
||||
|
||||
public ModLogs(RegexbotClient bot) : base(bot) {
|
||||
// TODO missing logging features: joins, leaves, user edits (nick/username/discr)
|
||||
|
@ -15,7 +16,7 @@ internal partial class ModLogs : RegexbotModule {
|
|||
bot.SharedEventReceived += HandleReceivedSharedEvent;
|
||||
}
|
||||
|
||||
public override Task<object?> CreateGuildStateAsync(ulong guildID, JToken config) {
|
||||
public override Task<object?> CreateGuildStateAsync(ulong guildID, JToken? config) {
|
||||
if (config == null) return Task.FromResult<object?>(null);
|
||||
if (config.Type != JTokenType.Object)
|
||||
throw new ModuleLoadException("Configuration for this section is invalid.");
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
using Discord;
|
||||
using RegexBot.Common;
|
||||
using RegexBot.Data;
|
||||
using System.Text;
|
||||
|
||||
namespace RegexBot.Modules.ModLogs;
|
||||
// Contains all logic relating to reporting new database mod log entries
|
||||
|
@ -12,6 +14,37 @@ internal partial class ModLogs {
|
|||
var reportChannel = conf?.ReportingChannel?.FindChannelIn(guild, true);
|
||||
if (reportChannel == null) return;
|
||||
|
||||
await reportChannel.SendMessageAsync(embed: entry.BuildEmbed(Bot));
|
||||
await reportChannel.SendMessageAsync(embed: BuildLogEmbed(entry));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds and returns an embed which displays this log entry.
|
||||
/// </summary>
|
||||
private Embed BuildLogEmbed(ModLogEntry entry) {
|
||||
var issuedDisplay = Utilities.TryFromEntityNameString(entry.IssuedBy, Bot);
|
||||
string targetDisplay;
|
||||
var targetq = Bot.EcQueryUser(entry.UserId.ToString());
|
||||
if (targetq != null) targetDisplay = $"<@{targetq.UserId}> - {targetq.Username}#{targetq.Discriminator} `{targetq.UserId}`";
|
||||
else targetDisplay = $"User with ID `{entry.UserId}`";
|
||||
|
||||
var logEmbed = new EmbedBuilder()
|
||||
.WithColor(Color.DarkGrey)
|
||||
.WithTitle(Enum.GetName(typeof(ModLogType), entry.LogType) + " logged:")
|
||||
.WithTimestamp(entry.Timestamp)
|
||||
.WithFooter($"Log #{entry.LogId}", Bot.DiscordClient.CurrentUser.GetAvatarUrl()); // Escaping '#' not necessary here
|
||||
if (entry.Message != null) {
|
||||
logEmbed.Description = entry.Message;
|
||||
}
|
||||
|
||||
var contextStr = new StringBuilder();
|
||||
contextStr.AppendLine($"User: {targetDisplay}");
|
||||
contextStr.AppendLine($"Logged by: {issuedDisplay}");
|
||||
|
||||
logEmbed.AddField(new EmbedFieldBuilder() {
|
||||
Name = "Context",
|
||||
Value = contextStr.ToString()
|
||||
});
|
||||
|
||||
return logEmbed.Build();
|
||||
}
|
||||
}
|
|
@ -29,9 +29,10 @@ internal partial class ModLogs {
|
|||
.SingleOrDefault();
|
||||
|
||||
var reportEmbed = new EmbedBuilder()
|
||||
.WithColor(Color.Red)
|
||||
.WithTitle("Message deleted")
|
||||
.WithCurrentTimestamp()
|
||||
.WithFooter($"User ID: {(cachedMsg == null ? "Unknown" : cachedMsg.AuthorId)}");
|
||||
.WithFooter($"Message ID: {argMsg.Id}");
|
||||
|
||||
if (cachedMsg != null) {
|
||||
if (cachedMsg.Content == null) {
|
||||
|
@ -60,7 +61,7 @@ internal partial class ModLogs {
|
|||
|
||||
var editLine = $"Posted: {MakeTimestamp(SnowflakeUtils.FromSnowflake(argMsg.Id))}";
|
||||
if (cachedMsg?.EditedAt != null) editLine += $"\nLast edit: {MakeTimestamp(cachedMsg.EditedAt.Value)}";
|
||||
SetContextField(reportEmbed, (ulong?)cachedMsg?.AuthorId, channel, editLine, argMsg.Id);
|
||||
SetContextField(reportEmbed, (ulong?)cachedMsg?.AuthorId, channel, editLine);
|
||||
|
||||
await reportChannel.SendMessageAsync(embed: reportEmbed.Build());
|
||||
}
|
||||
|
@ -78,9 +79,10 @@ internal partial class ModLogs {
|
|||
}
|
||||
|
||||
var reportEmbed = new EmbedBuilder()
|
||||
.WithColor(new Color(0xffff00)) // yellow
|
||||
.WithTitle("Message edited")
|
||||
.WithCurrentTimestamp()
|
||||
.WithFooter($"User ID: {newMsg.Author.Id}");
|
||||
.WithFooter($"Message ID: {newMsg.Id}");
|
||||
|
||||
reportEmbed.Author = new EmbedAuthorBuilder() {
|
||||
Name = $"{newMsg.Author.Username}#{newMsg.Author.Discriminator}",
|
||||
|
@ -119,12 +121,12 @@ internal partial class ModLogs {
|
|||
string editLine;
|
||||
if ((oldMsg?.EditedAt) == null) editLine = $"Posted: {MakeTimestamp(SnowflakeUtils.FromSnowflake(newMsg.Id))}";
|
||||
else editLine = $"Previous edit: {MakeTimestamp(oldMsg.EditedAt.Value)}";
|
||||
SetContextField(reportEmbed, newMsg.Author.Id, channel, editLine, newMsg.Id);
|
||||
SetContextField(reportEmbed, newMsg.Author.Id, channel, editLine);
|
||||
|
||||
await reportChannel.SendMessageAsync(embed: reportEmbed.Build());
|
||||
}
|
||||
|
||||
private void SetContextField(EmbedBuilder e, ulong? userId, SocketTextChannel channel, string editLine, ulong msgId) {
|
||||
private void SetContextField(EmbedBuilder e, ulong? userId, SocketTextChannel channel, string editLine) {
|
||||
string userDisplay;
|
||||
if (userId.HasValue) {
|
||||
var q = Bot.EcQueryUser(userId.Value.ToString());
|
||||
|
@ -138,7 +140,6 @@ internal partial class ModLogs {
|
|||
contextStr.AppendLine($"User: {userDisplay}");
|
||||
contextStr.AppendLine($"Channel: <#{channel.Id}> (#{channel.Name})");
|
||||
contextStr.AppendLine(editLine);
|
||||
contextStr.AppendLine($"Message ID: {msgId}");
|
||||
|
||||
e.AddField(new EmbedFieldBuilder() {
|
||||
Name = "Context",
|
||||
|
|
|
@ -41,7 +41,7 @@ internal class PendingOutRole : RegexbotModule {
|
|||
}
|
||||
}
|
||||
|
||||
public override Task<object?> CreateGuildStateAsync(ulong guildID, JToken config) {
|
||||
public override Task<object?> CreateGuildStateAsync(ulong guildID, JToken? config) {
|
||||
if (config == null) return Task.FromResult<object?>(null);
|
||||
if (config.Type != JTokenType.Object)
|
||||
throw new ModuleLoadException("Configuration for this section is invalid.");
|
||||
|
|
|
@ -12,7 +12,7 @@ internal class RegexModerator : RegexbotModule {
|
|||
DiscordClient.MessageUpdated += DiscordClient_MessageUpdated;
|
||||
}
|
||||
|
||||
public override Task<object?> CreateGuildStateAsync(ulong guildID, JToken config) {
|
||||
public override Task<object?> CreateGuildStateAsync(ulong guildID, JToken? config) {
|
||||
if (config == null) return Task.FromResult<object?>(null);
|
||||
var defs = new List<ConfDefinition>();
|
||||
|
||||
|
|
|
@ -135,11 +135,11 @@ class ResponseExecutor {
|
|||
#region Response delegates
|
||||
private static Task<ResponseResult> CmdComment(string? parameter) => Task.FromResult(FromSuccess(parameter));
|
||||
|
||||
private Task<ResponseResult> CmdBan(string? parameter) => CmdBanKick(RemovalType.Ban, parameter);
|
||||
private Task<ResponseResult> CmdKick(string? parameter) => CmdBanKick(RemovalType.Kick, parameter);
|
||||
private async Task<ResponseResult> CmdBanKick(RemovalType rt, string? parameter) {
|
||||
private Task<ResponseResult> CmdBan(string? parameter) => CmdBanKick(true, parameter);
|
||||
private Task<ResponseResult> CmdKick(string? parameter) => CmdBanKick(false, parameter);
|
||||
private async Task<ResponseResult> CmdBanKick(bool isBan, string? parameter) {
|
||||
BanKickResult result;
|
||||
if (rt == RemovalType.Ban) {
|
||||
if (isBan) {
|
||||
result = await _bot.BanAsync(_guild, LogSource, _user.Id,
|
||||
_rule.BanPurgeDays, parameter, _rule.NotifyUser);
|
||||
} else {
|
||||
|
|
|
@ -43,7 +43,7 @@ internal class VoiceRoleSync : RegexbotModule {
|
|||
}
|
||||
}
|
||||
|
||||
public override Task<object?> CreateGuildStateAsync(ulong guildID, JToken config) {
|
||||
public override Task<object?> CreateGuildStateAsync(ulong guildID, JToken? config) {
|
||||
if (config == null) return Task.FromResult<object?>(null);
|
||||
if (config.Type != JTokenType.Object)
|
||||
throw new ModuleLoadException("Configuration for this section is invalid.");
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Authors>NoiTheCat</Authors>
|
||||
<Description>Advanced and flexible Discord moderation bot.</Description>
|
||||
<Version>3.1.0</Version>
|
||||
<Version>3.1.1</Version>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||
|
@ -29,7 +29,7 @@
|
|||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.7" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
||||
<PackageReference Include="Npgsql" Version="6.0.7" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.7" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.Design" Version="1.1.0" />
|
||||
|
|
|
@ -43,7 +43,7 @@ public abstract class RegexbotModule {
|
|||
/// <returns>
|
||||
/// An object instance containing state and/or configuration information for the guild currently being processed.
|
||||
/// </returns>
|
||||
public abstract Task<object?> CreateGuildStateAsync(ulong guildID, JToken config);
|
||||
public abstract Task<object?> CreateGuildStateAsync(ulong guildID, JToken? config);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the state object that corresponds with the given guild.
|
||||
|
|
|
@ -7,7 +7,6 @@ namespace RegexBot;
|
|||
/// </summary>
|
||||
public class BanKickResult {
|
||||
private readonly bool _userNotFound; // possible to receive this error by means other than exception
|
||||
private readonly RemovalType _rptRemovalType;
|
||||
private readonly ulong _rptTargetId;
|
||||
|
||||
/// <summary>
|
||||
|
@ -59,12 +58,22 @@ public class BanKickResult {
|
|||
/// </value>
|
||||
public bool MessageSendSuccess { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating if this result represents a ban.
|
||||
/// </summary>
|
||||
public bool IsBan { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating if this result represents a kick.
|
||||
/// </summary>
|
||||
public bool IsKick { get => !IsBan; }
|
||||
|
||||
internal BanKickResult(HttpException? error, bool notificationSuccess, bool errorNotFound,
|
||||
RemovalType rtype, ulong rtarget) {
|
||||
bool isBan, ulong rtarget) {
|
||||
OperationError = error;
|
||||
MessageSendSuccess = notificationSuccess;
|
||||
_userNotFound = errorNotFound;
|
||||
_rptRemovalType = rtype;
|
||||
IsBan = isBan;
|
||||
_rptTargetId = rtarget;
|
||||
}
|
||||
|
||||
|
@ -78,14 +87,12 @@ public class BanKickResult {
|
|||
if (OperationSuccess) msg = ":white_check_mark: ";
|
||||
else msg = ":x: Failed to ";
|
||||
|
||||
if (_rptRemovalType == RemovalType.Ban) {
|
||||
if (IsBan) {
|
||||
if (OperationSuccess) msg += "Banned";
|
||||
else msg += "ban";
|
||||
} else if (_rptRemovalType == RemovalType.Kick) {
|
||||
} else {
|
||||
if (OperationSuccess) msg += "Kicked";
|
||||
else msg += "kick";
|
||||
} else {
|
||||
throw new InvalidOperationException("Cannot create a message for removal type of None.");
|
||||
}
|
||||
|
||||
if (_rptTargetId != 0) {
|
||||
|
|
|
@ -18,7 +18,7 @@ partial class RegexbotClient {
|
|||
int purgeDays,
|
||||
string? reason,
|
||||
bool sendDMToTarget)
|
||||
=> _svcCommonFunctions.BanOrKickAsync(RemovalType.Ban, guild, source, targetUser, purgeDays, reason, sendDMToTarget);
|
||||
=> _svcCommonFunctions.BanOrKickAsync(true, guild, source, targetUser, purgeDays, reason, sendDMToTarget);
|
||||
|
||||
/// <summary>
|
||||
/// Similar to <see cref="BanAsync(SocketGuild, string, ulong, int, string, bool)"/>, but making use of an
|
||||
|
@ -37,7 +37,7 @@ partial class RegexbotClient {
|
|||
string? reason,
|
||||
bool sendDMToTarget) {
|
||||
var result = EcQueryGuildUser(guild.Id, targetSearch);
|
||||
if (result == null) return new BanKickResult(null, false, true, RemovalType.Ban, 0);
|
||||
if (result == null) return new BanKickResult(null, false, true, true, 0);
|
||||
return await BanAsync(guild, source, (ulong)result.UserId, purgeDays, reason, sendDMToTarget);
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ partial class RegexbotClient {
|
|||
ulong targetUser,
|
||||
string? reason,
|
||||
bool sendDMToTarget)
|
||||
=> _svcCommonFunctions.BanOrKickAsync(RemovalType.Kick, guild, source, targetUser, default, reason, sendDMToTarget);
|
||||
=> _svcCommonFunctions.BanOrKickAsync(false, guild, source, targetUser, default, reason, sendDMToTarget);
|
||||
|
||||
/// <summary>
|
||||
/// Similar to <see cref="KickAsync(SocketGuild, string, ulong, string, bool)"/>, but making use of an
|
||||
|
@ -80,7 +80,7 @@ partial class RegexbotClient {
|
|||
string? reason,
|
||||
bool sendDMToTarget) {
|
||||
var result = EcQueryGuildUser(guild.Id, targetSearch);
|
||||
if (result == null) return new BanKickResult(null, false, true, RemovalType.Kick, 0);
|
||||
if (result == null) return new BanKickResult(null, false, true, false, 0);
|
||||
return await KickAsync(guild, source, (ulong)result.UserId, reason, sendDMToTarget);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,42 +4,41 @@ using Discord.Net;
|
|||
namespace RegexBot.Services.CommonFunctions;
|
||||
internal partial class CommonFunctionsService : Service {
|
||||
// Hooked (indirectly)
|
||||
internal async Task<BanKickResult> BanOrKickAsync(RemovalType t, SocketGuild guild, string source, ulong target,
|
||||
internal async Task<BanKickResult> BanOrKickAsync(bool isBan, SocketGuild guild, string source, ulong target,
|
||||
int banPurgeDays, string? logReason, bool sendDmToTarget) {
|
||||
if (t == RemovalType.None) throw new ArgumentException("Removal type must be 'ban' or 'kick'.");
|
||||
var dmSuccess = true;
|
||||
|
||||
SocketGuildUser utarget = guild.GetUser(target);
|
||||
// Can't kick without obtaining user object. Quit here.
|
||||
if (t == RemovalType.Kick && utarget == null) return new BanKickResult(null, false, true, RemovalType.Kick, 0);
|
||||
if (isBan == false && utarget == null) return new BanKickResult(null, false, true, false, 0);
|
||||
|
||||
// Send DM notification
|
||||
// Must be done before removal, or we risk not being able to send a notification afterwards
|
||||
if (sendDmToTarget) {
|
||||
if (utarget != null) dmSuccess = await BanKickSendNotificationAsync(utarget, t, logReason);
|
||||
if (utarget != null) dmSuccess = await BanKickSendNotificationAsync(utarget, isBan, logReason);
|
||||
else dmSuccess = false;
|
||||
}
|
||||
|
||||
// Perform the action
|
||||
var auditReason = $"(By: {source}) {logReason}";
|
||||
try {
|
||||
if (t == RemovalType.Ban) await guild.AddBanAsync(target, banPurgeDays, auditReason);
|
||||
if (isBan) await guild.AddBanAsync(target, banPurgeDays, auditReason);
|
||||
else await utarget!.KickAsync(auditReason);
|
||||
} catch (HttpException ex) {
|
||||
return new BanKickResult(ex, dmSuccess, false, t, target);
|
||||
return new BanKickResult(ex, dmSuccess, false, isBan, target);
|
||||
}
|
||||
ModLogsProcessRemoval(guild.Id, target, t == RemovalType.Ban ? ModLogType.Ban : ModLogType.Kick, source, logReason);
|
||||
ModLogsProcessRemoval(guild.Id, target, isBan ? ModLogType.Ban : ModLogType.Kick, source, logReason);
|
||||
|
||||
return new BanKickResult(null, dmSuccess, false, t, target);
|
||||
return new BanKickResult(null, dmSuccess, false, isBan, target);
|
||||
}
|
||||
|
||||
private async Task<bool> BanKickSendNotificationAsync(SocketGuildUser target, RemovalType action, string? reason) {
|
||||
private async Task<bool> BanKickSendNotificationAsync(SocketGuildUser target, bool isBan, string? reason) {
|
||||
const string DMTemplate = "You have been {0} from {1}";
|
||||
const string DMTemplateReason = " for the following reason:\n{2}";
|
||||
|
||||
var outMessage = string.IsNullOrWhiteSpace(reason)
|
||||
? string.Format(DMTemplate + ".", action == RemovalType.Ban ? "banned" : "kicked", target.Guild.Name)
|
||||
: string.Format(DMTemplate + DMTemplateReason, action == RemovalType.Ban ? "banned" : "kicked", target.Guild.Name, reason);
|
||||
? string.Format(DMTemplate + ".", isBan ? "banned" : "kicked", target.Guild.Name)
|
||||
: string.Format(DMTemplate + DMTemplateReason, isBan ? "banned" : "kicked", target.Guild.Name, reason);
|
||||
|
||||
var dch = await target.CreateDMChannelAsync();
|
||||
try { await dch.SendMessageAsync(outMessage); } catch (HttpException) { return false; }
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
namespace RegexBot;
|
||||
/// <summary>
|
||||
/// Specifies possible outcomes for the removal of a user from a guild.
|
||||
/// </summary>
|
||||
// Despite specific to CommonFunctionsService, this enum is meant to be visible by modules too,
|
||||
// thus it is placed within the root namespace.
|
||||
// TODO Tends to be unused except internally. Look into removing.
|
||||
public enum RemovalType {
|
||||
/// <summary>
|
||||
/// Default value. Not used in any actual circumstances.
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// Specifies that the type of removal includes placing the user on the guild's ban list.
|
||||
/// </summary>
|
||||
Ban,
|
||||
/// <summary>
|
||||
/// Specifies that the user is removed from the server via kick.
|
||||
/// </summary>
|
||||
Kick
|
||||
}
|
|
@ -21,7 +21,11 @@ class MessageCachingSubservice {
|
|||
}
|
||||
|
||||
private async Task AddOrUpdateCacheItemAsync(SocketMessage arg, bool isUpdate) {
|
||||
if (!Common.Utilities.IsValidUserMessage(arg, out _)) return;
|
||||
//if (!Common.Utilities.IsValidUserMessage(arg, out _)) return;
|
||||
if (arg.Channel is not SocketTextChannel) return;
|
||||
if (arg.Author.IsWebhook) return; // do get bot messages, don't get webhooks
|
||||
if (((IMessage)arg).Type != MessageType.Default) return;
|
||||
if (arg is SocketSystemMessage) return;
|
||||
|
||||
using var db = new BotDatabaseContext();
|
||||
CachedGuildMessage? cachedMsg = db.GuildMessageCache.Where(m => m.MessageId == (long)arg.Id).SingleOrDefault();
|
||||
|
|
|
@ -18,15 +18,22 @@ class UserCachingSubservice {
|
|||
bot.DiscordClient.GuildMemberUpdated += DiscordClient_GuildMemberUpdated;
|
||||
bot.DiscordClient.UserUpdated += DiscordClient_UserUpdated;
|
||||
}
|
||||
private async Task DiscordClient_GuildMembersDownloaded(SocketGuild arg) {
|
||||
_log($"{arg.Name}: Full member list obtained. Cache update in progress.");
|
||||
using var db = new BotDatabaseContext();
|
||||
foreach (var user in arg.Users) {
|
||||
UpdateUser(user, db);
|
||||
UpdateGuildUser(user, db);
|
||||
}
|
||||
var changes = await db.SaveChangesAsync();
|
||||
_log($"{arg.Name}: Member caches updated ({changes} database writes).");
|
||||
private Task DiscordClient_GuildMembersDownloaded(SocketGuild arg) {
|
||||
var userlist = arg.Users.ToList();
|
||||
_ = Task.Run(async () => {
|
||||
try {
|
||||
using var db = new BotDatabaseContext();
|
||||
foreach (var user in userlist) {
|
||||
UpdateUser(user, db);
|
||||
UpdateGuildUser(user, db);
|
||||
}
|
||||
var changes = await db.SaveChangesAsync();
|
||||
_log($"{arg.Name}: Member caches updated ({changes} database writes).");
|
||||
} catch (Exception ex) {
|
||||
_log($"{arg.Name}: {ex}");
|
||||
}
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task DiscordClient_GuildMemberUpdated(Discord.Cacheable<SocketGuildUser, ulong> old, SocketGuildUser current) {
|
||||
|
|
|
@ -76,7 +76,7 @@ class ModuleStateService : Service {
|
|||
foreach (var module in BotClient.Modules) {
|
||||
var t = module.GetType();
|
||||
try {
|
||||
var state = await module.CreateGuildStateAsync(guild.Id, guildConf[module.Name]!);
|
||||
var state = await module.CreateGuildStateAsync(guild.Id, guildConf[module.Name]);
|
||||
newStates.Add(t, state);
|
||||
} catch (ModuleLoadException ex) {
|
||||
Log($"{module.Name} failed to read configuration for {guild.Name}: {ex.Message}");
|
||||
|
|
Loading…
Reference in a new issue