From dfacbc51ab5d0ee21937af63b352a7beee8b395e Mon Sep 17 00:00:00 2001
From: dev-kittens <acw@ml1.net>
Date: Sun, 4 Oct 2020 08:53:07 +0000
Subject: [PATCH] Confirm before clearing (most) entity properties

---
 PluralKit.Bot/CommandSystem/ContextArgumentsExt.cs | 11 ++++++++---
 PluralKit.Bot/Commands/Groups.cs                   |  8 ++++----
 PluralKit.Bot/Commands/MemberAvatar.cs             |  2 +-
 PluralKit.Bot/Commands/MemberEdit.cs               | 12 ++++++------
 PluralKit.Bot/Commands/MemberProxy.cs              |  4 ++--
 PluralKit.Bot/Commands/SystemEdit.cs               | 10 +++++-----
 PluralKit.Bot/Utils/ContextUtils.cs                |  6 ++++++
 7 files changed, 32 insertions(+), 21 deletions(-)

diff --git a/PluralKit.Bot/CommandSystem/ContextArgumentsExt.cs b/PluralKit.Bot/CommandSystem/ContextArgumentsExt.cs
index 299b84a8..8d8a9ce0 100644
--- a/PluralKit.Bot/CommandSystem/ContextArgumentsExt.cs
+++ b/PluralKit.Bot/CommandSystem/ContextArgumentsExt.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
@@ -60,8 +60,13 @@ namespace PluralKit.Bot
             return potentialMatches.Any(potentialMatch => flags.Contains(potentialMatch));
         }
 
-        public static bool MatchClear(this Context ctx) =>
-            ctx.Match("clear", "reset") || ctx.MatchFlag("c", "clear");
+        public static async Task<bool> MatchClear(this Context ctx, string toClear = null)
+        {
+            var matched = ctx.Match("clear", "reset") || ctx.MatchFlag("c", "clear");
+            Console.WriteLine(toClear);
+            if (matched && toClear != null) return await ctx.ConfirmClear(toClear);
+            else return matched;
+        }
 
         public static async Task<List<PKMember>> ParseMemberList(this Context ctx, SystemId? restrictToSystem)
         {
diff --git a/PluralKit.Bot/Commands/Groups.cs b/PluralKit.Bot/Commands/Groups.cs
index 732e85f2..19b6a625 100644
--- a/PluralKit.Bot/Commands/Groups.cs
+++ b/PluralKit.Bot/Commands/Groups.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
@@ -86,7 +86,7 @@ namespace PluralKit.Bot
 
         public async Task GroupDisplayName(Context ctx, PKGroup target)
         {
-            if (ctx.MatchClear())
+            if (await ctx.MatchClear("this group's display name"))
             {
                 ctx.CheckOwnGroup(target);
                 
@@ -122,7 +122,7 @@ namespace PluralKit.Bot
         
         public async Task GroupDescription(Context ctx, PKGroup target)
         {
-            if (ctx.MatchClear())
+            if (await ctx.MatchClear("this group's description"))
             {
                 ctx.CheckOwnGroup(target);
 
@@ -216,7 +216,7 @@ namespace PluralKit.Bot
                     throw new PKSyntaxError("This group does not have an icon set. Set one by attaching an image to this command, or by passing an image URL or @mention.");
             }
 
-            if (ctx.MatchClear())
+            if (await ctx.MatchClear("this group's icon"))
                 await ClearIcon();
             else if (await ctx.MatchImage() is {} img)
                 await SetIcon(img);
diff --git a/PluralKit.Bot/Commands/MemberAvatar.cs b/PluralKit.Bot/Commands/MemberAvatar.cs
index bf1726dc..255052bc 100644
--- a/PluralKit.Bot/Commands/MemberAvatar.cs
+++ b/PluralKit.Bot/Commands/MemberAvatar.cs
@@ -85,7 +85,7 @@ namespace PluralKit.Bot
         private async Task AvatarCommandTree(AvatarLocation location, Context ctx, PKMember target, MemberGuildSettings? guildData)
         {
             // First, see if we need to *clear*
-            if (ctx.MatchClear())
+            if (await ctx.MatchClear("this member's avatar"))
             {
                 ctx.CheckSystem().CheckOwnMember(target);
                 await AvatarClear(location, ctx, target, guildData);
diff --git a/PluralKit.Bot/Commands/MemberEdit.cs b/PluralKit.Bot/Commands/MemberEdit.cs
index 727af9de..af8a2eec 100644
--- a/PluralKit.Bot/Commands/MemberEdit.cs
+++ b/PluralKit.Bot/Commands/MemberEdit.cs
@@ -64,7 +64,7 @@ namespace PluralKit.Bot
         }
 
         public async Task Description(Context ctx, PKMember target) {
-            if (ctx.MatchClear())
+            if (await ctx.MatchClear("this member's description"))
             {
                 CheckEditMemberPermission(ctx, target);
 
@@ -107,7 +107,7 @@ namespace PluralKit.Bot
         }
         
         public async Task Pronouns(Context ctx, PKMember target) {
-            if (ctx.MatchClear())
+            if (await ctx.MatchClear("this member's pronouns"))
             {
                 CheckEditMemberPermission(ctx, target);
                 var patch = new MemberPatch {Pronouns = Partial<string>.Null()};
@@ -145,7 +145,7 @@ namespace PluralKit.Bot
         public async Task Color(Context ctx, PKMember target)
         {
             var color = ctx.RemainderOrNull();
-            if (ctx.MatchClear())
+            if (await ctx.MatchClear())
             {
                 CheckEditMemberPermission(ctx, target);
                 
@@ -193,7 +193,7 @@ namespace PluralKit.Bot
         }
         public async Task Birthday(Context ctx, PKMember target)
         {
-            if (ctx.MatchClear())
+            if (await ctx.MatchClear("this member's birthday"))
             {
                 CheckEditMemberPermission(ctx, target);
                 
@@ -279,7 +279,7 @@ namespace PluralKit.Bot
                 await ctx.Reply(successStr);
             }
             
-            if (ctx.MatchClear())
+            if (await ctx.MatchClear("this member's display name"))
             {
                 CheckEditMemberPermission(ctx, target);
                 
@@ -313,7 +313,7 @@ namespace PluralKit.Bot
         {
             ctx.CheckGuildContext();
             
-            if (ctx.MatchClear())
+            if (await ctx.MatchClear("this member's server name"))
             {
                 CheckEditMemberPermission(ctx, target);
 
diff --git a/PluralKit.Bot/Commands/MemberProxy.cs b/PluralKit.Bot/Commands/MemberProxy.cs
index 3df730b1..fb9ef0fd 100644
--- a/PluralKit.Bot/Commands/MemberProxy.cs
+++ b/PluralKit.Bot/Commands/MemberProxy.cs
@@ -1,4 +1,4 @@
-using System.Linq;
+using System.Linq;
 using System.Threading.Tasks;
 
 using Dapper;
@@ -46,7 +46,7 @@ namespace PluralKit.Bot
             }
             
             // "Sub"command: clear flag
-            if (ctx.MatchClear())
+            if (await ctx.MatchClear())
             {
                 // If we already have multiple tags, this would clear everything, so prompt that
                 if (target.ProxyTags.Count > 1)
diff --git a/PluralKit.Bot/Commands/SystemEdit.cs b/PluralKit.Bot/Commands/SystemEdit.cs
index 0ab656eb..39676ebd 100644
--- a/PluralKit.Bot/Commands/SystemEdit.cs
+++ b/PluralKit.Bot/Commands/SystemEdit.cs
@@ -32,7 +32,7 @@ namespace PluralKit.Bot
         {
             ctx.CheckSystem();
 
-            if (ctx.MatchClear())
+            if (await ctx.MatchClear("your system's name"))
             {
                 var clearPatch = new SystemPatch {Name = null};
                 await _db.Execute(conn => _repo.UpdateSystem(conn, ctx.System.Id, clearPatch));
@@ -63,7 +63,7 @@ namespace PluralKit.Bot
         public async Task Description(Context ctx) {
             ctx.CheckSystem();
 
-            if (ctx.MatchClear())
+            if (await ctx.MatchClear("your system's description"))
             {
                 var patch = new SystemPatch {Description = null};
                 await _db.Execute(conn => _repo.UpdateSystem(conn, ctx.System.Id, patch));
@@ -101,7 +101,7 @@ namespace PluralKit.Bot
         {
             ctx.CheckSystem();
 
-            if (ctx.MatchClear())
+            if (await ctx.MatchClear("your system's tag"))
             {
                 var patch = new SystemPatch {Tag = null};
                 await _db.Execute(conn => _repo.UpdateSystem(conn, ctx.System.Id, patch));
@@ -175,7 +175,7 @@ namespace PluralKit.Bot
                     throw new PKSyntaxError("This system does not have an icon set. Set one by attaching an image to this command, or by passing an image URL or @mention.");
             }
 
-            if (ctx.MatchClear())
+            if (await ctx.MatchClear("your system's icon"))
                 await ClearIcon();
             else if (await ctx.MatchImage() is {} img)
                 await SetIcon(img);
@@ -226,7 +226,7 @@ namespace PluralKit.Bot
         {
             if (ctx.System == null) throw Errors.NoSystemError;
 
-            if (ctx.MatchClear())
+            if (await ctx.MatchClear())
             {
                 var clearPatch = new SystemPatch {UiTz = "UTC"};
                 await _db.Execute(conn => _repo.UpdateSystem(conn, ctx.System.Id, clearPatch));
diff --git a/PluralKit.Bot/Utils/ContextUtils.cs b/PluralKit.Bot/Utils/ContextUtils.cs
index 5fab9056..0cfb8203 100644
--- a/PluralKit.Bot/Utils/ContextUtils.cs
+++ b/PluralKit.Bot/Utils/ContextUtils.cs
@@ -17,6 +17,12 @@ using PluralKit.Core;
 
 namespace PluralKit.Bot {
     public static class ContextUtils {
+        public static async Task<bool> ConfirmClear(this Context ctx, string toClear)
+        {
+            if (!(await ctx.PromptYesNo($"{Emojis.Warn} Are you sure you want to clear {toClear}?"))) throw Errors.GenericCancelled();
+            else return true;
+        }
+
         public static async Task<bool> PromptYesNo(this Context ctx, String msgString, DiscordUser user = null, Duration? timeout = null, IEnumerable<IMention> mentions = null)
         {
             DiscordMessage message;