mirror of
https://github.com/PluralKit/PluralKit.git
synced 2026-02-04 04:56:49 +00:00
feat(bot): lookup command messages
This commit is contained in:
parent
301bf25d44
commit
539fc82342
6 changed files with 120 additions and 37 deletions
|
|
@ -33,7 +33,10 @@ public class ApplicationCommandProxiedMessage
|
||||||
var messageId = ctx.Event.Data!.TargetId!.Value;
|
var messageId = ctx.Event.Data!.TargetId!.Value;
|
||||||
var msg = await ctx.Repository.GetFullMessage(messageId);
|
var msg = await ctx.Repository.GetFullMessage(messageId);
|
||||||
if (msg == null)
|
if (msg == null)
|
||||||
throw Errors.MessageNotFound(messageId);
|
{
|
||||||
|
await QueryCommandMessage(ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var showContent = true;
|
var showContent = true;
|
||||||
var channel = await _rest.GetChannelOrNull(msg.Message.Channel);
|
var channel = await _rest.GetChannelOrNull(msg.Message.Channel);
|
||||||
|
|
@ -58,6 +61,20 @@ public class ApplicationCommandProxiedMessage
|
||||||
await ctx.Reply(embeds: embeds.ToArray());
|
await ctx.Reply(embeds: embeds.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task QueryCommandMessage(InteractionContext ctx)
|
||||||
|
{
|
||||||
|
var messageId = ctx.Event.Data!.TargetId!.Value;
|
||||||
|
var msg = await ctx.Repository.GetCommandMessage(messageId);
|
||||||
|
if (msg == null)
|
||||||
|
throw Errors.MessageNotFound(messageId);
|
||||||
|
|
||||||
|
var embeds = new List<Embed>();
|
||||||
|
|
||||||
|
embeds.Add(await _embeds.CreateCommandMessageInfoEmbed(msg, true));
|
||||||
|
|
||||||
|
await ctx.Reply(embeds: embeds.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
public async Task DeleteMessage(InteractionContext ctx)
|
public async Task DeleteMessage(InteractionContext ctx)
|
||||||
{
|
{
|
||||||
var messageId = ctx.Event.Data!.TargetId!.Value;
|
var messageId = ctx.Event.Data!.TargetId!.Value;
|
||||||
|
|
|
||||||
|
|
@ -101,12 +101,17 @@ public class Context
|
||||||
AllowedMentions = mentions ?? new AllowedMentions()
|
AllowedMentions = mentions ?? new AllowedMentions()
|
||||||
});
|
});
|
||||||
|
|
||||||
// if (embed != null)
|
// store log of sent message, so it can be queried or deleted later
|
||||||
// {
|
// skip DMs as DM messages can always be deleted
|
||||||
// Sensitive information that might want to be deleted by :x: reaction is typically in an embed format (member cards, for example)
|
if (Guild != null)
|
||||||
// but since we can, we just store all sent messages for possible deletion
|
await Repository.AddCommandMessage(new Core.CommandMessage
|
||||||
await _commandMessageService.RegisterMessage(msg.Id, Guild?.Id ?? 0, msg.ChannelId, Author.Id);
|
{
|
||||||
// }
|
Mid = msg.Id,
|
||||||
|
Guild = Guild!.Id,
|
||||||
|
Channel = Channel.Id,
|
||||||
|
Sender = Author.Id,
|
||||||
|
OriginalMid = Message.Id,
|
||||||
|
});
|
||||||
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -347,13 +347,8 @@ public class ProxiedMessage
|
||||||
var message = await ctx.Repository.GetFullMessage(messageId.Value);
|
var message = await ctx.Repository.GetFullMessage(messageId.Value);
|
||||||
if (message == null)
|
if (message == null)
|
||||||
{
|
{
|
||||||
if (isDelete)
|
await GetCommandMessage(ctx, messageId.Value, isDelete);
|
||||||
{
|
return;
|
||||||
await DeleteCommandMessage(ctx, messageId.Value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw Errors.MessageNotFound(messageId.Value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var showContent = true;
|
var showContent = true;
|
||||||
|
|
@ -448,20 +443,35 @@ public class ProxiedMessage
|
||||||
await ctx.Reply(embed: await _embeds.CreateMessageInfoEmbed(message, showContent, ctx.Config));
|
await ctx.Reply(embed: await _embeds.CreateMessageInfoEmbed(message, showContent, ctx.Config));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DeleteCommandMessage(Context ctx, ulong messageId)
|
private async Task GetCommandMessage(Context ctx, ulong messageId, bool isDelete)
|
||||||
{
|
{
|
||||||
var cmessage = await ctx.Services.Resolve<CommandMessageService>().GetCommandMessage(messageId);
|
var msg = await _repo.GetCommandMessage(messageId);
|
||||||
if (cmessage == null)
|
if (msg == null)
|
||||||
throw Errors.MessageNotFound(messageId);
|
throw Errors.MessageNotFound(messageId);
|
||||||
|
|
||||||
if (cmessage!.AuthorId != ctx.Author.Id)
|
if (isDelete)
|
||||||
throw new PKError("You can only delete command messages queried by this account.");
|
{
|
||||||
|
if (msg.Sender != ctx.Author.Id)
|
||||||
|
throw new PKError("You can only delete command messages queried by this account.");
|
||||||
|
|
||||||
await ctx.Rest.DeleteMessage(cmessage.ChannelId, messageId);
|
await ctx.Rest.DeleteMessage(msg.Channel, messageId);
|
||||||
|
|
||||||
if (ctx.Guild != null)
|
if (ctx.Guild != null)
|
||||||
await ctx.Rest.DeleteMessage(ctx.Message);
|
await ctx.Rest.DeleteMessage(ctx.Message);
|
||||||
else
|
else
|
||||||
await ctx.Rest.CreateReaction(ctx.Message.ChannelId, ctx.Message.Id, new Emoji { Name = Emojis.Success });
|
await ctx.Rest.CreateReaction(ctx.Message.ChannelId, ctx.Message.Id, new Emoji { Name = Emojis.Success });
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var showContent = true;
|
||||||
|
|
||||||
|
var channel = await _rest.GetChannelOrNull(msg.Channel);
|
||||||
|
if (channel == null)
|
||||||
|
showContent = false;
|
||||||
|
else if (!await ctx.CheckPermissionsInGuildChannel(channel, PermissionSet.ViewChannel))
|
||||||
|
showContent = false;
|
||||||
|
|
||||||
|
await ctx.Reply(embed: await _embeds.CreateCommandMessageInfoEmbed(msg, showContent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -9,29 +9,23 @@ namespace PluralKit.Bot;
|
||||||
public class CommandMessageService
|
public class CommandMessageService
|
||||||
{
|
{
|
||||||
private readonly RedisService _redis;
|
private readonly RedisService _redis;
|
||||||
|
private readonly ModelRepository _repo;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private static readonly TimeSpan CommandMessageRetention = TimeSpan.FromHours(24);
|
private static readonly TimeSpan CommandMessageRetention = TimeSpan.FromHours(24);
|
||||||
|
|
||||||
public CommandMessageService(RedisService redis, IClock clock, ILogger logger)
|
public CommandMessageService(RedisService redis, ModelRepository repo, IClock clock, ILogger logger)
|
||||||
{
|
{
|
||||||
_redis = redis;
|
_redis = redis;
|
||||||
|
_repo = repo;
|
||||||
_logger = logger.ForContext<CommandMessageService>();
|
_logger = logger.ForContext<CommandMessageService>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RegisterMessage(ulong messageId, ulong guildId, ulong channelId, ulong authorId)
|
|
||||||
{
|
|
||||||
if (_redis.Connection == null) return;
|
|
||||||
|
|
||||||
_logger.Debug(
|
|
||||||
"Registering command response {MessageId} from author {AuthorId} in {ChannelId}",
|
|
||||||
messageId, authorId, channelId
|
|
||||||
);
|
|
||||||
|
|
||||||
await _redis.Connection.GetDatabase().StringSetAsync("command_message:" + messageId.ToString(), $"{authorId}-{channelId}-{guildId}", expiry: CommandMessageRetention);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<CommandMessage?> GetCommandMessage(ulong messageId)
|
public async Task<CommandMessage?> GetCommandMessage(ulong messageId)
|
||||||
{
|
{
|
||||||
|
var repoMsg = await _repo.GetCommandMessage(messageId);
|
||||||
|
if (repoMsg != null)
|
||||||
|
return new CommandMessage(repoMsg.Sender, repoMsg.Channel, repoMsg.Guild);
|
||||||
|
|
||||||
var str = await _redis.Connection.GetDatabase().StringGetAsync(messageId.ToString());
|
var str = await _redis.Connection.GetDatabase().StringGetAsync(messageId.ToString());
|
||||||
if (str.HasValue)
|
if (str.HasValue)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -420,6 +420,24 @@ public class EmbedService
|
||||||
return eb.Build();
|
return eb.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<Embed> CreateCommandMessageInfoEmbed(Core.CommandMessage msg, bool showContent)
|
||||||
|
{
|
||||||
|
var content = "*(command message deleted or inaccessible)*";
|
||||||
|
if (showContent)
|
||||||
|
{
|
||||||
|
var discordMessage = await _rest.GetMessageOrNull(msg.Channel, msg.OriginalMid);
|
||||||
|
if (discordMessage != null)
|
||||||
|
content = discordMessage.Content;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new EmbedBuilder()
|
||||||
|
.Title("Command response message")
|
||||||
|
.Description(content)
|
||||||
|
.Field(new("Original message", $"https://discord.com/channels/{msg.Guild}/{msg.Channel}/{msg.OriginalMid}", true))
|
||||||
|
.Field(new("Sent by", $"<@{msg.Sender}>", true))
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
public Task<Embed> CreateFrontPercentEmbed(FrontBreakdown breakdown, PKSystem system, PKGroup group,
|
public Task<Embed> CreateFrontPercentEmbed(FrontBreakdown breakdown, PKSystem system, PKGroup group,
|
||||||
DateTimeZone tz, LookupContext ctx, string embedTitle,
|
DateTimeZone tz, LookupContext ctx, string embedTitle,
|
||||||
bool ignoreNoFronters, bool showFlat)
|
bool ignoreNoFronters, bool showFlat)
|
||||||
|
|
|
||||||
|
|
@ -42,12 +42,37 @@ public partial class ModelRepository
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task AddCommandMessage(CommandMessage msg)
|
||||||
|
{
|
||||||
|
var query = new Query("command_messages").AsInsert(new
|
||||||
|
{
|
||||||
|
mid = msg.Mid,
|
||||||
|
guild = msg.Guild,
|
||||||
|
channel = msg.Channel,
|
||||||
|
sender = msg.Sender,
|
||||||
|
original_mid = msg.OriginalMid
|
||||||
|
});
|
||||||
|
await _db.ExecuteQuery(query, messages: true);
|
||||||
|
|
||||||
|
_logger.Debug("Stored command message {@StoredMessage} in channel {Channel}", msg, msg.Channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<CommandMessage?> GetCommandMessage(ulong id)
|
||||||
|
=> _db.QueryFirst<CommandMessage?>(new Query("command_messages").Where("mid", id), messages: true);
|
||||||
|
|
||||||
public async Task DeleteMessage(ulong id)
|
public async Task DeleteMessage(ulong id)
|
||||||
{
|
{
|
||||||
var query = new Query("messages").AsDelete().Where("mid", id);
|
var query = new Query("messages").AsDelete().Where("mid", id);
|
||||||
var rowCount = await _db.ExecuteQuery(query, messages: true);
|
var rowCount = await _db.ExecuteQuery(query, messages: true);
|
||||||
if (rowCount > 0)
|
if (rowCount > 0)
|
||||||
_logger.Information("Deleted message {MessageId} from database", id);
|
_logger.Information("Deleted message {MessageId} from database", id);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var cquery = new Query("command_messages").AsDelete().Where("mid", id);
|
||||||
|
var crowCount = await _db.ExecuteQuery(query, messages: true);
|
||||||
|
if (crowCount > 0)
|
||||||
|
_logger.Information("Deleted command message {MessageId} from database", id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteMessagesBulk(IReadOnlyCollection<ulong> ids)
|
public async Task DeleteMessagesBulk(IReadOnlyCollection<ulong> ids)
|
||||||
|
|
@ -59,5 +84,19 @@ public partial class ModelRepository
|
||||||
if (rowCount > 0)
|
if (rowCount > 0)
|
||||||
_logger.Information("Bulk deleted messages ({FoundCount} found) from database: {MessageIds}", rowCount,
|
_logger.Information("Bulk deleted messages ({FoundCount} found) from database: {MessageIds}", rowCount,
|
||||||
ids);
|
ids);
|
||||||
|
var cquery = new Query("command_messages").AsDelete().WhereIn("mid", ids.Select(id => (long)id).ToArray());
|
||||||
|
var crowCount = await _db.ExecuteQuery(query, messages: true);
|
||||||
|
if (crowCount > 0)
|
||||||
|
_logger.Information("Bulk deleted command messages ({FoundCount} found) from database: {MessageIds}", rowCount,
|
||||||
|
ids);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CommandMessage
|
||||||
|
{
|
||||||
|
public ulong Mid { get; set; }
|
||||||
|
public ulong Guild { get; set; }
|
||||||
|
public ulong Channel { get; set; }
|
||||||
|
public ulong Sender { get; set; }
|
||||||
|
public ulong OriginalMid { get; set; }
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue