diff --git a/Common/Utilities.cs b/Common/Utilities.cs
index 3c17d64..ee2a4fc 100644
--- a/Common/Utilities.cs
+++ b/Common/Utilities.cs
@@ -70,14 +70,7 @@ public static class Utilities {
/// Builds and returns an embed which displays this log entry.
///
public static Embed BuildEmbed(this Data.ModLogEntry entry, RegexbotClient bot) {
- string? issuedDisplay = null;
- try {
- var entityTry = new EntityName(entry.IssuedBy, EntityType.User);
- var issueq = bot.EcQueryUser(entityTry.Id!.Value.ToString());
- if (issueq != null) issuedDisplay = $"<@{issueq.UserId}> - {issueq.Username}#{issueq.Discriminator} `{issueq.UserId}`";
- else issuedDisplay = $"Unknown user with ID `{entityTry.Id!.Value}`";
- } catch (Exception) { }
- issuedDisplay ??= entry.IssuedBy;
+ 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}`";
@@ -107,4 +100,20 @@ public static class Utilities {
/// Returns a representation of this entity that can be parsed by the constructor.
///
public static string AsEntityNameString(this IUser entity) => $"@{entity.Id}::{entity.Username}";
+
+ ///
+ /// If given string is in an EntityName format, returns a displayable representation of it based on
+ /// a cache query. Otherwise, returns the input string as-is.
+ ///
+ [return: NotNullIfNotNull("input")]
+ public static string? TryFromEntityNameString(string? input, RegexbotClient bot) {
+ string? result = null;
+ try {
+ var entityTry = new EntityName(input!, EntityType.User);
+ var issueq = bot.EcQueryUser(entityTry.Id!.Value.ToString());
+ if (issueq != null) result = $"<@{issueq.UserId}> - {issueq.Username}#{issueq.Discriminator} `{issueq.UserId}`";
+ else result = $"Unknown user with ID `{entityTry.Id!.Value}`";
+ } catch (Exception) { }
+ return result ?? input;
+ }
}
diff --git a/Modules/ModCommands/Commands/ShowModLogs.cs b/Modules/ModCommands/Commands/ShowModLogs.cs
new file mode 100644
index 0000000..9837bb2
--- /dev/null
+++ b/Modules/ModCommands/Commands/ShowModLogs.cs
@@ -0,0 +1,82 @@
+using Discord;
+using Microsoft.EntityFrameworkCore;
+using RegexBot.Common;
+using RegexBot.Data;
+
+namespace RegexBot.Modules.ModCommands.Commands;
+class ShowModLogs : CommandConfig {
+ const int LogEntriesPerMessage = 10;
+ private readonly string _usage;
+
+ protected override string DefaultUsageMsg => _usage;
+
+ // No configuration.
+ // TODO bring in some options from BanKick. Particularly custom success msg.
+ // TODO when ModLogs fully implemented, add a reason?
+ public ShowModLogs(ModCommands module, JObject config) : base(module, config) {
+ _usage = $"{Command} `user or user ID` [page]\n"
+ + "Retrieves moderation log entries regarding the specified user.";
+ }
+
+ // Usage: (command) (query) [page]
+ public override async Task Invoke(SocketGuild g, SocketMessage msg) {
+ var line = msg.Content.Split(new char[] { ' ' }, 3, StringSplitOptions.RemoveEmptyEntries);
+ if (line.Length < 2) {
+ await SendUsageMessageAsync(msg.Channel, null);
+ return;
+ }
+ int pagenum;
+ if (line.Length == 3) {
+ const string PageNumError = ":x: Requested page must be a non-negative number.";
+ if (!int.TryParse(line[2], out pagenum)) {
+ await SendUsageMessageAsync(msg.Channel, PageNumError);
+ }
+ if (pagenum <= 0) await SendUsageMessageAsync(msg.Channel, PageNumError);
+ } else pagenum = 1;
+
+ var query = Module.Bot.EcQueryGuildUser(g.Id, line[1]);
+ if (query == null) {
+ await msg.Channel.SendMessageAsync(":x: Unable to find the given user.");
+ return;
+ }
+
+ int totalPages;
+ List results;
+ using (var db = new BotDatabaseContext()) {
+ var totalEntries = db.ModLogs
+ .Where(l => l.GuildId == query.GuildId && l.UserId == query.UserId)
+ .Count();
+ totalPages = (int)Math.Ceiling((double)totalEntries / LogEntriesPerMessage);
+ results = db.ModLogs
+ .Where(l => l.GuildId == query.GuildId && l.UserId == query.UserId)
+ .OrderByDescending(l => l.LogId)
+ .Skip((pagenum - 1) * LogEntriesPerMessage)
+ .Take(LogEntriesPerMessage)
+ .AsNoTracking()
+ .ToList();
+ }
+
+ var resultList = new EmbedBuilder() {
+ Author = new EmbedAuthorBuilder() {
+ Name = $"{query.User.Username}#{query.User.Discriminator}",
+ IconUrl = query.User.AvatarUrl
+ },
+ Footer = new EmbedFooterBuilder() {
+ Text = $"Page {pagenum} of {totalPages}",
+ IconUrl = Module.Bot.DiscordClient.CurrentUser.GetAvatarUrl()
+ },
+ Title = "Moderation logs"
+ };
+ foreach (var item in results) {
+ var f = new EmbedFieldBuilder() {
+ Name = $"{Enum.GetName(item.LogType)} \\#{item.LogId}",
+ Value = $"**Timestamp**: \n"
+ + $"**Issued by**: {Utilities.TryFromEntityNameString(item.IssuedBy, Module.Bot)}\n"
+ + $"**Message**: {item.Message ?? "*none specified*"}"
+ };
+ resultList.AddField(f);
+ }
+
+ await msg.Channel.SendMessageAsync(embed: resultList.Build());
+ }
+}
\ No newline at end of file
diff --git a/Modules/ModCommands/ModuleConfig.cs b/Modules/ModCommands/ModuleConfig.cs
index c30b0a8..9b7418e 100644
--- a/Modules/ModCommands/ModuleConfig.cs
+++ b/Modules/ModCommands/ModuleConfig.cs
@@ -41,7 +41,9 @@ class ModuleConfig {
{ "addrole", typeof(RoleAdd) },
{ "roleadd", typeof(RoleAdd) },
{ "delrole", typeof(RoleDel) },
- { "roledel", typeof(RoleDel) }
+ { "roledel", typeof(RoleDel) },
+ { "modlogs", typeof(ShowModLogs) },
+ { "showmodlogs", typeof(ShowModLogs) }
}
);