public async Task SwitchDelete(Context ctx) { ctx.CheckSystem(); if (ctx.Match("all", "clear")) { // Subcommand: "delete all" var purgeMsg = await ctx.Reply($"{Emojis.Warn} This will delete *all registered switches* in your system. Are you sure you want to proceed?"); if (!await ctx.PromptYesNo(purgeMsg)) { throw Errors.GenericCancelled(); } await _data.DeleteAllSwitches(ctx.System); await ctx.Reply($"{Emojis.Success} Cleared system switches!"); return; } // Fetch the last two switches for the system to do bounds checking on var lastTwoSwitches = await _data.GetSwitches(ctx.System).Take(2).ToListAsync(); if (lastTwoSwitches.Count == 0) { throw Errors.NoRegisteredSwitches; } var lastSwitchMembers = _data.GetSwitchMembers(lastTwoSwitches[0]); var lastSwitchMemberStr = string.Join(", ", await lastSwitchMembers.Select(m => m.Name).ToListAsync()); var lastSwitchDeltaStr = DateTimeFormats.DurationFormat.Format(SystemClock.Instance.GetCurrentInstant() - lastTwoSwitches[0].Timestamp); DiscordMessage msg; if (lastTwoSwitches.Count == 1) { msg = await ctx.Reply( $"{Emojis.Warn} This will delete the latest switch ({lastSwitchMemberStr.SanitizeMentions()}, {lastSwitchDeltaStr} ago). You have no other switches logged. Is this okay?"); } else { var secondSwitchMembers = _data.GetSwitchMembers(lastTwoSwitches[1]); var secondSwitchMemberStr = string.Join(", ", await secondSwitchMembers.Select(m => m.Name).ToListAsync()); var secondSwitchDeltaStr = DateTimeFormats.DurationFormat.Format(SystemClock.Instance.GetCurrentInstant() - lastTwoSwitches[1].Timestamp); msg = await ctx.Reply( $"{Emojis.Warn} This will delete the latest switch ({lastSwitchMemberStr.SanitizeMentions()}, {lastSwitchDeltaStr} ago). The next latest switch is {secondSwitchMemberStr.SanitizeMentions()} ({secondSwitchDeltaStr} ago). Is this okay?"); } if (!await ctx.PromptYesNo(msg)) { throw Errors.SwitchDeleteCancelled; } await _data.DeleteSwitch(lastTwoSwitches[0]); await ctx.Reply($"{Emojis.Success} Switch deleted."); }
public async Task SwitchDelete(Context ctx) { ctx.CheckSystem(); if (ctx.Match("all", "clear") || ctx.MatchFlag("all", "clear")) { // Subcommand: "delete all" var purgeMsg = $"{Emojis.Warn} This will delete *all registered switches* in your system. Are you sure you want to proceed?"; if (!await ctx.PromptYesNo(purgeMsg, "Clear Switches")) { throw Errors.GenericCancelled(); } await _db.Execute(c => _repo.DeleteAllSwitches(c, ctx.System.Id)); await ctx.Reply($"{Emojis.Success} Cleared system switches!"); return; } await using var conn = await _db.Obtain(); // Fetch the last two switches for the system to do bounds checking on var lastTwoSwitches = await _repo.GetSwitches(conn, ctx.System.Id).Take(2).ToListAsync(); if (lastTwoSwitches.Count == 0) { throw Errors.NoRegisteredSwitches; } var lastSwitchMembers = _repo.GetSwitchMembers(conn, lastTwoSwitches[0].Id); var lastSwitchMemberStr = string.Join(", ", await lastSwitchMembers.Select(m => m.NameFor(ctx)).ToListAsync()); var lastSwitchDeltaStr = (SystemClock.Instance.GetCurrentInstant() - lastTwoSwitches[0].Timestamp).FormatDuration(); string msg; if (lastTwoSwitches.Count == 1) { msg = $"{Emojis.Warn} This will delete the latest switch ({lastSwitchMemberStr}, {lastSwitchDeltaStr} ago). You have no other switches logged. Is this okay?"; } else { var secondSwitchMembers = _repo.GetSwitchMembers(conn, lastTwoSwitches[1].Id); var secondSwitchMemberStr = string.Join(", ", await secondSwitchMembers.Select(m => m.NameFor(ctx)).ToListAsync()); var secondSwitchDeltaStr = (SystemClock.Instance.GetCurrentInstant() - lastTwoSwitches[1].Timestamp).FormatDuration(); msg = $"{Emojis.Warn} This will delete the latest switch ({lastSwitchMemberStr}, {lastSwitchDeltaStr} ago). The next latest switch is {secondSwitchMemberStr} ({secondSwitchDeltaStr} ago). Is this okay?"; } if (!await ctx.PromptYesNo(msg, "Delete Switch")) { throw Errors.SwitchDeleteCancelled; } await _repo.DeleteSwitch(conn, lastTwoSwitches[0].Id); await ctx.Reply($"{Emojis.Success} Switch deleted."); }
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}?", "Clear"))) { throw Errors.GenericCancelled(); } else { return(true); } }
public async Task Proxy(Context ctx, PKMember target) { ctx.CheckSystem().CheckOwnMember(target); ProxyTag ParseProxyTags(string exampleProxy) { // // Make sure there's one and only one instance of "text" in the example proxy given var prefixAndSuffix = exampleProxy.Split("text"); if (prefixAndSuffix.Length == 1) { prefixAndSuffix = prefixAndSuffix[0].Split("TEXT"); } if (prefixAndSuffix.Length < 2) { throw Errors.ProxyMustHaveText; } if (prefixAndSuffix.Length > 2) { throw Errors.ProxyMultipleText; } return(new ProxyTag(prefixAndSuffix[0], prefixAndSuffix[1])); } async Task <bool> WarnOnConflict(ProxyTag newTag) { var query = "select * from (select *, (unnest(proxy_tags)).prefix as prefix, (unnest(proxy_tags)).suffix as suffix from members where system = @System) as _ where prefix is not distinct from @Prefix and suffix is not distinct from @Suffix and id != @Existing"; var conflicts = (await _db.Execute(conn => conn.QueryAsync <PKMember>(query, new { Prefix = newTag.Prefix, Suffix = newTag.Suffix, Existing = target.Id, system = target.System }))).ToList(); if (conflicts.Count <= 0) { return(true); } var conflictList = conflicts.Select(m => $"- **{m.NameFor(ctx)}**"); var msg = $"{Emojis.Warn} The following members have conflicting proxy tags:\n{string.Join('\n', conflictList)}\nDo you want to proceed anyway?"; return(await ctx.PromptYesNo(msg, "Proceed")); } // "Sub"command: clear flag if (await ctx.MatchClear()) { // If we already have multiple tags, this would clear everything, so prompt that if (target.ProxyTags.Count > 1) { var msg = $"{Emojis.Warn} You already have multiple proxy tags set: {target.ProxyTagsString()}\nDo you want to clear them all?"; if (!await ctx.PromptYesNo(msg, "Clear")) { throw Errors.GenericCancelled(); } } var patch = new MemberPatch { ProxyTags = Partial <ProxyTag[]> .Present(new ProxyTag[0]) }; await _db.Execute(conn => _repo.UpdateMember(conn, target.Id, patch)); await ctx.Reply($"{Emojis.Success} Proxy tags cleared."); } // "Sub"command: no arguments; will print proxy tags else if (!ctx.HasNext(skipFlags: false)) { if (target.ProxyTags.Count == 0) { await ctx.Reply("This member does not have any proxy tags."); } else { await ctx.Reply($"This member's proxy tags are:\n{target.ProxyTagsString("\n")}"); } } // Subcommand: "add" else if (ctx.Match("add", "append")) { if (!ctx.HasNext(skipFlags: false)) { throw new PKSyntaxError("You must pass an example proxy to add (eg. `[text]` or `J:text`)."); } var tagToAdd = ParseProxyTags(ctx.RemainderOrNull(skipFlags: false)); if (tagToAdd.IsEmpty) { throw Errors.EmptyProxyTags(target); } if (target.ProxyTags.Contains(tagToAdd)) { throw Errors.ProxyTagAlreadyExists(tagToAdd, target); } if (!await WarnOnConflict(tagToAdd)) { throw Errors.GenericCancelled(); } var newTags = target.ProxyTags.ToList(); newTags.Add(tagToAdd); var patch = new MemberPatch { ProxyTags = Partial <ProxyTag[]> .Present(newTags.ToArray()) }; await _db.Execute(conn => _repo.UpdateMember(conn, target.Id, patch)); await ctx.Reply($"{Emojis.Success} Added proxy tags {tagToAdd.ProxyString.AsCode()}."); } // Subcommand: "remove" else if (ctx.Match("remove", "delete")) { if (!ctx.HasNext(skipFlags: false)) { throw new PKSyntaxError("You must pass a proxy tag to remove (eg. `[text]` or `J:text`)."); } var tagToRemove = ParseProxyTags(ctx.RemainderOrNull(skipFlags: false)); if (tagToRemove.IsEmpty) { throw Errors.EmptyProxyTags(target); } if (!target.ProxyTags.Contains(tagToRemove)) { throw Errors.ProxyTagDoesNotExist(tagToRemove, target); } var newTags = target.ProxyTags.ToList(); newTags.Remove(tagToRemove); var patch = new MemberPatch { ProxyTags = Partial <ProxyTag[]> .Present(newTags.ToArray()) }; await _db.Execute(conn => _repo.UpdateMember(conn, target.Id, patch)); await ctx.Reply($"{Emojis.Success} Removed proxy tags {tagToRemove.ProxyString.AsCode()}."); } // Subcommand: bare proxy tag given else { var requestedTag = ParseProxyTags(ctx.RemainderOrNull(skipFlags: false)); if (requestedTag.IsEmpty) { throw Errors.EmptyProxyTags(target); } // This is mostly a legacy command, so it's gonna warn if there's // already more than one proxy tag. if (target.ProxyTags.Count > 1) { var msg = $"This member already has more than one proxy tag set: {target.ProxyTagsString()}\nDo you want to replace them?"; if (!await ctx.PromptYesNo(msg, "Replace")) { throw Errors.GenericCancelled(); } } if (!await WarnOnConflict(requestedTag)) { throw Errors.GenericCancelled(); } var newTags = new[] { requestedTag }; var patch = new MemberPatch { ProxyTags = Partial <ProxyTag[]> .Present(newTags) }; await _db.Execute(conn => _repo.UpdateMember(conn, target.Id, patch)); await ctx.Reply($"{Emojis.Success} Member proxy tags set to {requestedTag.ProxyString.AsCode()}."); } }
public async Task Proxy(Context ctx, PKMember target) { if (ctx.System == null) { throw Errors.NoSystemError; } if (target.System != ctx.System.Id) { throw Errors.NotOwnMemberError; } ProxyTag ParseProxyTags(string exampleProxy) { // // Make sure there's one and only one instance of "text" in the example proxy given var prefixAndSuffix = exampleProxy.Split("text"); if (prefixAndSuffix.Length < 2) { throw Errors.ProxyMustHaveText; } if (prefixAndSuffix.Length > 2) { throw Errors.ProxyMultipleText; } return(new ProxyTag(prefixAndSuffix[0], prefixAndSuffix[1])); } async Task <bool> WarnOnConflict(ProxyTag newTag) { var conflicts = (await _data.GetConflictingProxies(ctx.System, newTag)) .Where(m => m.Id != target.Id) .ToList(); if (conflicts.Count <= 0) { return(true); } var conflictList = conflicts.Select(m => $"- **{m.Name}**"); var msg = await ctx.Reply( $"{Emojis.Warn} The following members have conflicting proxy tags:\n{string.Join('\n', conflictList)}\nDo you want to proceed anyway?"); return(await ctx.PromptYesNo(msg)); } // "Sub"command: no arguments clearing // Also matches the pseudo-subcommand "text" which is equivalent to empty proxy tags on both sides. if (!ctx.HasNext() || ctx.Match("clear", "purge", "clean", "removeall")) { // If we already have multiple tags, this would clear everything, so prompt that if (target.ProxyTags.Count > 1) { var msg = await ctx.Reply( $"{Emojis.Warn} You already have multiple proxy tags set: {target.ProxyTagsString()}\nDo you want to clear them all?"); if (!await ctx.PromptYesNo(msg)) { throw Errors.GenericCancelled(); } } target.ProxyTags = new ProxyTag[] { }; await _data.SaveMember(target); await ctx.Reply($"{Emojis.Success} Proxy tags cleared."); } // Subcommand: "add" else if (ctx.Match("add", "append")) { if (!ctx.HasNext()) { throw new PKSyntaxError("You must pass an example proxy to add (eg. `[text]` or `J:text`)."); } var tagToAdd = ParseProxyTags(ctx.RemainderOrNull()); if (tagToAdd.IsEmpty) { throw Errors.EmptyProxyTags(target); } if (target.ProxyTags.Contains(tagToAdd)) { throw Errors.ProxyTagAlreadyExists(tagToAdd, target); } if (!await WarnOnConflict(tagToAdd)) { throw Errors.GenericCancelled(); } // It's not guaranteed the list's mutable, so we force it to be target.ProxyTags = target.ProxyTags.ToList(); target.ProxyTags.Add(tagToAdd); await _data.SaveMember(target); await ctx.Reply($"{Emojis.Success} Added proxy tags `{tagToAdd.ProxyString.SanitizeMentions()}`."); } // Subcommand: "remove" else if (ctx.Match("remove", "delete")) { if (!ctx.HasNext()) { throw new PKSyntaxError("You must pass a proxy tag to remove (eg. `[text]` or `J:text`)."); } var tagToRemove = ParseProxyTags(ctx.RemainderOrNull()); if (tagToRemove.IsEmpty) { throw Errors.EmptyProxyTags(target); } if (!target.ProxyTags.Contains(tagToRemove)) { throw Errors.ProxyTagDoesNotExist(tagToRemove, target); } // It's not guaranteed the list's mutable, so we force it to be target.ProxyTags = target.ProxyTags.ToList(); target.ProxyTags.Remove(tagToRemove); await _data.SaveMember(target); await ctx.Reply($"{Emojis.Success} Removed proxy tags `{tagToRemove.ProxyString.SanitizeMentions()}`."); } // Subcommand: bare proxy tag given else { if (!ctx.HasNext()) { throw new PKSyntaxError("You must pass an example proxy to set (eg. `[text]` or `J:text`)."); } var requestedTag = ParseProxyTags(ctx.RemainderOrNull()); if (requestedTag.IsEmpty) { throw Errors.EmptyProxyTags(target); } // This is mostly a legacy command, so it's gonna warn if there's // already more than one proxy tag. if (target.ProxyTags.Count > 1) { var msg = await ctx.Reply($"This member already has more than one proxy tag set: {target.ProxyTagsString().SanitizeMentions()}\nDo you want to replace them?"); if (!await ctx.PromptYesNo(msg)) { throw Errors.GenericCancelled(); } } if (!await WarnOnConflict(requestedTag)) { throw Errors.GenericCancelled(); } target.ProxyTags = new[] { requestedTag }; await _data.SaveMember(target); await ctx.Reply($"{Emojis.Success} Member proxy tags set to `{requestedTag.ProxyString.SanitizeMentions()}`."); } }