Merge pull request #233 from dev-kittens/feature/delete-bot-responses
Allow deleting bot responses with ❌ reaction
This commit is contained in:
commit
8f56a1cc32
@ -9,6 +9,8 @@ using App.Metrics;
|
|||||||
|
|
||||||
using Autofac;
|
using Autofac;
|
||||||
|
|
||||||
|
using Dapper;
|
||||||
|
|
||||||
using DSharpPlus;
|
using DSharpPlus;
|
||||||
using DSharpPlus.Entities;
|
using DSharpPlus.Entities;
|
||||||
using DSharpPlus.EventArgs;
|
using DSharpPlus.EventArgs;
|
||||||
@ -34,18 +36,21 @@ namespace PluralKit.Bot
|
|||||||
private readonly PeriodicStatCollector _collector;
|
private readonly PeriodicStatCollector _collector;
|
||||||
private readonly IMetrics _metrics;
|
private readonly IMetrics _metrics;
|
||||||
private readonly ErrorMessageService _errorMessageService;
|
private readonly ErrorMessageService _errorMessageService;
|
||||||
|
private readonly IDatabase _db;
|
||||||
|
|
||||||
private bool _hasReceivedReady = false;
|
private bool _hasReceivedReady = false;
|
||||||
private Timer _periodicTask; // Never read, just kept here for GC reasons
|
private Timer _periodicTask; // Never read, just kept here for GC reasons
|
||||||
|
|
||||||
public Bot(DiscordShardedClient client, ILifetimeScope services, ILogger logger, PeriodicStatCollector collector, IMetrics metrics, ErrorMessageService errorMessageService)
|
public Bot(DiscordShardedClient client, ILifetimeScope services, ILogger logger, PeriodicStatCollector collector, IMetrics metrics,
|
||||||
|
ErrorMessageService errorMessageService, IDatabase db)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
|
_logger = logger.ForContext<Bot>();
|
||||||
_services = services;
|
_services = services;
|
||||||
_collector = collector;
|
_collector = collector;
|
||||||
_metrics = metrics;
|
_metrics = metrics;
|
||||||
_errorMessageService = errorMessageService;
|
_errorMessageService = errorMessageService;
|
||||||
_logger = logger.ForContext<Bot>();
|
_db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
@ -177,6 +182,9 @@ namespace PluralKit.Bot
|
|||||||
|
|
||||||
await UpdateBotStatus();
|
await UpdateBotStatus();
|
||||||
|
|
||||||
|
// Clean up message cache in postgres
|
||||||
|
await _db.Execute(conn => conn.QueryAsync("select from cleanup_command_message()"));
|
||||||
|
|
||||||
// Collect some stats, submit them to the metrics backend
|
// Collect some stats, submit them to the metrics backend
|
||||||
await _collector.CollectStats();
|
await _collector.CollectStats();
|
||||||
await Task.WhenAll(((IMetricsRoot) _metrics).ReportRunner.RunAllAsync());
|
await Task.WhenAll(((IMetricsRoot) _metrics).ReportRunner.RunAllAsync());
|
||||||
|
@ -64,7 +64,7 @@ namespace PluralKit.Bot
|
|||||||
internal IDatabase Database => _db;
|
internal IDatabase Database => _db;
|
||||||
internal ModelRepository Repository => _repo;
|
internal ModelRepository Repository => _repo;
|
||||||
|
|
||||||
public Task<DiscordMessage> Reply(string text = null, DiscordEmbed embed = null, IEnumerable<IMention> mentions = null)
|
public async Task<DiscordMessage> Reply(string text = null, DiscordEmbed embed = null, IEnumerable<IMention> mentions = null)
|
||||||
{
|
{
|
||||||
if (!this.BotHasAllPermissions(Permissions.SendMessages))
|
if (!this.BotHasAllPermissions(Permissions.SendMessages))
|
||||||
// Will be "swallowed" during the error handler anyway, this message is never shown.
|
// Will be "swallowed" during the error handler anyway, this message is never shown.
|
||||||
@ -72,7 +72,12 @@ namespace PluralKit.Bot
|
|||||||
|
|
||||||
if (embed != null && !this.BotHasAllPermissions(Permissions.EmbedLinks))
|
if (embed != null && !this.BotHasAllPermissions(Permissions.EmbedLinks))
|
||||||
throw new PKError("PluralKit does not have permission to send embeds in this channel. Please ensure I have the **Embed Links** permission enabled.");
|
throw new PKError("PluralKit does not have permission to send embeds in this channel. Please ensure I have the **Embed Links** permission enabled.");
|
||||||
return Channel.SendMessageFixedAsync(text, embed: embed, mentions: mentions);
|
var msg = await Channel.SendMessageFixedAsync(text, embed: embed, mentions: mentions);
|
||||||
|
if (embed != null)
|
||||||
|
// Sensitive information that might want to be deleted by :x: reaction is typically in an embed format (member cards, for example)
|
||||||
|
// This may need to be changed at some point but works well enough for now
|
||||||
|
await _db.Execute(conn => _repo.SaveCommandMessage(conn, msg.Id, Author.Id));
|
||||||
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Execute<T>(Command commandDef, Func<T, Task> handler)
|
public async Task Execute<T>(Command commandDef, Func<T, Task> handler)
|
||||||
|
@ -189,9 +189,9 @@ namespace PluralKit.Bot
|
|||||||
if (ctx.Match("random", "r"))
|
if (ctx.Match("random", "r"))
|
||||||
return ctx.Execute<Member>(MemberRandom, m => m.MemberRandom(ctx));
|
return ctx.Execute<Member>(MemberRandom, m => m.MemberRandom(ctx));
|
||||||
|
|
||||||
ctx.Reply(
|
// remove compiler warning
|
||||||
|
return ctx.Reply(
|
||||||
$"{Emojis.Error} Unknown command {ctx.PeekArgument().AsCode()}. For a list of possible commands, see <https://pluralkit.me/commands>.");
|
$"{Emojis.Error} Unknown command {ctx.PeekArgument().AsCode()}. For a list of possible commands, see <https://pluralkit.me/commands>.");
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HandleSystemCommand(Context ctx)
|
private async Task HandleSystemCommand(Context ctx)
|
||||||
|
@ -48,12 +48,15 @@ namespace PluralKit.Bot
|
|||||||
_db.Execute(c => _repo.GetMessage(c, evt.Message.Id));
|
_db.Execute(c => _repo.GetMessage(c, evt.Message.Id));
|
||||||
|
|
||||||
FullMessage msg;
|
FullMessage msg;
|
||||||
|
CommandMessage cmdmsg;
|
||||||
switch (evt.Emoji.Name)
|
switch (evt.Emoji.Name)
|
||||||
{
|
{
|
||||||
// Message deletion
|
// Message deletion
|
||||||
case "\u274C": // Red X
|
case "\u274C": // Red X
|
||||||
if ((msg = await GetMessage()) != null)
|
if ((msg = await GetMessage()) != null)
|
||||||
await HandleDeleteReaction(evt, msg);
|
await HandleDeleteReaction(evt, msg);
|
||||||
|
else if ((cmdmsg = await _db.Execute(conn => _repo.GetCommandMessage(conn, evt.Message.Id))) != null)
|
||||||
|
await HandleCommandDeleteReaction(evt, cmdmsg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "\u2753": // Red question mark
|
case "\u2753": // Red question mark
|
||||||
@ -92,6 +95,25 @@ namespace PluralKit.Bot
|
|||||||
await _db.Execute(c => _repo.DeleteMessage(c, evt.Message.Id));
|
await _db.Execute(c => _repo.DeleteMessage(c, evt.Message.Id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async ValueTask HandleCommandDeleteReaction(MessageReactionAddEventArgs evt, CommandMessage msg)
|
||||||
|
{
|
||||||
|
if (!evt.Channel.BotHasAllPermissions(Permissions.ManageMessages)) return;
|
||||||
|
|
||||||
|
// Can only delete your own message
|
||||||
|
if (msg.author_id != evt.User.Id) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await evt.Message.DeleteAsync();
|
||||||
|
}
|
||||||
|
catch (NotFoundException)
|
||||||
|
{
|
||||||
|
// Message was deleted by something/someone else before we got to it
|
||||||
|
}
|
||||||
|
|
||||||
|
// No need to delete database row here, it'll get deleted by the once-per-minute scheduled task.
|
||||||
|
}
|
||||||
|
|
||||||
private async ValueTask HandleQueryReaction(MessageReactionAddEventArgs evt, FullMessage msg)
|
private async ValueTask HandleQueryReaction(MessageReactionAddEventArgs evt, FullMessage msg)
|
||||||
{
|
{
|
||||||
// Try to DM the user info about the message
|
// Try to DM the user info about the message
|
||||||
|
@ -19,7 +19,7 @@ namespace PluralKit.Core
|
|||||||
internal class Database: IDatabase
|
internal class Database: IDatabase
|
||||||
{
|
{
|
||||||
private const string RootPath = "PluralKit.Core.Database"; // "resource path" root for SQL files
|
private const string RootPath = "PluralKit.Core.Database"; // "resource path" root for SQL files
|
||||||
private const int TargetSchemaVersion = 10;
|
private const int TargetSchemaVersion = 11;
|
||||||
|
|
||||||
private readonly CoreConfig _config;
|
private readonly CoreConfig _config;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
17
PluralKit.Core/Database/Migrations/11.sql
Normal file
17
PluralKit.Core/Database/Migrations/11.sql
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
-- SCHEMA VERSION 11: (insert date) --
|
||||||
|
-- Create command message table --
|
||||||
|
|
||||||
|
create table command_message
|
||||||
|
(
|
||||||
|
message_id bigint primary key,
|
||||||
|
author_id bigint not null,
|
||||||
|
timestamp timestamp not null default now()
|
||||||
|
);
|
||||||
|
|
||||||
|
create function cleanup_command_message() returns void as $$
|
||||||
|
begin
|
||||||
|
delete from command_message where timestamp < now() - interval '2 hours';
|
||||||
|
end;
|
||||||
|
$$ language plpgsql;
|
||||||
|
|
||||||
|
update info set schema_version = 11;
|
@ -0,0 +1,24 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Dapper;
|
||||||
|
|
||||||
|
namespace PluralKit.Core
|
||||||
|
{
|
||||||
|
public partial class ModelRepository
|
||||||
|
{
|
||||||
|
public Task SaveCommandMessage(IPKConnection conn, ulong message_id, ulong author_id) =>
|
||||||
|
conn.QueryAsync("insert into command_message (message_id, author_id) values (@Message, @Author)",
|
||||||
|
new {Message = message_id, Author = author_id });
|
||||||
|
|
||||||
|
public Task<CommandMessage> GetCommandMessage(IPKConnection conn, ulong message_id) =>
|
||||||
|
conn.QuerySingleOrDefaultAsync<CommandMessage>("select message_id, author_id from command_message where message_id = @Message",
|
||||||
|
new {Message = message_id});
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CommandMessage
|
||||||
|
{
|
||||||
|
public ulong author_id { get; set; }
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user