From e65c2de5423f4103f80b8562be16bf30c3564354 Mon Sep 17 00:00:00 2001 From: Iris System Date: Wed, 23 Nov 2022 23:54:21 +1300 Subject: [PATCH] feat(bot): add admin command for account recovery --- PluralKit.Bot/CommandMeta/CommandTree.cs | 2 + PluralKit.Bot/Commands/Admin.cs | 55 +++++++++++++++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/PluralKit.Bot/CommandMeta/CommandTree.cs b/PluralKit.Bot/CommandMeta/CommandTree.cs index da051b20..0d5eb3d7 100644 --- a/PluralKit.Bot/CommandMeta/CommandTree.cs +++ b/PluralKit.Bot/CommandMeta/CommandTree.cs @@ -127,6 +127,8 @@ public partial class CommandTree await ctx.Execute(Admin, a => a.SystemMemberLimit(ctx)); else if (ctx.Match("ugl", "updategrouplimit")) await ctx.Execute(Admin, a => a.SystemGroupLimit(ctx)); + else if (ctx.Match("sr", "systemrecover")) + await ctx.Execute(Admin, a => a.SystemRecover(ctx)); else await ctx.Reply($"{Emojis.Error} Unknown command."); } diff --git a/PluralKit.Bot/Commands/Admin.cs b/PluralKit.Bot/Commands/Admin.cs index d5a2ed0f..374ab485 100644 --- a/PluralKit.Bot/Commands/Admin.cs +++ b/PluralKit.Bot/Commands/Admin.cs @@ -3,6 +3,9 @@ using System.Text.RegularExpressions; using Dapper; using SqlKata; +using Myriad.Rest; +using Myriad.Types; + using PluralKit.Core; namespace PluralKit.Bot; @@ -10,10 +13,12 @@ namespace PluralKit.Bot; public class Admin { private readonly BotConfig _botConfig; + private readonly DiscordApiClient _rest; - public Admin(BotConfig botConfig) + public Admin(BotConfig botConfig, DiscordApiClient rest) { _botConfig = botConfig; + _rest = rest; } public async Task UpdateSystemId(Context ctx) @@ -213,4 +218,52 @@ public class Admin await ctx.Repository.UpdateSystemConfig(target.Id, new SystemConfigPatch { GroupLimitOverride = newLimit }); await ctx.Reply($"{Emojis.Success} Group limit updated."); } + + public async Task SystemRecover(Context ctx) + { + ctx.AssertBotAdmin(); + + var rerollToken = ctx.MatchFlag("rt", "reroll-token"); + + var systemToken = ctx.PopArgument(); + var systemId = await ctx.Database.Execute(conn => conn.QuerySingleOrDefaultAsync( + "select id from systems where token = @token", + new { token = systemToken } + )); + + if (systemId == null) + throw new PKError("Could not retrieve a system with that token."); + + var account = await ctx.MatchUser(); + if (account == null) + throw new PKError("You must pass an account to associate the system with (either ID or @mention)."); + + var existingAccount = await ctx.Repository.GetSystemByAccount(account.Id); + if (existingAccount != null) + throw Errors.AccountInOtherSystem(existingAccount); + + var system = await ctx.Repository.GetSystem(systemId.Value!); + + if (!await ctx.PromptYesNo($"Associate account {account.NameAndMention()} with system `{system.Hid}`?", "Recover account")) + throw new PKError("System recovery cancelled."); + + await ctx.Repository.AddAccount(system.Id, account.Id); + if (rerollToken) + await ctx.Repository.UpdateSystem(system.Id, new SystemPatch { Token = StringUtils.GenerateToken() }); + + if ((await ctx.BotPermissions).HasFlag(PermissionSet.ManageMessages)) + await _rest.DeleteMessage(ctx.Message); + + await ctx.Reply(null, new Embed + { + Title = "System recovered", + Description = $"{account.NameAndMention()} has been linked to system `{system.Hid}`.", + Fields = new Embed.Field[] + { + new Embed.Field("Token rerolled?", rerollToken ? "yes" : "no", true), + new Embed.Field("Actioned by", ctx.Author.NameAndMention(), true), + }, + Color = DiscordUtils.Green, + }); + } } \ No newline at end of file