remove rest of the parsing in csharp bot

This commit is contained in:
dusk 2025-10-08 03:26:40 +00:00
parent 15ffd16c01
commit 479e0a59b5
No known key found for this signature in database
35 changed files with 242 additions and 409 deletions

View file

@ -7,28 +7,13 @@ public partial class CommandTree
private async Task PrintCommandList(Context ctx, string subject, string commands)
{
await ctx.Reply(
$"Here is a list of commands related to {subject}:",
embed: new Embed()
{
Description = $"{commands}\nFor a full list of possible commands, see <https://pluralkit.me/commands>.",
Color = DiscordUtils.Blue,
}
components: [
new MessageComponent()
{
Type = ComponentType.Text,
Content = $"Here is a list of commands related to {subject}:\n{commands}\nFor a full list of possible commands, see <https://pluralkit.me/commands>.",
}
]
);
}
private async Task<string> CreateSystemNotFoundError(Context ctx)
{
var input = ctx.PopArgument();
if (input.TryParseMention(out var id))
{
// Try to resolve the user ID to find the associated account,
// so we can print their username.
var user = await ctx.Rest.GetUser(id);
if (user != null)
return $"Account **{user.Username}#{user.Discriminator}** does not have a system registered.";
return $"Account with ID `{id}` not found.";
}
return $"System with ID {input.AsCode()} not found.";
}
}

View file

@ -22,13 +22,13 @@ public partial class CommandTree
Commands.MemberNew(var param, _) => ctx.Execute<Member>(MemberNew, m => m.NewMember(ctx, param.name)),
Commands.MemberSoulscream(var param, _) => ctx.Execute<Member>(MemberInfo, m => m.Soulscream(ctx, param.target)),
Commands.MemberAvatarShow(var param, var flags) => ctx.Execute<MemberAvatar>(MemberAvatar, m => m.ShowAvatar(ctx, param.target, flags.GetReplyFormat())),
Commands.MemberAvatarClear(var param, var flags) => ctx.Execute<MemberAvatar>(MemberAvatar, m => m.ClearAvatar(ctx, param.target)),
Commands.MemberAvatarClear(var param, var flags) => ctx.Execute<MemberAvatar>(MemberAvatar, m => m.ClearAvatar(ctx, param.target, flags.yes)),
Commands.MemberAvatarUpdate(var param, _) => ctx.Execute<MemberAvatar>(MemberAvatar, m => m.ChangeAvatar(ctx, param.target, param.avatar)),
Commands.MemberWebhookAvatarShow(var param, var flags) => ctx.Execute<MemberAvatar>(MemberAvatar, m => m.ShowWebhookAvatar(ctx, param.target, flags.GetReplyFormat())),
Commands.MemberWebhookAvatarClear(var param, var flags) => ctx.Execute<MemberAvatar>(MemberAvatar, m => m.ClearWebhookAvatar(ctx, param.target)),
Commands.MemberWebhookAvatarClear(var param, var flags) => ctx.Execute<MemberAvatar>(MemberAvatar, m => m.ClearWebhookAvatar(ctx, param.target, flags.yes)),
Commands.MemberWebhookAvatarUpdate(var param, _) => ctx.Execute<MemberAvatar>(MemberAvatar, m => m.ChangeWebhookAvatar(ctx, param.target, param.avatar)),
Commands.MemberServerAvatarShow(var param, var flags) => ctx.Execute<MemberAvatar>(MemberAvatar, m => m.ShowServerAvatar(ctx, param.target, flags.GetReplyFormat())),
Commands.MemberServerAvatarClear(var param, var flags) => ctx.Execute<MemberAvatar>(MemberAvatar, m => m.ClearServerAvatar(ctx, param.target)),
Commands.MemberServerAvatarClear(var param, var flags) => ctx.Execute<MemberAvatar>(MemberAvatar, m => m.ClearServerAvatar(ctx, param.target, flags.yes)),
Commands.MemberServerAvatarUpdate(var param, _) => ctx.Execute<MemberAvatar>(MemberAvatar, m => m.ChangeServerAvatar(ctx, param.target, param.avatar)),
Commands.MemberPronounsShow(var param, var flags) => ctx.Execute<MemberEdit>(MemberPronouns, m => m.ShowPronouns(ctx, param.target, flags.GetReplyFormat())),
Commands.MemberPronounsClear(var param, var flags) => ctx.Execute<MemberEdit>(MemberPronouns, m => m.ClearPronouns(ctx, param.target, flags.yes)),
@ -37,7 +37,7 @@ public partial class CommandTree
Commands.MemberDescClear(var param, var flags) => ctx.Execute<MemberEdit>(MemberDesc, m => m.ClearDescription(ctx, param.target, flags.yes)),
Commands.MemberDescUpdate(var param, _) => ctx.Execute<MemberEdit>(MemberDesc, m => m.ChangeDescription(ctx, param.target, param.description)),
Commands.MemberNameShow(var param, var flags) => ctx.Execute<MemberEdit>(MemberInfo, m => m.ShowName(ctx, param.target, flags.GetReplyFormat())),
Commands.MemberNameUpdate(var param, _) => ctx.Execute<MemberEdit>(MemberInfo, m => m.ChangeName(ctx, param.target, param.name)),
Commands.MemberNameUpdate(var param, var flags) => ctx.Execute<MemberEdit>(MemberInfo, m => m.ChangeName(ctx, param.target, param.name, flags.yes)),
Commands.MemberBannerShow(var param, var flags) => ctx.Execute<MemberEdit>(MemberBannerImage, m => m.ShowBannerImage(ctx, param.target, flags.GetReplyFormat())),
Commands.MemberBannerClear(var param, var flags) => ctx.Execute<MemberEdit>(MemberBannerImage, m => m.ClearBannerImage(ctx, param.target, flags.yes)),
Commands.MemberBannerUpdate(var param, _) => ctx.Execute<MemberEdit>(MemberBannerImage, m => m.ChangeBannerImage(ctx, param.target, param.banner)),
@ -59,7 +59,7 @@ public partial class CommandTree
Commands.MemberServerKeepproxyUpdate(var param, _) => ctx.Execute<MemberEdit>(MemberServerKeepProxy, m => m.ChangeServerKeepProxy(ctx, param.target, param.value)),
Commands.MemberServerKeepproxyClear(var param, var flags) => ctx.Execute<MemberEdit>(MemberServerKeepProxy, m => m.ClearServerKeepProxy(ctx, param.target, flags.yes)),
Commands.MemberProxyShow(var param, _) => ctx.Execute<MemberProxy>(MemberProxy, m => m.ShowProxy(ctx, param.target)),
Commands.MemberProxyClear(var param, var flags) => ctx.Execute<MemberProxy>(MemberProxy, m => m.ClearProxy(ctx, param.target)),
Commands.MemberProxyClear(var param, var flags) => ctx.Execute<MemberProxy>(MemberProxy, m => m.ClearProxy(ctx, param.target, flags.yes)),
Commands.MemberProxyAdd(var param, _) => ctx.Execute<MemberProxy>(MemberProxy, m => m.AddProxy(ctx, param.target, param.tag)),
Commands.MemberProxyRemove(var param, _) => ctx.Execute<MemberProxy>(MemberProxy, m => m.RemoveProxy(ctx, param.target, param.tag)),
Commands.MemberProxySet(var param, _) => ctx.Execute<MemberProxy>(MemberProxy, m => m.SetProxy(ctx, param.target, param.tags)),
@ -205,7 +205,7 @@ public partial class CommandTree
Commands.SwitchDo(var param, _) => ctx.Execute<Switch>(Switch, m => m.SwitchDo(ctx, param.targets)),
Commands.SwitchMove(var param, _) => ctx.Execute<Switch>(SwitchMove, m => m.SwitchMove(ctx, param.@string)),
Commands.SwitchEdit(var param, var flags) => ctx.Execute<Switch>(SwitchEdit, m => m.SwitchEdit(ctx, param.targets, false, flags.first, flags.remove, flags.append, flags.prepend)),
Commands.SwitchEditOut(_, _) => ctx.Execute<Switch>(SwitchEditOut, m => m.SwitchEditOut(ctx)),
Commands.SwitchEditOut(_, var flags) => ctx.Execute<Switch>(SwitchEditOut, m => m.SwitchEditOut(ctx, flags.yes)),
Commands.SwitchDelete(var param, var flags) => ctx.Execute<Switch>(SwitchDelete, m => m.SwitchDelete(ctx, flags.all)),
Commands.SwitchCopy(var param, var flags) => ctx.Execute<Switch>(SwitchCopy, m => m.SwitchEdit(ctx, param.targets, true, flags.first, flags.remove, flags.append, flags.prepend)),
Commands.SystemFronter(var param, var flags) => ctx.Execute<SystemFront>(SystemFronter, m => m.Fronter(ctx, param.target)),
@ -213,7 +213,9 @@ public partial class CommandTree
Commands.SystemFronterPercent(var param, var flags) => ctx.Execute<SystemFront>(SystemFrontPercent, m => m.FrontPercent(ctx, param.target, flags.duration, flags.fronters_only, flags.flat)),
Commands.SystemDisplayId(var param, _) => ctx.Execute<System>(SystemId, m => m.DisplayId(ctx, param.target)),
Commands.SystemDisplayIdSelf => ctx.Execute<System>(SystemId, m => m.DisplayId(ctx, ctx.System)),
Commands.SystemWebhook => ctx.Execute<Api>(null, m => m.SystemWebhook(ctx)),
Commands.SystemWebhookShow => ctx.Execute<Api>(null, m => m.GetSystemWebhook(ctx)),
Commands.SystemWebhookClear(_, var flags) => ctx.Execute<Api>(null, m => m.ClearSystemWebhook(ctx, flags.yes)),
Commands.SystemWebhookSet(var param, _) => ctx.Execute<Api>(null, m => m.SetSystemWebhook(ctx, param.url)),
Commands.RandomSelf(_, var flags) =>
flags.group
? ctx.Execute<Random>(GroupRandom, m => m.Group(ctx, ctx.System, flags.all, flags.show_embed))
@ -224,21 +226,21 @@ public partial class CommandTree
: ctx.Execute<Random>(MemberRandom, m => m.Member(ctx, param.target, flags.all, flags.show_embed)),
Commands.GroupRandomMember(var param, var flags) => ctx.Execute<Random>(GroupMemberRandom, m => m.GroupMember(ctx, param.target, flags)),
Commands.SystemLink(var param, _) => ctx.Execute<SystemLink>(Link, m => m.LinkSystem(ctx, param.account)),
Commands.SystemUnlink(var param, _) => ctx.Execute<SystemLink>(Unlink, m => m.UnlinkAccount(ctx, param.account)),
Commands.SystemUnlink(var param, var flags) => ctx.Execute<SystemLink>(Unlink, m => m.UnlinkAccount(ctx, param.account, flags.yes)),
Commands.SystemMembersListSelf(var param, var flags) => ctx.Execute<SystemList>(SystemList, m => m.MemberList(ctx, ctx.System, null, flags)),
Commands.SystemMembersSearchSelf(var param, var flags) => ctx.Execute<SystemList>(SystemFind, m => m.MemberList(ctx, ctx.System, param.query, flags)),
Commands.SystemMembersList(var param, var flags) => ctx.Execute<SystemList>(SystemList, m => m.MemberList(ctx, param.target, null, flags)),
Commands.SystemMembersSearch(var param, var flags) => ctx.Execute<SystemList>(SystemFind, m => m.MemberList(ctx, param.target, param.query, flags)),
Commands.MemberListGroups(var param, var flags) => ctx.Execute<GroupMember>(MemberGroups, m => m.ListMemberGroups(ctx, param.target, null, flags)),
Commands.MemberSearchGroups(var param, var flags) => ctx.Execute<GroupMember>(MemberGroups, m => m.ListMemberGroups(ctx, param.target, param.query, flags)),
Commands.MemberListGroups(var param, var flags) => ctx.Execute<GroupMember>(MemberGroups, m => m.ListMemberGroups(ctx, param.target, null, flags, flags.all)),
Commands.MemberSearchGroups(var param, var flags) => ctx.Execute<GroupMember>(MemberGroups, m => m.ListMemberGroups(ctx, param.target, param.query, flags, flags.all)),
Commands.GroupListMembers(var param, var flags) => ctx.Execute<GroupMember>(GroupMemberList, m => m.ListGroupMembers(ctx, param.target, null, flags)),
Commands.GroupSearchMembers(var param, var flags) => ctx.Execute<GroupMember>(GroupMemberList, m => m.ListGroupMembers(ctx, param.target, param.query, flags)),
Commands.SystemListGroups(var param, var flags) => ctx.Execute<Groups>(GroupList, g => g.ListSystemGroups(ctx, param.target, null, flags)),
Commands.SystemSearchGroups(var param, var flags) => ctx.Execute<Groups>(GroupList, g => g.ListSystemGroups(ctx, param.target, param.query, flags)),
Commands.GroupListGroups(var param, var flags) => ctx.Execute<Groups>(GroupList, g => g.ListSystemGroups(ctx, ctx.System, null, flags)),
Commands.GroupSearchGroups(var param, var flags) => ctx.Execute<Groups>(GroupList, g => g.ListSystemGroups(ctx, ctx.System, param.query, flags)),
Commands.SystemListGroups(var param, var flags) => ctx.Execute<Groups>(GroupList, g => g.ListSystemGroups(ctx, param.target, null, flags, flags.all)),
Commands.SystemSearchGroups(var param, var flags) => ctx.Execute<Groups>(GroupList, g => g.ListSystemGroups(ctx, param.target, param.query, flags, flags.all)),
Commands.GroupListGroups(var param, var flags) => ctx.Execute<Groups>(GroupList, g => g.ListSystemGroups(ctx, ctx.System, null, flags, flags.all)),
Commands.GroupSearchGroups(var param, var flags) => ctx.Execute<Groups>(GroupList, g => g.ListSystemGroups(ctx, ctx.System, param.query, flags, flags.all)),
Commands.GroupNew(var param, _) => ctx.Execute<Groups>(GroupNew, g => g.CreateGroup(ctx, param.name)),
Commands.GroupInfo(var param, _) => ctx.Execute<Groups>(GroupInfo, g => g.ShowGroupCard(ctx, param.target)),
Commands.GroupInfo(var param, var flags) => ctx.Execute<Groups>(GroupInfo, g => g.ShowGroupCard(ctx, param.target, flags.show_embed, flags.all)),
Commands.GroupShowName(var param, var flags) => ctx.Execute<Groups>(GroupRename, g => g.ShowGroupDisplayName(ctx, param.target, flags.GetReplyFormat())),
Commands.GroupClearName(var param, var flags) => ctx.Execute<Groups>(GroupRename, g => g.RenameGroup(ctx, param.target, null)),
Commands.GroupRename(var param, _) => ctx.Execute<Groups>(GroupRename, g => g.RenameGroup(ctx, param.target, param.name)),
@ -249,16 +251,16 @@ public partial class CommandTree
Commands.GroupClearDescription(var param, var flags) => ctx.Execute<Groups>(GroupDesc, g => g.ClearGroupDescription(ctx, param.target)),
Commands.GroupChangeDescription(var param, _) => ctx.Execute<Groups>(GroupDesc, g => g.ChangeGroupDescription(ctx, param.target, param.description)),
Commands.GroupShowIcon(var param, var flags) => ctx.Execute<Groups>(GroupIcon, g => g.ShowGroupIcon(ctx, param.target, flags.GetReplyFormat())),
Commands.GroupClearIcon(var param, var flags) => ctx.Execute<Groups>(GroupIcon, g => g.ClearGroupIcon(ctx, param.target)),
Commands.GroupClearIcon(var param, var flags) => ctx.Execute<Groups>(GroupIcon, g => g.ClearGroupIcon(ctx, param.target, flags.yes)),
Commands.GroupChangeIcon(var param, _) => ctx.Execute<Groups>(GroupIcon, g => g.ChangeGroupIcon(ctx, param.target, param.icon)),
Commands.GroupShowBanner(var param, var flags) => ctx.Execute<Groups>(GroupBannerImage, g => g.ShowGroupBanner(ctx, param.target, flags.GetReplyFormat())),
Commands.GroupClearBanner(var param, var flags) => ctx.Execute<Groups>(GroupBannerImage, g => g.ClearGroupBanner(ctx, param.target)),
Commands.GroupClearBanner(var param, var flags) => ctx.Execute<Groups>(GroupBannerImage, g => g.ClearGroupBanner(ctx, param.target, flags.yes)),
Commands.GroupChangeBanner(var param, _) => ctx.Execute<Groups>(GroupBannerImage, g => g.ChangeGroupBanner(ctx, param.target, param.banner)),
Commands.GroupShowColor(var param, var flags) => ctx.Execute<Groups>(GroupColor, g => g.ShowGroupColor(ctx, param.target, flags.GetReplyFormat())),
Commands.GroupClearColor(var param, var flags) => ctx.Execute<Groups>(GroupColor, g => g.ClearGroupColor(ctx, param.target)),
Commands.GroupChangeColor(var param, _) => ctx.Execute<Groups>(GroupColor, g => g.ChangeGroupColor(ctx, param.target, param.color)),
Commands.GroupAddMember(var param, var flags) => ctx.Execute<GroupMember>(GroupAdd, g => g.AddRemoveMembers(ctx, param.target, param.targets, Groups.AddRemoveOperation.Add, flags.all)),
Commands.GroupRemoveMember(var param, var flags) => ctx.Execute<GroupMember>(GroupRemove, g => g.AddRemoveMembers(ctx, param.target, param.targets, Groups.AddRemoveOperation.Remove, flags.all)),
Commands.GroupAddMember(var param, var flags) => ctx.Execute<GroupMember>(GroupAdd, g => g.AddRemoveMembers(ctx, param.target, param.targets, Groups.AddRemoveOperation.Add, flags.all, flags.yes)),
Commands.GroupRemoveMember(var param, var flags) => ctx.Execute<GroupMember>(GroupRemove, g => g.AddRemoveMembers(ctx, param.target, param.targets, Groups.AddRemoveOperation.Remove, flags.all, flags.yes)),
Commands.GroupShowPrivacy(var param, _) => ctx.Execute<Groups>(GroupPrivacy, g => g.ShowGroupPrivacy(ctx, param.target)),
Commands.GroupChangePrivacyAll(var param, _) => ctx.Execute<Groups>(GroupPrivacy, g => g.SetAllGroupPrivacy(ctx, param.target, param.level)),
Commands.GroupChangePrivacy(var param, _) => ctx.Execute<Groups>(GroupPrivacy, g => g.SetGroupPrivacy(ctx, param.target, param.privacy, param.level)),
@ -282,12 +284,12 @@ public partial class CommandTree
Commands.MessageDelete(var param, var flags) => ctx.Execute<ProxiedMessage>(Message, m => m.GetMessage(ctx, param.target.MessageId, flags.GetReplyFormat(), true, false)),
Commands.MessageEdit(var param, var flags) => ctx.Execute<ProxiedMessage>(MessageEdit, m => m.EditMessage(ctx, param.target.MessageId, param.new_content, flags.regex, flags.mutate_space, flags.append, flags.prepend, flags.clear_embeds, flags.clear_attachments)),
Commands.MessageReproxy(var param, _) => ctx.Execute<ProxiedMessage>(MessageReproxy, m => m.ReproxyMessage(ctx, param.msg.MessageId, param.member)),
Commands.Import(var param, _) => ctx.Execute<ImportExport>(Import, m => m.Import(ctx, param.url)),
Commands.Import(var param, var flags) => ctx.Execute<ImportExport>(Import, m => m.Import(ctx, param.url, flags.yes)),
Commands.Export(_, _) => ctx.Execute<ImportExport>(Export, m => m.Export(ctx)),
Commands.ServerConfigShow => ctx.Execute<ServerConfig>(null, m => m.ShowConfig(ctx)),
Commands.ServerConfigLogChannelShow => ctx.Execute<ServerConfig>(null, m => m.ShowLogChannel(ctx)),
Commands.ServerConfigLogChannelSet(var param, _) => ctx.Execute<ServerConfig>(null, m => m.SetLogChannel(ctx, param.channel)),
Commands.ServerConfigLogChannelClear => ctx.Execute<ServerConfig>(null, m => m.ClearLogChannel(ctx)),
Commands.ServerConfigLogChannelClear(_, var flags) => ctx.Execute<ServerConfig>(null, m => m.ClearLogChannel(ctx, flags.yes)),
Commands.ServerConfigLogCleanupShow => ctx.Execute<ServerConfig>(null, m => m.ShowLogCleanup(ctx)),
Commands.ServerConfigLogCleanupSet(var param, _) => ctx.Execute<ServerConfig>(null, m => m.SetLogCleanup(ctx, param.toggle)),
Commands.ServerConfigLogBlacklistShow => ctx.Execute<ServerConfig>(null, m => m.ShowLogBlacklist(ctx)),
@ -302,27 +304,27 @@ public partial class CommandTree
Commands.ServerConfigRequireSystemTagSet(var param, _) => ctx.Execute<ServerConfig>(null, m => m.SetRequireSystemTag(ctx, param.toggle)),
Commands.ServerConfigSuppressNotificationsShow => ctx.Execute<ServerConfig>(null, m => m.ShowSuppressNotifications(ctx)),
Commands.ServerConfigSuppressNotificationsSet(var param, _) => ctx.Execute<ServerConfig>(null, m => m.SetSuppressNotifications(ctx, param.toggle)),
Commands.AdminUpdateSystemId(var param, _) => ctx.Execute<Admin>(null, m => m.UpdateSystemId(ctx, param.target, param.new_hid)),
Commands.AdminUpdateMemberId(var param, _) => ctx.Execute<Admin>(null, m => m.UpdateMemberId(ctx, param.target, param.new_hid)),
Commands.AdminUpdateGroupId(var param, _) => ctx.Execute<Admin>(null, m => m.UpdateGroupId(ctx, param.target, param.new_hid)),
Commands.AdminRerollSystemId(var param, _) => ctx.Execute<Admin>(null, m => m.RerollSystemId(ctx, param.target)),
Commands.AdminRerollMemberId(var param, _) => ctx.Execute<Admin>(null, m => m.RerollMemberId(ctx, param.target)),
Commands.AdminRerollGroupId(var param, _) => ctx.Execute<Admin>(null, m => m.RerollGroupId(ctx, param.target)),
Commands.AdminSystemMemberLimit(var param, _) => ctx.Execute<Admin>(null, m => m.SystemMemberLimit(ctx, param.target, param.limit)),
Commands.AdminSystemGroupLimit(var param, _) => ctx.Execute<Admin>(null, m => m.SystemGroupLimit(ctx, param.target, param.limit)),
Commands.AdminSystemRecover(var param, var flags) => ctx.Execute<Admin>(null, m => m.SystemRecover(ctx, param.token, param.account, flags.reroll_token)),
Commands.AdminUpdateSystemId(var param, var flags) => ctx.Execute<Admin>(null, m => m.UpdateSystemId(ctx, param.target, param.new_hid, flags.yes)),
Commands.AdminUpdateMemberId(var param, var flags) => ctx.Execute<Admin>(null, m => m.UpdateMemberId(ctx, param.target, param.new_hid, flags.yes)),
Commands.AdminUpdateGroupId(var param, var flags) => ctx.Execute<Admin>(null, m => m.UpdateGroupId(ctx, param.target, param.new_hid, flags.yes)),
Commands.AdminRerollSystemId(var param, var flags) => ctx.Execute<Admin>(null, m => m.RerollSystemId(ctx, param.target, flags.yes)),
Commands.AdminRerollMemberId(var param, var flags) => ctx.Execute<Admin>(null, m => m.RerollMemberId(ctx, param.target, flags.yes)),
Commands.AdminRerollGroupId(var param, var flags) => ctx.Execute<Admin>(null, m => m.RerollGroupId(ctx, param.target, flags.yes)),
Commands.AdminSystemMemberLimit(var param, var flags) => ctx.Execute<Admin>(null, m => m.SystemMemberLimit(ctx, param.target, param.limit, flags.yes)),
Commands.AdminSystemGroupLimit(var param, var flags) => ctx.Execute<Admin>(null, m => m.SystemGroupLimit(ctx, param.target, param.limit, flags.yes)),
Commands.AdminSystemRecover(var param, var flags) => ctx.Execute<Admin>(null, m => m.SystemRecover(ctx, param.token, param.account, flags.reroll_token, flags.yes)),
Commands.AdminSystemDelete(var param, _) => ctx.Execute<Admin>(null, m => m.SystemDelete(ctx, param.target)),
Commands.AdminSendMessage(var param, _) => ctx.Execute<Admin>(null, m => m.SendAdminMessage(ctx, param.account, param.content)),
Commands.AdminAbuselogCreate(var param, var flags) => ctx.Execute<Admin>(null, m => m.AbuseLogCreate(ctx, param.account, flags.deny_boy_usage, param.description)),
Commands.AdminAbuselogShowAccount(var param, _) => ctx.Execute<Admin>(null, m => m.AbuseLogShow(ctx, param.account, null)),
Commands.AdminAbuselogFlagDenyAccount(var param, _) => ctx.Execute<Admin>(null, m => m.AbuseLogFlagDeny(ctx, param.account, null, param.value)),
Commands.AdminAbuselogDescriptionAccount(var param, var flags) => ctx.Execute<Admin>(null, m => m.AbuseLogDescription(ctx, param.account, null, param.desc, flags.clear)),
Commands.AdminAbuselogDescriptionAccount(var param, var flags) => ctx.Execute<Admin>(null, m => m.AbuseLogDescription(ctx, param.account, null, param.desc, flags.clear, flags.yes)),
Commands.AdminAbuselogAddUserAccount(var param, _) => ctx.Execute<Admin>(null, m => m.AbuseLogAddUser(ctx, param.account, null, ctx.Author)),
Commands.AdminAbuselogRemoveUserAccount(var param, _) => ctx.Execute<Admin>(null, m => m.AbuseLogRemoveUser(ctx, param.account, null, ctx.Author)),
Commands.AdminAbuselogDeleteAccount(var param, _) => ctx.Execute<Admin>(null, m => m.AbuseLogDelete(ctx, param.account, null)),
Commands.AdminAbuselogShowLogId(var param, _) => ctx.Execute<Admin>(null, m => m.AbuseLogShow(ctx, null, param.log_id)),
Commands.AdminAbuselogFlagDenyLogId(var param, _) => ctx.Execute<Admin>(null, m => m.AbuseLogFlagDeny(ctx, null, param.log_id, param.value)),
Commands.AdminAbuselogDescriptionLogId(var param, var flags) => ctx.Execute<Admin>(null, m => m.AbuseLogDescription(ctx, null, param.log_id, param.desc, flags.clear)),
Commands.AdminAbuselogDescriptionLogId(var param, var flags) => ctx.Execute<Admin>(null, m => m.AbuseLogDescription(ctx, null, param.log_id, param.desc, flags.clear, flags.yes)),
Commands.AdminAbuselogAddUserLogId(var param, _) => ctx.Execute<Admin>(null, m => m.AbuseLogAddUser(ctx, null, param.log_id, ctx.Author)),
Commands.AdminAbuselogRemoveUserLogId(var param, _) => ctx.Execute<Admin>(null, m => m.AbuseLogRemoveUser(ctx, null, param.log_id, ctx.Author)),
Commands.AdminAbuselogDeleteLogId(var param, _) => ctx.Execute<Admin>(null, m => m.AbuseLogDelete(ctx, null, param.log_id)),

View file

@ -2,110 +2,10 @@ using System.Text.RegularExpressions;
using Myriad.Types;
using PluralKit.Core;
namespace PluralKit.Bot;
public static class ContextArgumentsExt
{
public static string PopArgument(this Context ctx) => throw new PKError("todo: PopArgument");
public static string PeekArgument(this Context ctx) => throw new PKError("todo: PeekArgument");
public static string RemainderOrNull(this Context ctx, bool skipFlags = true) => throw new PKError("todo: RemainderOrNull");
public static bool HasNext(this Context ctx, bool skipFlags = true) => throw new PKError("todo: HasNext");
public static string FullCommand(this Context ctx) => throw new PKError("todo: FullCommand");
/// <summary>
/// Checks if the next parameter is equal to one of the given keywords and pops it from the stack. Case-insensitive.
/// </summary>
public static bool Match(this Context ctx, ref string used, params string[] potentialMatches)
{
var arg = ctx.PeekArgument();
foreach (var match in potentialMatches)
if (arg.Equals(match, StringComparison.InvariantCultureIgnoreCase))
{
used = ctx.PopArgument();
return true;
}
return false;
}
/// <summary>
/// Checks if the next parameter is equal to one of the given keywords. Case-insensitive.
/// </summary>
public static bool Match(this Context ctx, params string[] potentialMatches)
{
string used = null; // Unused and unreturned, we just yeet it
return ctx.Match(ref used, potentialMatches);
}
/// <summary>
/// Checks if the next parameter (starting from `ptr`) is equal to one of the given keywords, and leaves it on the stack. Case-insensitive.
/// </summary>
public static bool PeekMatch(this Context ctx, ref int ptr, string[] potentialMatches)
{
throw new PKError("todo: PeekMatch");
}
/// <summary>
/// Matches the next *n* parameters against each parameter consecutively.
/// <br />
/// Note that this is handled differently than single-parameter Match:
/// each method parameter is an array of potential matches for the *n*th command string parameter.
/// </summary>
public static bool MatchMultiple(this Context ctx, params string[][] potentialParametersMatches)
{
throw new PKError("todo: MatchMultiple");
}
public static bool MatchFlag(this Context ctx, params string[] potentialMatches)
{
// Flags are *ALWAYS PARSED LOWERCASE*. This means we skip out on a "ToLower" call here.
// Can assume the caller array only contains lowercase *and* the set below only contains lowercase
throw new NotImplementedException();
}
public static bool MatchClear(this Context ctx)
=> ctx.Match("clear", "reset", "default") || ctx.MatchFlag("c", "clear");
public static ReplyFormat MatchFormat(this Context ctx)
{
if (ctx.Match("r", "raw") || ctx.MatchFlag("r", "raw")) return ReplyFormat.Raw;
if (ctx.Match("pt", "plaintext") || ctx.MatchFlag("pt", "plaintext")) return ReplyFormat.Plaintext;
return ReplyFormat.Standard;
}
public static ReplyFormat PeekMatchFormat(this Context ctx)
{
throw new PKError("todo: PeekMatchFormat");
}
public static bool MatchToggle(this Context ctx, bool? defaultValue = null)
{
var value = ctx.MatchToggleOrNull(defaultValue);
if (value == null) throw new PKError("You must pass either \"on\" or \"off\" to this command.");
return value.Value;
}
public static bool? MatchToggleOrNull(this Context ctx, bool? defaultValue = null)
{
if (defaultValue != null && ctx.MatchClear())
return defaultValue.Value;
var yesToggles = new[] { "yes", "on", "enable", "enabled", "true" };
var noToggles = new[] { "no", "off", "disable", "disabled", "false" };
if (ctx.Match(yesToggles) || ctx.MatchFlag(yesToggles))
return true;
else if (ctx.Match(noToggles) || ctx.MatchFlag(noToggles))
return false;
else return null;
}
public static (ulong? messageId, ulong? channelId) GetRepliedTo(this Context ctx)
{
if (ctx.Message.Type == Message.MessageType.Reply && ctx.Message.MessageReference?.MessageId != null)

View file

@ -48,10 +48,6 @@ public static class ContextAvatarExt
// ToString URL-decodes, which breaks URLs to spaces; AbsoluteUri doesn't
return new ParsedImage { Url = uri.AbsoluteUri, Source = AvatarSource.Url };
}
public static async Task<ParsedImage?> MatchImage(this Context ctx)
{
throw new NotImplementedException();
}
}
public struct ParsedImage

View file

@ -1,9 +1,6 @@
using System.Text.RegularExpressions;
using Myriad.Extensions;
using Myriad.Types;
using PluralKit.Bot.Utils;
using PluralKit.Core;
namespace PluralKit.Bot;
@ -120,23 +117,4 @@ public static class ContextEntityArgumentsExt
return $"{entity} with ID or name \"{input}\" not found.";
return $"{entity} with name \"{input}\" not found. Note that a {entity.ToLower()} ID is 5 or 6 characters long.";
}
public static async Task<Channel> MatchChannel(this Context ctx)
{
if (!MentionUtils.TryParseChannel(ctx.PeekArgument(), out var id))
return null;
// todo: match channels in other guilds
var channel = await ctx.Cache.TryGetChannel(ctx.Guild!.Id, id);
if (channel == null)
channel = await ctx.Rest.GetChannelOrNull(id);
if (channel == null)
return null;
if (!DiscordUtils.IsValidGuildChannel(channel))
return null;
ctx.PopArgument();
return channel;
}
}

View file

@ -1,51 +0,0 @@
using PluralKit.Core;
namespace PluralKit.Bot;
public static class ContextPrivacyExt
{
public static PrivacyLevel PopPrivacyLevel(this Context ctx)
{
if (ctx.Match("public", "pub", "show", "shown", "visible", "unhide", "unhidden"))
return PrivacyLevel.Public;
if (ctx.Match("private", "priv", "hide", "hidden"))
return PrivacyLevel.Private;
if (!ctx.HasNext())
throw new PKSyntaxError("You must pass a privacy level (`public` or `private`)");
throw new PKSyntaxError(
$"Invalid privacy level {ctx.PopArgument().AsCode()} (must be `public` or `private`).");
}
public static SystemPrivacySubject PopSystemPrivacySubject(this Context ctx)
{
if (!SystemPrivacyUtils.TryParseSystemPrivacy(ctx.PeekArgument(), out var subject))
throw new PKSyntaxError(
$"Invalid privacy subject {ctx.PopArgument().AsCode()} (must be `description`, `members`, `front`, `fronthistory`, `groups`, or `all`).");
ctx.PopArgument();
return subject;
}
public static MemberPrivacySubject PopMemberPrivacySubject(this Context ctx)
{
if (!MemberPrivacyUtils.TryParseMemberPrivacy(ctx.PeekArgument(), out var subject))
throw new PKSyntaxError(
$"Invalid privacy subject {ctx.PopArgument().AsCode()} (must be `name`, `description`, `avatar`, `birthday`, `pronouns`, `proxy`, `metadata`, `visibility`, or `all`).");
ctx.PopArgument();
return subject;
}
public static GroupPrivacySubject PopGroupPrivacySubject(this Context ctx)
{
if (!GroupPrivacyUtils.TryParseGroupPrivacy(ctx.PeekArgument(), out var subject))
throw new PKSyntaxError(
$"Invalid privacy subject {ctx.PopArgument().AsCode()} (must be `name`, `description`, `icon`, `metadata`, `visibility`, or `all`).");
ctx.PopArgument();
return subject;
}
}

View file

@ -72,7 +72,7 @@ public class Parameters
private async Task<Parameter?> ResolveFfiParam(Context ctx, uniffi.commands.Parameter ffi_param)
{
var byId = HasFlag("id", "by-id");
var byId = HasFlag("id", "by-id"); // this is added as a hidden flag to all command definitions
switch (ffi_param)
{
case uniffi.commands.Parameter.MemberRef memberRef:

View file

@ -111,7 +111,7 @@ public class Admin
return eb.Build();
}
public async Task UpdateSystemId(Context ctx, PKSystem target, string newHid)
public async Task UpdateSystemId(Context ctx, PKSystem target, string newHid, bool confirmYes)
{
ctx.AssertBotAdmin();
@ -121,14 +121,14 @@ public class Admin
await ctx.Reply(null, await CreateEmbed(ctx, target));
if (!await ctx.PromptYesNo($"Change system ID of `{target.Hid}` to `{newHid}`?", "Change"))
if (!await ctx.PromptYesNo($"Change system ID of `{target.Hid}` to `{newHid}`?", "Change", flagValue: confirmYes))
throw new PKError("ID change cancelled.");
await ctx.Repository.UpdateSystem(target.Id, new SystemPatch { Hid = newHid });
await ctx.Reply($"{Emojis.Success} System ID updated (`{target.Hid}` -> `{newHid}`).");
}
public async Task UpdateMemberId(Context ctx, PKMember target, string newHid)
public async Task UpdateMemberId(Context ctx, PKMember target, string newHid, bool confirmYes)
{
ctx.AssertBotAdmin();
@ -141,7 +141,7 @@ public class Admin
if (!await ctx.PromptYesNo(
$"Change member ID of **{target.NameFor(LookupContext.ByNonOwner)}** (`{target.Hid}`) to `{newHid}`?",
"Change"
"Change", flagValue: confirmYes
))
throw new PKError("ID change cancelled.");
@ -149,7 +149,7 @@ public class Admin
await ctx.Reply($"{Emojis.Success} Member ID updated (`{target.Hid}` -> `{newHid}`).");
}
public async Task UpdateGroupId(Context ctx, PKGroup target, string newHid)
public async Task UpdateGroupId(Context ctx, PKGroup target, string newHid, bool confirmYes)
{
ctx.AssertBotAdmin();
@ -161,7 +161,7 @@ public class Admin
await ctx.Reply(null, await CreateEmbed(ctx, system));
if (!await ctx.PromptYesNo($"Change group ID of **{target.Name}** (`{target.Hid}`) to `{newHid}`?",
"Change"
"Change", flagValue: confirmYes
))
throw new PKError("ID change cancelled.");
@ -169,13 +169,13 @@ public class Admin
await ctx.Reply($"{Emojis.Success} Group ID updated (`{target.Hid}` -> `{newHid}`).");
}
public async Task RerollSystemId(Context ctx, PKSystem target)
public async Task RerollSystemId(Context ctx, PKSystem target, bool confirmYes)
{
ctx.AssertBotAdmin();
await ctx.Reply(null, await CreateEmbed(ctx, target));
if (!await ctx.PromptYesNo($"Reroll system ID `{target.Hid}`?", "Reroll"))
if (!await ctx.PromptYesNo($"Reroll system ID `{target.Hid}`?", "Reroll", flagValue: confirmYes))
throw new PKError("ID change cancelled.");
var query = new Query("systems").AsUpdate(new
@ -188,7 +188,7 @@ public class Admin
await ctx.Reply($"{Emojis.Success} System ID updated (`{target.Hid}` -> `{newHid}`).");
}
public async Task RerollMemberId(Context ctx, PKMember target)
public async Task RerollMemberId(Context ctx, PKMember target, bool confirmYes)
{
ctx.AssertBotAdmin();
@ -197,7 +197,7 @@ public class Admin
if (!await ctx.PromptYesNo(
$"Reroll member ID for **{target.NameFor(LookupContext.ByNonOwner)}** (`{target.Hid}`)?",
"Reroll"
"Reroll", flagValue: confirmYes
))
throw new PKError("ID change cancelled.");
@ -211,7 +211,7 @@ public class Admin
await ctx.Reply($"{Emojis.Success} Member ID updated (`{target.Hid}` -> `{newHid}`).");
}
public async Task RerollGroupId(Context ctx, PKGroup target)
public async Task RerollGroupId(Context ctx, PKGroup target, bool confirmYes)
{
ctx.AssertBotAdmin();
@ -219,7 +219,7 @@ public class Admin
await ctx.Reply(null, await CreateEmbed(ctx, system));
if (!await ctx.PromptYesNo($"Reroll group ID for **{target.Name}** (`{target.Hid}`)?",
"Change"
"Change", flagValue: confirmYes
))
throw new PKError("ID change cancelled.");
@ -233,7 +233,7 @@ public class Admin
await ctx.Reply($"{Emojis.Success} Group ID updated (`{target.Hid}` -> `{newHid}`).");
}
public async Task SystemMemberLimit(Context ctx, PKSystem target, int? newLimit)
public async Task SystemMemberLimit(Context ctx, PKSystem target, int? newLimit, bool confirmYes)
{
ctx.AssertBotAdmin();
@ -247,14 +247,14 @@ public class Admin
}
await ctx.Reply(null, await CreateEmbed(ctx, target));
if (!await ctx.PromptYesNo($"Update member limit from **{currentLimit}** to **{newLimit}**?", "Update"))
if (!await ctx.PromptYesNo($"Update member limit from **{currentLimit}** to **{newLimit}**?", "Update", flagValue: confirmYes))
throw new PKError("Member limit change cancelled.");
await ctx.Repository.UpdateSystemConfig(target.Id, new SystemConfigPatch { MemberLimitOverride = newLimit });
await ctx.Reply($"{Emojis.Success} Member limit updated.");
}
public async Task SystemGroupLimit(Context ctx, PKSystem target, int? newLimit)
public async Task SystemGroupLimit(Context ctx, PKSystem target, int? newLimit, bool confirmYes)
{
ctx.AssertBotAdmin();
@ -268,14 +268,14 @@ public class Admin
}
await ctx.Reply(null, await CreateEmbed(ctx, target));
if (!await ctx.PromptYesNo($"Update group limit from **{currentLimit}** to **{newLimit}**?", "Update"))
if (!await ctx.PromptYesNo($"Update group limit from **{currentLimit}** to **{newLimit}**?", "Update", flagValue: confirmYes))
throw new PKError("Group limit change cancelled.");
await ctx.Repository.UpdateSystemConfig(target.Id, new SystemConfigPatch { GroupLimitOverride = newLimit });
await ctx.Reply($"{Emojis.Success} Group limit updated.");
}
public async Task SystemRecover(Context ctx, string systemToken, User account, bool rerollToken)
public async Task SystemRecover(Context ctx, string systemToken, User account, bool rerollToken, bool confirmYes)
{
ctx.AssertBotAdmin();
@ -294,7 +294,7 @@ public class Admin
var system = await ctx.Repository.GetSystem(systemId.Value!);
await ctx.Reply(null, await CreateEmbed(ctx, system));
if (!await ctx.PromptYesNo($"Associate account {account.NameAndMention()} with system `{system.Hid}`?", "Recover account"))
if (!await ctx.PromptYesNo($"Associate account {account.NameAndMention()} with system `{system.Hid}`?", "Recover account", flagValue: confirmYes))
throw new PKError("System recovery cancelled.");
await ctx.Repository.AddAccount(system.Id, account.Id);
@ -402,7 +402,7 @@ public class Admin
}
}
public async Task AbuseLogDescription(Context ctx, User? account, string? id, string? description, bool clear)
public async Task AbuseLogDescription(Context ctx, User? account, string? id, string? description, bool clear, bool confirmClear)
{
ctx.AssertBotAdmin();
@ -410,7 +410,7 @@ public class Admin
if (abuseLog == null)
return;
if (clear && await ctx.ConfirmClear("this abuse log description"))
if (clear && await ctx.ConfirmClear("this abuse log description", confirmClear))
{
await ctx.Repository.UpdateAbuseLog(abuseLog.Id, new AbuseLogPatch { Description = null });
await ctx.Reply($"{Emojis.Success} Abuse log description cleared.");

View file

@ -115,28 +115,32 @@ public class Api
}
}
public async Task SystemWebhook(Context ctx)
public async Task GetSystemWebhook(Context ctx)
{
ctx.CheckSystem().CheckDMContext();
if (!ctx.HasNext(false))
{
if (ctx.System.WebhookUrl == null)
await ctx.Reply($"Your system does not have a webhook URL set. Set one with `{ctx.DefaultPrefix}system webhook <url>`!");
else
await ctx.Reply($"Your system's webhook URL is <{ctx.System.WebhookUrl}>.");
if (ctx.System.WebhookUrl == null)
await ctx.Reply($"Your system does not have a webhook URL set. Set one with `{ctx.DefaultPrefix}system webhook <url>`!");
else
await ctx.Reply($"Your system's webhook URL is <{ctx.System.WebhookUrl}>.");
}
public async Task ClearSystemWebhook(Context ctx, bool confirmYes)
{
ctx.CheckSystem().CheckDMContext();
if (!await ctx.ConfirmClear("your system's webhook URL", confirmYes))
return;
}
if (ctx.MatchClear() && await ctx.ConfirmClear("your system's webhook URL"))
{
await ctx.Repository.UpdateSystem(ctx.System.Id, new SystemPatch { WebhookUrl = null, WebhookToken = null });
await ctx.Repository.UpdateSystem(ctx.System.Id, new SystemPatch { WebhookUrl = null, WebhookToken = null });
await ctx.Reply($"{Emojis.Success} System webhook URL removed.");
return;
}
await ctx.Reply($"{Emojis.Success} System webhook URL removed.");
}
public async Task SetSystemWebhook(Context ctx, string newUrl)
{
ctx.CheckSystem().CheckDMContext();
var newUrl = ctx.RemainderOrNull();
if (!await DispatchExt.ValidateUri(newUrl))
throw new PKError($"The URL {newUrl.AsCode()} is invalid or I cannot access it. Are you sure this is a valid, publicly accessible URL?");

View file

@ -290,7 +290,7 @@ public class Config
await ctx.Reply($"{Emojis.Success} System time zone cleared (set to UTC).");
}
public async Task EditSystemTimezone(Context ctx, string zoneStr)
public async Task EditSystemTimezone(Context ctx, string zoneStr, bool confirmYes = false)
{
if (ctx.System == null) throw Errors.NoSystemError(ctx.DefaultPrefix);
@ -299,7 +299,7 @@ public class Config
var currentTime = SystemClock.Instance.GetCurrentInstant().InZone(zone);
var msg = $"This will change the system time zone to **{zone.Id}**. The current time is **{currentTime.FormatZoned()}**. Is this correct?";
if (!await ctx.PromptYesNo(msg, "Change Timezone")) throw Errors.TimezoneChangeCancelled;
if (!await ctx.PromptYesNo(msg, "Change Timezone", flagValue: confirmYes)) throw Errors.TimezoneChangeCancelled;
await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { UiTz = zone.Id });

View file

@ -37,20 +37,16 @@ public class Fun
public Task Meow(Context ctx) =>
ctx.Reply("*mrrp :3*");
public Task Error(Context ctx)
{
if (ctx.Match("message"))
return ctx.Reply("> **Error code:** `50f3c7b439d111ecab2023a5431fffbd`", new EmbedBuilder()
.Color(0xE74C3C)
.Title("Internal error occurred")
.Description(
"For support, please send the error code above in **#bug-reports-and-errors** on **[the support server *(click to join)*](https://discord.gg/PczBt78)** with a description of what you were doing at the time.")
.Footer(new Embed.EmbedFooter("50f3c7b439d111ecab2023a5431fffbd"))
.Timestamp(SystemClock.Instance.GetCurrentInstant().ToDateTimeOffset().ToString("O"))
.Build()
);
public Task ErrorMessage(Context ctx) => ctx.Reply("> **Error code:** `50f3c7b439d111ecab2023a5431fffbd`", new EmbedBuilder()
.Color(0xE74C3C)
.Title("Internal error occurred")
.Description(
"For support, please send the error code above in **#bug-reports-and-errors** on **[the support server *(click to join)*](https://discord.gg/PczBt78)** with a description of what you were doing at the time.")
.Footer(new Embed.EmbedFooter("50f3c7b439d111ecab2023a5431fffbd"))
.Timestamp(SystemClock.Instance.GetCurrentInstant().ToDateTimeOffset().ToString("O"))
.Build()
);
return ctx.Reply(
$"{Emojis.Error} Unknown command {"error".AsCode()}. For a list of possible commands, see <https://pluralkit.me/commands>.");
}
public Task Error(Context ctx) => ctx.Reply(
$"{Emojis.Error} Unknown command {"error".AsCode()}. For a list of possible commands, see <https://pluralkit.me/commands>.");
}

View file

@ -51,7 +51,7 @@ public class GroupMember
groups.Count - toAction.Count));
}
public async Task ListMemberGroups(Context ctx, PKMember target, string? query, IHasListOptions flags)
public async Task ListMemberGroups(Context ctx, PKMember target, string? query, IHasListOptions flags, bool all)
{
var targetSystem = await ctx.Repository.GetSystem(target.System);
var opts = flags.GetListOptions(ctx, target.System);
@ -80,10 +80,10 @@ public class GroupMember
title.Append($" matching **{opts.Search.Truncate(100)}**");
await ctx.RenderGroupList(ctx.LookupContextFor(target.System), target.System, title.ToString(),
target.Color, opts);
target.Color, opts, all);
}
public async Task AddRemoveMembers(Context ctx, PKGroup target, List<PKMember> _members, Groups.AddRemoveOperation op, bool all)
public async Task AddRemoveMembers(Context ctx, PKGroup target, List<PKMember> _members, Groups.AddRemoveOperation op, bool all, bool confirmYes)
{
ctx.CheckOwnGroup(target);
@ -126,7 +126,7 @@ public class GroupMember
.Where(m => existingMembersInGroup.Contains(m.Value))
.ToList();
if (all && !await ctx.PromptYesNo($"Are you sure you want to remove all members from group {target.Reference(ctx)}?", "Empty Group")) throw Errors.GenericCancelled();
if (all && !await ctx.PromptYesNo($"Are you sure you want to remove all members from group {target.Reference(ctx)}?", "Empty Group", flagValue: confirmYes)) throw Errors.GenericCancelled();
await ctx.Repository.RemoveMembersFromGroup(target.Id, toAction);
}

View file

@ -32,7 +32,7 @@ public class Groups
_avatarHosting = avatarHosting;
}
public async Task CreateGroup(Context ctx, string groupName)
public async Task CreateGroup(Context ctx, string groupName, bool confirmYes = false)
{
ctx.CheckSystem();
@ -53,7 +53,7 @@ public class Groups
{
var msg =
$"{Emojis.Warn} You already have a group in your system with the name \"{existingGroup.Name}\" (with ID `{existingGroup.DisplayHid(ctx.Config)}`). Do you want to create another group with the same name?";
if (!await ctx.PromptYesNo(msg, "Create"))
if (!await ctx.PromptYesNo(msg, "Create", flagValue: confirmYes))
throw new PKError("Group creation cancelled.");
}
@ -98,7 +98,7 @@ public class Groups
await ctx.Reply(replyStr, eb.Build());
}
public async Task RenameGroup(Context ctx, PKGroup target, string newName)
public async Task RenameGroup(Context ctx, PKGroup target, string? newName, bool confirmYes = false)
{
ctx.CheckOwnGroup(target);
@ -113,7 +113,7 @@ public class Groups
{
var msg =
$"{Emojis.Warn} You already have a group in your system with the name \"{existingGroup.Name}\" (with ID `{existingGroup.DisplayHid(ctx.Config)}`). Do you want to rename this group to that name too?";
if (!await ctx.PromptYesNo(msg, "Rename"))
if (!await ctx.PromptYesNo(msg, "Rename", flagValue: confirmYes))
throw new PKError("Group rename cancelled.");
}
@ -320,10 +320,10 @@ public class Groups
await ctx.Reply(embed: ebS.Build());
}
public async Task ClearGroupIcon(Context ctx, PKGroup target)
public async Task ClearGroupIcon(Context ctx, PKGroup target, bool confirmYes)
{
ctx.CheckOwnGroup(target);
await ctx.ConfirmClear("this group's icon");
await ctx.ConfirmClear("this group's icon", confirmYes);
await ctx.Repository.UpdateGroup(target.Id, new GroupPatch { Icon = null });
await ctx.Reply($"{Emojis.Success} Group icon cleared.");
@ -400,10 +400,10 @@ public class Groups
await ctx.Reply(embed: ebS.Build());
}
public async Task ClearGroupBanner(Context ctx, PKGroup target)
public async Task ClearGroupBanner(Context ctx, PKGroup target, bool confirmYes)
{
ctx.CheckOwnGroup(target);
await ctx.ConfirmClear("this group's banner image");
await ctx.ConfirmClear("this group's banner image", confirmYes);
await ctx.Repository.UpdateGroup(target.Id, new GroupPatch { BannerImage = null });
await ctx.Reply($"{Emojis.Success} Group banner image cleared.");
@ -506,7 +506,7 @@ public class Groups
files: [MiscUtils.GenerateColorPreview(color)]);
}
public async Task ListSystemGroups(Context ctx, PKSystem system, string? query, IHasListOptions flags)
public async Task ListSystemGroups(Context ctx, PKSystem system, string? query, IHasListOptions flags, bool all)
{
if (system == null)
{
@ -528,7 +528,8 @@ public class Groups
system.Id,
GetEmbedTitle(ctx, system, opts),
system.Color,
opts
opts,
all
);
}
@ -547,16 +548,16 @@ public class Groups
return title.ToString();
}
public async Task ShowGroupCard(Context ctx, PKGroup target, bool showEmbed = false)
public async Task ShowGroupCard(Context ctx, PKGroup target, bool showEmbed, bool all)
{
var system = await GetGroupSystem(ctx, target);
if (showEmbed)
{
await ctx.Reply(text: EmbedService.LEGACY_EMBED_WARNING, embed: await _embeds.CreateGroupEmbed(ctx, system, target));
await ctx.Reply(text: EmbedService.LEGACY_EMBED_WARNING, embed: await _embeds.CreateGroupEmbed(ctx, system, target, all));
return;
}
await ctx.Reply(components: await _embeds.CreateGroupMessageComponents(ctx, system, target));
await ctx.Reply(components: await _embeds.CreateGroupMessageComponents(ctx, system, target, all));
}
public async Task ShowGroupPrivacy(Context ctx, PKGroup target)

View file

@ -31,7 +31,7 @@ public class ImportExport
_dmCache = dmCache;
}
public async Task Import(Context ctx, string? inputUrl)
public async Task Import(Context ctx, string? inputUrl, bool confirmYes)
{
inputUrl = inputUrl ?? ctx.Message.Attachments.FirstOrDefault()?.Url;
if (inputUrl == null) throw Errors.NoImportFilePassed;
@ -77,7 +77,7 @@ public class ImportExport
async Task ConfirmImport(string message)
{
var msg = $"{message}\n\nDo you want to proceed with the import?";
if (!await ctx.PromptYesNo(msg, "Proceed"))
if (!await ctx.PromptYesNo(msg, "Proceed", flagValue: confirmYes))
throw Errors.ImportCancelled;
}
@ -86,7 +86,7 @@ public class ImportExport
&& data.Value<JArray>("accounts").Contains(ctx.Author.Id.ToString()))
{
var msg = $"{Emojis.Warn} You seem to importing a system profile belonging to another account. Are you sure you want to proceed?";
if (!await ctx.PromptYesNo(msg, "Import")) throw Errors.ImportCancelled;
if (!await ctx.PromptYesNo(msg, "Import", flagValue: confirmYes)) throw Errors.ImportCancelled;
}
var result = await _dataFiles.ImportSystem(ctx.Author.Id, ctx.System, data, ConfirmImport);

View file

@ -130,7 +130,7 @@ public static class ContextListExt
}
public static async Task RenderGroupList(this Context ctx, LookupContext lookupCtx,
SystemId system, string embedTitle, string color, ListOptions opts)
SystemId system, string embedTitle, string color, ListOptions opts, bool all)
{
// We take an IDatabase instead of a IPKConnection so we don't keep the handle open for the entire runtime
// We wanna release it as soon as the member list is actually *fetched*, instead of potentially minutes later (paginate timeout)
@ -204,7 +204,7 @@ public static class ContextListExt
{
if (g.ListPrivacy == PrivacyLevel.Public || lookupCtx == LookupContext.ByOwner)
{
if (ctx.MatchFlag("all", "a"))
if (all)
{
ret += $"({"member".ToQuantity(g.TotalMemberCount)})";
}
@ -242,7 +242,7 @@ public static class ContextListExt
if (g.ListPrivacy == PrivacyLevel.Public || lookupCtx == LookupContext.ByOwner)
{
if (ctx.MatchFlag("all", "a") && ctx.DirectLookupContextFor(system) == LookupContext.ByOwner)
if (all && ctx.DirectLookupContextFor(system) == LookupContext.ByOwner)
profile.Append($"\n**Member Count:** {g.TotalMemberCount}");
else
profile.Append($"\n**Member Count:** {g.PublicMemberCount}");

View file

@ -28,7 +28,7 @@ public class Member
_avatarHosting = avatarHosting;
}
public async Task NewMember(Context ctx, string? memberName)
public async Task NewMember(Context ctx, string? memberName, bool confirmYes = false)
{
if (ctx.System == null) throw Errors.NoSystemError(ctx.DefaultPrefix);
memberName = memberName ?? throw new PKSyntaxError("You must pass a member name.");
@ -42,7 +42,7 @@ public class Member
if (existingMember != null)
{
var msg = $"{Emojis.Warn} You already have a member in your system with the name \"{existingMember.NameFor(ctx)}\" (with ID `{existingMember.DisplayHid(ctx.Config)}`). Do you want to create another member with the same name?";
if (!await ctx.PromptYesNo(msg, "Create")) throw new PKError("Member creation cancelled.");
if (!await ctx.PromptYesNo(msg, "Create", flagValue: confirmYes)) throw new PKError("Member creation cancelled.");
}
await using var conn = await ctx.Database.Obtain();

View file

@ -17,10 +17,10 @@ public class MemberAvatar
_avatarHosting = avatarHosting;
}
private async Task AvatarClear(MemberAvatarLocation location, Context ctx, PKMember target, MemberGuildSettings? mgs)
private async Task AvatarClear(MemberAvatarLocation location, Context ctx, PKMember target, MemberGuildSettings? mgs, bool confirmYes)
{
ctx.CheckSystem().CheckOwnMember(target);
await ctx.ConfirmClear("this member's " + location.Name());
await ctx.ConfirmClear("this member's " + location.Name(), confirmYes);
await UpdateAvatar(location, ctx, target, null);
if (location == MemberAvatarLocation.Server)
@ -149,10 +149,10 @@ public class MemberAvatar
await AvatarShow(MemberAvatarLocation.Server, ctx, target, guildData, format);
}
public async Task ClearServerAvatar(Context ctx, PKMember target)
public async Task ClearServerAvatar(Context ctx, PKMember target, bool confirmYes)
{
var guildData = await GetServerAvatarGuildData(ctx, target);
await AvatarClear(MemberAvatarLocation.Server, ctx, target, guildData);
await AvatarClear(MemberAvatarLocation.Server, ctx, target, guildData, confirmYes);
}
public async Task ChangeServerAvatar(Context ctx, PKMember target, ParsedImage avatar)
@ -167,10 +167,10 @@ public class MemberAvatar
await AvatarShow(MemberAvatarLocation.Member, ctx, target, guildData, format);
}
public async Task ClearAvatar(Context ctx, PKMember target)
public async Task ClearAvatar(Context ctx, PKMember target, bool confirmYes)
{
var guildData = await GetAvatarGuildData(ctx, target);
await AvatarClear(MemberAvatarLocation.Member, ctx, target, guildData);
await AvatarClear(MemberAvatarLocation.Member, ctx, target, guildData, confirmYes);
}
public async Task ChangeAvatar(Context ctx, PKMember target, ParsedImage avatar)
@ -185,10 +185,10 @@ public class MemberAvatar
await AvatarShow(MemberAvatarLocation.MemberWebhook, ctx, target, guildData, format);
}
public async Task ClearWebhookAvatar(Context ctx, PKMember target)
public async Task ClearWebhookAvatar(Context ctx, PKMember target, bool confirmYes)
{
var guildData = await GetWebhookAvatarGuildData(ctx, target);
await AvatarClear(MemberAvatarLocation.MemberWebhook, ctx, target, guildData);
await AvatarClear(MemberAvatarLocation.MemberWebhook, ctx, target, guildData, confirmYes);
}
public async Task ChangeWebhookAvatar(Context ctx, PKMember target, ParsedImage avatar)

View file

@ -44,7 +44,7 @@ public class MemberEdit
}
}
public async Task ChangeName(Context ctx, PKMember target, string newName)
public async Task ChangeName(Context ctx, PKMember target, string newName, bool confirmYes)
{
ctx.CheckSystem().CheckOwnMember(target);
@ -58,7 +58,7 @@ public class MemberEdit
{
var msg =
$"{Emojis.Warn} You already have a member in your system with the name \"{existingMember.NameFor(ctx)}\" (`{existingMember.DisplayHid(ctx.Config)}`). Do you want to rename this member to that name too?";
if (!await ctx.PromptYesNo(msg, "Rename")) throw new PKError("Member renaming cancelled.");
if (!await ctx.PromptYesNo(msg, "Rename", flagValue: confirmYes)) throw new PKError("Member renaming cancelled.");
}
// Rename the member

View file

@ -14,7 +14,7 @@ public class MemberProxy
await ctx.Reply($"This member's proxy tags are:\n{target.ProxyTagsString("\n")}");
}
public async Task ClearProxy(Context ctx, PKMember target)
public async Task ClearProxy(Context ctx, PKMember target, bool confirmYes = false)
{
ctx.CheckSystem().CheckOwnMember(target);
@ -22,7 +22,7 @@ public class MemberProxy
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"))
if (!await ctx.PromptYesNo(msg, "Clear", flagValue: confirmYes))
throw Errors.GenericCancelled();
}
@ -32,7 +32,7 @@ public class MemberProxy
await ctx.Reply($"{Emojis.Success} Proxy tags cleared.");
}
public async Task AddProxy(Context ctx, PKMember target, string proxyString)
public async Task AddProxy(Context ctx, PKMember target, string proxyString, bool confirmYes = false)
{
ctx.CheckSystem().CheckOwnMember(target);
@ -44,7 +44,7 @@ public class MemberProxy
throw new PKError(
$"Proxy tag too long ({tagToAdd.ProxyString.Length} > {Limits.MaxProxyTagLength} characters).");
if (!await WarnOnConflict(ctx, target, tagToAdd))
if (!await WarnOnConflict(ctx, target, tagToAdd, confirmYes))
throw Errors.GenericCancelled();
var newTags = target.ProxyTags.ToList();
@ -72,7 +72,7 @@ public class MemberProxy
await ctx.Reply($"{Emojis.Success} Removed proxy tags {tagToRemove.ProxyString.AsCode()}.");
}
public async Task SetProxy(Context ctx, PKMember target, string proxyString)
public async Task SetProxy(Context ctx, PKMember target, string proxyString, bool confirmYes = false)
{
ctx.CheckSystem().CheckOwnMember(target);
@ -82,7 +82,7 @@ public class MemberProxy
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"))
if (!await ctx.PromptYesNo(msg, "Replace", flagValue: confirmYes))
throw Errors.GenericCancelled();
}
@ -90,7 +90,7 @@ public class MemberProxy
throw new PKError(
$"Proxy tag too long ({requestedTag.ProxyString.Length} > {Limits.MaxProxyTagLength} characters).");
if (!await WarnOnConflict(ctx, target, requestedTag))
if (!await WarnOnConflict(ctx, target, requestedTag, confirmYes))
throw Errors.GenericCancelled();
var newTags = new[] { requestedTag };
@ -110,7 +110,7 @@ public class MemberProxy
return new ProxyTag(prefixAndSuffix[0], prefixAndSuffix[1]);
}
private async Task<bool> WarnOnConflict(Context ctx, PKMember target, ProxyTag newTag)
private async Task<bool> WarnOnConflict(Context ctx, PKMember target, ProxyTag newTag, bool confirmYes = false)
{
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 ctx.Database.Execute(conn => conn.QueryAsync<PKMember>(query,
@ -120,6 +120,6 @@ public class MemberProxy
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");
return await ctx.PromptYesNo(msg, "Proceed", flagValue: confirmYes);
}
}

View file

@ -322,9 +322,7 @@ public class ProxiedMessage
{
if (messageId == null)
{
if (!ctx.HasNext())
throw new PKSyntaxError("You must pass a message ID or link.");
throw new PKSyntaxError($"Could not parse {ctx.PeekArgument().AsCode()} as a message ID or link.");
throw new PKSyntaxError("You must pass a message ID or link.");
}
var message = await ctx.Repository.GetFullMessage(messageId.Value);

View file

@ -74,12 +74,12 @@ public class Random
{
await ctx.Reply(
text: EmbedService.LEGACY_EMBED_WARNING,
embed: await _embeds.CreateGroupEmbed(ctx, target, groups.ToArray()[randInt]));
embed: await _embeds.CreateGroupEmbed(ctx, target, groups.ToArray()[randInt], all));
return;
}
await ctx.Reply(
components: await _embeds.CreateGroupMessageComponents(ctx, target, groups.ToArray()[randInt]));
components: await _embeds.CreateGroupMessageComponents(ctx, target, groups.ToArray()[randInt], all));
}
public async Task GroupMember(Context ctx, PKGroup group, GroupRandomMemberFlags flags)

View file

@ -144,11 +144,11 @@ public class ServerConfig
await ctx.Reply($"{Emojis.Success} Proxy logging channel set to <#{channel.Id}>.");
}
public async Task ClearLogChannel(Context ctx)
public async Task ClearLogChannel(Context ctx, bool confirmYes)
{
await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server");
if (!await ctx.ConfirmClear("the server log channel"))
if (!await ctx.ConfirmClear("the server log channel", confirmYes))
return;
await ctx.Repository.UpdateGuild(ctx.Guild.Id, new GuildPatch { LogChannel = null });

View file

@ -57,14 +57,14 @@ public class Switch
$"{Emojis.Success} Switch registered. Current fronters are now {string.Join(", ", members.Select(m => m.NameFor(ctx)))}.");
}
public async Task SwitchMove(Context ctx, string timeToMove)
public async Task SwitchMove(Context ctx, string str, bool confirmYes = false)
{
ctx.CheckSystem();
var tz = TzdbDateTimeZoneSource.Default.ForId(ctx.Config?.UiTz ?? "UTC");
var result = DateUtils.ParseDateTime(timeToMove, true, tz);
if (result == null) throw Errors.InvalidDateTime(timeToMove);
var result = DateUtils.ParseDateTime(str, true, tz);
if (result == null) throw Errors.InvalidDateTime(str);
var time = result.Value;
@ -95,14 +95,14 @@ public class Switch
// yeet
var msg =
$"{Emojis.Warn} This will move the latest switch ({lastSwitchMemberStr}) from <t:{lastSwitchTime}> ({lastSwitchDeltaStr} ago) to <t:{newSwitchTime}> ({newSwitchDeltaStr} ago). Is this OK?";
if (!await ctx.PromptYesNo(msg, "Move Switch")) throw Errors.SwitchMoveCancelled;
if (!await ctx.PromptYesNo(msg, "Move Switch", flagValue: confirmYes)) throw Errors.SwitchMoveCancelled;
// aaaand *now* we do the move
await ctx.Repository.MoveSwitch(lastTwoSwitches[0].Id, time.ToInstant());
await ctx.Reply($"{Emojis.Success} Switch moved to <t:{newSwitchTime}> ({newSwitchDeltaStr} ago).");
}
public async Task SwitchEdit(Context ctx, List<PKMember>? newMembers, bool newSwitch = false, bool first = false, bool remove = false, bool append = false, bool prepend = false)
public async Task SwitchEdit(Context ctx, List<PKMember>? newMembers, bool newSwitch = false, bool first = false, bool remove = false, bool append = false, bool prepend = false, bool confirmYes = false)
{
ctx.CheckSystem();
@ -131,7 +131,7 @@ public class Switch
await DoSwitchCommand(ctx, newMembers);
}
else
await DoEditCommand(ctx, newMembers);
await DoEditCommand(ctx, newMembers, confirmYes);
}
public List<PKMember> PrependToSwitch(List<PKMember> members, List<PKMember> currentSwitchMembers)
@ -167,13 +167,13 @@ public class Switch
return members;
}
public async Task SwitchEditOut(Context ctx)
public async Task SwitchEditOut(Context ctx, bool confirmYes)
{
ctx.CheckSystem();
await DoEditCommand(ctx, []);
await DoEditCommand(ctx, [], confirmYes);
}
public async Task DoEditCommand(Context ctx, ICollection<PKMember>? members)
public async Task DoEditCommand(Context ctx, ICollection<PKMember>? members, bool confirmYes)
{
if (members == null) members = new List<PKMember>();
@ -203,7 +203,7 @@ public class Switch
msg = $"{Emojis.Warn} This will turn the latest switch ({lastSwitchMemberStr}, {lastSwitchDeltaStr} ago) into a switch-out. Is this okay?";
else
msg = $"{Emojis.Warn} This will change the latest switch ({lastSwitchMemberStr}, {lastSwitchDeltaStr} ago) to {newSwitchMemberStr}. Is this okay?";
if (!await ctx.PromptYesNo(msg, "Edit")) throw Errors.SwitchEditCancelled;
if (!await ctx.PromptYesNo(msg, "Edit", flagValue: confirmYes)) throw Errors.SwitchEditCancelled;
// Actually edit the switch
await ctx.Repository.EditSwitch(conn, lastSwitch.Id, members.Select(m => m.Id).ToList());
@ -217,7 +217,7 @@ public class Switch
await ctx.Reply($"{Emojis.Success} Switch edited. Current fronters are now {newSwitchMemberStr}.");
}
public async Task SwitchDelete(Context ctx, bool all)
public async Task SwitchDelete(Context ctx, bool all = false, bool confirmYes = false)
{
ctx.CheckSystem();
@ -226,7 +226,7 @@ public class Switch
// 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"))
if (!await ctx.PromptYesNo(purgeMsg, "Clear Switches", flagValue: confirmYes))
throw Errors.GenericCancelled();
await ctx.Repository.DeleteAllSwitches(ctx.System.Id);
await ctx.Reply($"{Emojis.Success} Cleared system switches!");
@ -258,7 +258,7 @@ public class Switch
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;
if (!await ctx.PromptYesNo(msg, "Delete Switch", flagValue: confirmYes)) throw Errors.SwitchDeleteCancelled;
await ctx.Repository.DeleteSwitch(lastTwoSwitches[0].Id);
await ctx.Reply($"{Emojis.Success} Switch deleted.");

View file

@ -26,7 +26,7 @@ public class SystemFront
await ctx.Reply(embed: await _embeds.CreateFronterEmbed(sw, ctx.Zone, ctx.LookupContextFor(system.Id)));
}
public async Task FrontHistory(Context ctx, PKSystem system, bool clear = false)
public async Task FrontHistory(Context ctx, PKSystem system, bool showMemberId, bool clear = false)
{
if (clear)
{
@ -55,8 +55,6 @@ public class SystemFront
embedTitle = $"Front history of {guildSettings.DisplayName} (`{system.Hid}`)";
}
var showMemberId = ctx.MatchFlag("with-id", "wid");
await ctx.Paginate(
sws,
totalSwitches,

View file

@ -25,7 +25,7 @@ public class SystemLink
await ctx.Reply($"{Emojis.Success} Account linked to system.");
}
public async Task UnlinkAccount(Context ctx, string idRaw)
public async Task UnlinkAccount(Context ctx, string idRaw, bool confirmYes)
{
ctx.CheckSystem();
@ -38,7 +38,7 @@ public class SystemLink
if (accountIds.Count == 1) throw Errors.UnlinkingLastAccount(ctx.DefaultPrefix);
var msg = $"Are you sure you want to unlink <@{id}> from your system?";
if (!await ctx.PromptYesNo(msg, "Unlink")) throw Errors.MemberUnlinkCancelled;
if (!await ctx.PromptYesNo(msg, "Unlink", flagValue: confirmYes)) throw Errors.MemberUnlinkCancelled;
await ctx.Repository.RemoveAccount(ctx.System.Id, id);
await ctx.Reply($"{Emojis.Success} Account unlinked.");

View file

@ -560,7 +560,7 @@ public class EmbedService
return eb.Build();
}
public async Task<MessageComponent[]> CreateGroupMessageComponents(Context ctx, PKSystem system, PKGroup target)
public async Task<MessageComponent[]> CreateGroupMessageComponents(Context ctx, PKSystem system, PKGroup target, bool all)
{
var pctx = ctx.LookupContextFor(system.Id);
var name = target.NameFor(ctx);
@ -568,7 +568,7 @@ public class EmbedService
var systemName = (ctx.Guild != null && systemGuildSettings?.DisplayName != null) ? systemGuildSettings?.DisplayName! : system.NameFor(ctx);
var countctx = LookupContext.ByNonOwner;
if (ctx.MatchFlag("a", "all"))
if (all)
{
if (system.Id == ctx.System?.Id)
countctx = LookupContext.ByOwner;
@ -673,12 +673,12 @@ public class EmbedService
];
}
public async Task<Embed> CreateGroupEmbed(Context ctx, PKSystem system, PKGroup target)
public async Task<Embed> CreateGroupEmbed(Context ctx, PKSystem system, PKGroup target, bool all)
{
var pctx = ctx.LookupContextFor(system.Id);
var countctx = LookupContext.ByNonOwner;
if (ctx.MatchFlag("a", "all"))
if (all)
{
if (system.Id == ctx.System?.Id)
countctx = LookupContext.ByOwner;

View file

@ -16,17 +16,17 @@ namespace PluralKit.Bot;
public static class ContextUtils
{
public static async Task<bool> ConfirmClear(this Context ctx, string toClear, bool? confirmYes = null)
public static async Task<bool> ConfirmClear(this Context ctx, string toClear, bool confirmYes)
{
if (!await ctx.PromptYesNo($"{Emojis.Warn} Are you sure you want to clear {toClear}?", "Clear", null, true, confirmYes))
if (!await ctx.PromptYesNo($"{Emojis.Warn} Are you sure you want to clear {toClear}?", "Clear", flagValue: confirmYes))
throw Errors.GenericCancelled();
return true;
}
public static async Task<bool> PromptYesNo(this Context ctx, string msgString, string acceptButton,
User user = null, bool matchFlag = true, bool? flagValue = null)
User user = null, bool matchFlag = true, bool flagValue = false)
{
if (matchFlag && (flagValue ?? ctx.MatchFlag("y", "yes"))) return true;
if (matchFlag && flagValue) return true;
var prompt = new YesNoPrompt(ctx)
{

View file

@ -16,6 +16,7 @@ pub fn cmds() -> impl Iterator<Item = Command> {
.help("Sets the deny flag on an abuse log entry"),
command!(abuselog, ("description", ["desc"]), log_param, Optional(("desc", OpaqueStringRemainder)) => format!("admin_abuselog_description_{}", log_param.name()))
.flag(("clear", ["c"]))
.flag(("yes", ["y"]))
.help("Sets the description of an abuse log entry"),
command!(abuselog, ("adduser", ["au"]), log_param => format!("admin_abuselog_add_user_{}", log_param.name()))
.help("Adds a user to an abuse log entry"),
@ -36,22 +37,31 @@ pub fn cmds() -> impl Iterator<Item = Command> {
[
command!(admin, ("updatesystemid", ["usid"]), SystemRef, ("new_hid", OpaqueString) => "admin_update_system_id")
.flag(("yes", ["y"]))
.help("Updates a system's ID"),
command!(admin, ("updatememberid", ["umid"]), MemberRef, ("new_hid", OpaqueString) => "admin_update_member_id")
.flag(("yes", ["y"]))
.help("Updates a member's ID"),
command!(admin, ("updategroupid", ["ugid"]), GroupRef, ("new_hid", OpaqueString) => "admin_update_group_id")
.flag(("yes", ["y"]))
.help("Updates a group's ID"),
command!(admin, ("rerollsystemid", ["rsid"]), SystemRef => "admin_reroll_system_id")
.flag(("yes", ["y"]))
.help("Rerolls a system's ID"),
command!(admin, ("rerollmemberid", ["rmid"]), MemberRef => "admin_reroll_member_id")
.flag(("yes", ["y"]))
.help("Rerolls a member's ID"),
command!(admin, ("rerollgroupid", ["rgid"]), GroupRef => "admin_reroll_group_id")
.flag(("yes", ["y"]))
.help("Rerolls a group's ID"),
command!(admin, ("updatememberlimit", ["uml"]), SystemRef, Optional(("limit", OpaqueInt)) => "admin_system_member_limit")
.flag(("yes", ["y"]))
.help("Updates a system's member limit"),
command!(admin, ("updategrouplimit", ["ugl"]), SystemRef, Optional(("limit", OpaqueInt)) => "admin_system_group_limit")
.flag(("yes", ["y"]))
.help("Updates a system's group limit"),
command!(admin, ("systemrecover", ["sr"]), ("token", OpaqueString), ("account", UserRef) => "admin_system_recover")
.flag(("yes", ["y"]))
.flag(("reroll-token", ["rt"]))
.help("Recovers a system"),
command!(admin, ("systemdelete", ["sd"]), SystemRef => "admin_system_delete")

View file

@ -21,9 +21,10 @@ pub fn cmds() -> impl Iterator<Item = Command> {
[command!(group_new, ("name", OpaqueString) => "group_new").help("Creates a new group")]
.into_iter();
let group_info_cmd =
[command!(group_target => "group_info").help("Shows information about a group")]
.into_iter();
let group_info_cmd = [command!(group_target => "group_info")
.flag(("all", ["a"]))
.help("Shows information about a group")]
.into_iter();
let group_name = tokens!(
group_target,
@ -159,9 +160,9 @@ pub fn cmds() -> impl Iterator<Item = Command> {
let group_modify_members_cmd = [
command!(group_target, "add", Optional(MemberRefs) => "group_add_member")
.flag(("all", ["a"])),
.flag(("all", ["a"])).flag(("yes", ["y"])),
command!(group_target, ("remove", ["delete", "del", "rem"]), Optional(MemberRefs) => "group_remove_member")
.flag(("all", ["a"])),
.flag(("all", ["a"])).flag(("yes", ["y"])),
]
.into_iter();

View file

@ -2,7 +2,8 @@ use super::*;
pub fn cmds() -> impl Iterator<Item = Command> {
[
command!("import", Optional(("url", OpaqueStringRemainder)) => "import"),
command!("import", Optional(("url", OpaqueStringRemainder)) => "import")
.flag(("yes", ["y"])),
command!("export" => "export"),
]
.into_iter()

View file

@ -49,6 +49,7 @@ pub fn cmds() -> impl Iterator<Item = Command> {
[
command!(member_name => "member_name_show").help("Shows a member's name"),
command!(member_name, ("name", OpaqueStringRemainder) => "member_name_update")
.flag(("yes", ["y"]))
.help("Changes a member's name"),
]
.into_iter()

View file

@ -51,6 +51,7 @@ pub fn cmds() -> impl Iterator<Item = Command> {
command!(log_channel, ("channel", ChannelRef) => "server_config_log_channel_set")
.help("Sets the log channel"),
command!(log_channel, ("clear", ["c"]) => "server_config_log_channel_clear")
.flag(("yes", ["y"]))
.help("Clears the log channel"),
]
.into_iter();

View file

@ -20,7 +20,7 @@ pub fn cmds() -> impl Iterator<Item = Command> {
command!(switch, out => "switch_out"),
command!(switch, r#move, OpaqueString => "switch_move"), // TODO: datetime parsing
command!(switch, delete => "switch_delete").flag(("all", ["clear", "c"])),
command!(switch, edit, out => "switch_edit_out"),
command!(switch, edit, out => "switch_edit_out").flag(("yes", ["y"])),
command!(switch, edit, Optional(MemberRefs) => "switch_edit").flags(edit_flags),
command!(switch, copy, Optional(MemberRefs) => "switch_copy").flags(edit_flags),
command!(switch, ("commands", ["help"]) => "switch_commands"),

View file

@ -28,25 +28,33 @@ pub fn edit() -> impl Iterator<Item = Command> {
]
.into_iter();
let system_webhook_cmd = [command!(system, ("webhook", ["hook"]) => "system_webhook")
.help("Creates a webhook for your system")]
let system_webhook = tokens!(system, ("webhook", ["hook"]));
let system_webhook_cmd = [
command!(system_webhook => "system_webhook_show").help("Shows your system's webhook URL"),
command!(system_webhook, ("clear", ["c"]) => "system_webhook_clear")
.flag(("yes", ["y"]))
.help("Clears your system's webhook URL"),
command!(system_webhook, ("url", OpaqueString) => "system_webhook_set")
.help("Sets your system's webhook URL"),
]
.into_iter();
let system_info_cmd = [
command!(system => "system_info_self").help("Shows information about your system"),
command!(system_target, ("info", ["show", "view"]) => "system_info")
.help("Shows information about your system"),
]
.into_iter()
.map(|cmd| {
let add_info_flags = |cmd: Command| {
cmd.flag(("public", ["pub"]))
.flag(("private", ["priv"]))
.flag(("all", ["a"]))
});
};
let system_info_cmd_self = std::iter::once(add_info_flags(
command!(system => "system_info_self").help("Shows information about your system"),
));
let system_info_cmd = std::iter::once(add_info_flags(
command!(system_target, ("info", ["show", "view"]) => "system_info")
.help("Shows information about your system"),
));
let system_name = tokens!(system_target, "name");
let system_name_cmd =
[command!(system_name => "system_show_name").help("Shows the systems name")].into_iter();
std::iter::once(command!(system_name => "system_show_name").help("Shows the systems name"));
let system_name_self = tokens!(system, "name");
let system_name_self_cmd = [
@ -60,9 +68,10 @@ pub fn edit() -> impl Iterator<Item = Command> {
.into_iter();
let system_server_name = tokens!(system_target, ("servername", ["sn", "guildname"]));
let system_server_name_cmd = [command!(system_server_name => "system_show_server_name")
.help("Shows the system's server name")]
.into_iter();
let system_server_name_cmd = std::iter::once(
command!(system_server_name => "system_show_server_name")
.help("Shows the system's server name"),
);
let system_server_name_self = tokens!(system, ("servername", ["sn", "guildname"]));
let system_server_name_self_cmd = [
@ -77,9 +86,10 @@ pub fn edit() -> impl Iterator<Item = Command> {
.into_iter();
let system_description = tokens!(system_target, ("description", ["desc", "d"]));
let system_description_cmd = [command!(system_description => "system_show_description")
.help("Shows the system's description")]
.into_iter();
let system_description_cmd = std::iter::once(
command!(system_description => "system_show_description")
.help("Shows the system's description"),
);
let system_description_self = tokens!(system, ("description", ["desc", "d"]));
let system_description_self_cmd = [
@ -93,9 +103,9 @@ pub fn edit() -> impl Iterator<Item = Command> {
.into_iter();
let system_color = tokens!(system_target, ("color", ["colour"]));
let system_color_cmd =
[command!(system_color => "system_show_color").help("Shows the system's color")]
.into_iter();
let system_color_cmd = std::iter::once(
command!(system_color => "system_show_color").help("Shows the system's color"),
);
let system_color_self = tokens!(system, ("color", ["colour"]));
let system_color_self_cmd = [
@ -110,7 +120,7 @@ pub fn edit() -> impl Iterator<Item = Command> {
let system_tag = tokens!(system_target, ("tag", ["suffix"]));
let system_tag_cmd =
[command!(system_tag => "system_show_tag").help("Shows the system's tag")].into_iter();
std::iter::once(command!(system_tag => "system_show_tag").help("Shows the system's tag"));
let system_tag_self = tokens!(system, ("tag", ["suffix"]));
let system_tag_self_cmd = [
@ -124,9 +134,10 @@ pub fn edit() -> impl Iterator<Item = Command> {
.into_iter();
let system_server_tag = tokens!(system_target, ("servertag", ["st", "guildtag"]));
let system_server_tag_cmd = [command!(system_server_tag => "system_show_server_tag")
.help("Shows the system's server tag")]
.into_iter();
let system_server_tag_cmd = std::iter::once(
command!(system_server_tag => "system_show_server_tag")
.help("Shows the system's server tag"),
);
let system_server_tag_self = tokens!(system, ("servertag", ["st", "guildtag"]));
let system_server_tag_self_cmd = [
@ -141,9 +152,9 @@ pub fn edit() -> impl Iterator<Item = Command> {
.into_iter();
let system_pronouns = tokens!(system_target, ("pronouns", ["prns"]));
let system_pronouns_cmd =
[command!(system_pronouns => "system_show_pronouns").help("Shows the system's pronouns")]
.into_iter();
let system_pronouns_cmd = std::iter::once(
command!(system_pronouns => "system_show_pronouns").help("Shows the system's pronouns"),
);
let system_pronouns_self = tokens!(system, ("pronouns", ["prns"]));
let system_pronouns_self_cmd = [
@ -158,9 +169,9 @@ pub fn edit() -> impl Iterator<Item = Command> {
.into_iter();
let system_avatar = tokens!(system_target, ("avatar", ["pfp"]));
let system_avatar_cmd =
[command!(system_avatar => "system_show_avatar").help("Shows the system's avatar")]
.into_iter();
let system_avatar_cmd = std::iter::once(
command!(system_avatar => "system_show_avatar").help("Shows the system's avatar"),
);
let system_avatar_self = tokens!(system, ("avatar", ["pfp"]));
let system_avatar_self_cmd = [
@ -175,11 +186,10 @@ pub fn edit() -> impl Iterator<Item = Command> {
.into_iter();
let system_server_avatar = tokens!(system_target, ("serveravatar", ["spfp"]));
let system_server_avatar_cmd = [
let system_server_avatar_cmd = std::iter::once(
command!(system_server_avatar => "system_show_server_avatar")
.help("Shows the system's server avatar"),
]
.into_iter();
);
let system_server_avatar_self = tokens!(system, ("serveravatar", ["spfp"]));
let system_server_avatar_self_cmd = [
@ -194,9 +204,9 @@ pub fn edit() -> impl Iterator<Item = Command> {
.into_iter();
let system_banner = tokens!(system_target, ("banner", ["cover"]));
let system_banner_cmd =
[command!(system_banner => "system_show_banner").help("Shows the system's banner")]
.into_iter();
let system_banner_cmd = std::iter::once(
command!(system_banner => "system_show_banner").help("Shows the system's banner"),
);
let system_banner_self = tokens!(system, ("banner", ["cover"]));
let system_banner_self_cmd = [
@ -253,7 +263,7 @@ pub fn edit() -> impl Iterator<Item = Command> {
let system_link = [
command!("link", ("account", UserRef) => "system_link"),
command!("unlink", ("account", OpaqueString) => "system_unlink"),
command!("unlink", ("account", OpaqueString) => "system_unlink").flag(("yes", ["y"])),
]
.into_iter();
@ -286,10 +296,12 @@ pub fn edit() -> impl Iterator<Item = Command> {
.map(add_list_flags);
let system_display_id_self_cmd =
[command!(system, "id" => "system_display_id_self")].into_iter();
let system_display_id_cmd = [command!(system_target, "id" => "system_display_id")].into_iter();
std::iter::once(command!(system, "id" => "system_display_id_self"));
let system_display_id_cmd =
std::iter::once(command!(system_target, "id" => "system_display_id"));
system_new_cmd
system_info_cmd_self
.chain(system_new_cmd)
.chain(system_webhook_cmd)
.chain(system_name_self_cmd)
.chain(system_server_name_self_cmd)

View file

@ -4,7 +4,7 @@ use command_parser::Tree;
use commands::COMMAND_TREE;
fn main() {
parse();
related();
}
fn related() {