diff --git a/PluralKit.Bot/CommandMeta/CommandTree.cs b/PluralKit.Bot/CommandMeta/CommandTree.cs index 6559a6e9..000c3d27 100644 --- a/PluralKit.Bot/CommandMeta/CommandTree.cs +++ b/PluralKit.Bot/CommandMeta/CommandTree.cs @@ -70,12 +70,45 @@ public partial class CommandTree Commands.MemberGroupAdd(var param, _) => ctx.Execute(MemberGroupAdd, m => m.AddRemoveGroups(ctx, param.target, param.groups, Groups.AddRemoveOperation.Add)), Commands.MemberGroupRemove(var param, _) => ctx.Execute(MemberGroupRemove, m => m.AddRemoveGroups(ctx, param.target, param.groups, Groups.AddRemoveOperation.Remove)), Commands.MemberId(var param, _) => ctx.Execute(MemberId, m => m.DisplayId(ctx, param.target)), + Commands.CfgShow => ctx.Execute(null, m => m.ShowConfig(ctx)), Commands.CfgApAccountShow => ctx.Execute(null, m => m.ViewAutoproxyAccount(ctx)), Commands.CfgApAccountUpdate(var param, _) => ctx.Execute(null, m => m.EditAutoproxyAccount(ctx, param.toggle)), Commands.CfgApTimeoutShow => ctx.Execute(null, m => m.ViewAutoproxyTimeout(ctx)), Commands.CfgApTimeoutOff => ctx.Execute(null, m => m.DisableAutoproxyTimeout(ctx)), Commands.CfgApTimeoutReset => ctx.Execute(null, m => m.ResetAutoproxyTimeout(ctx)), Commands.CfgApTimeoutUpdate(var param, _) => ctx.Execute(null, m => m.EditAutoproxyTimeout(ctx, param.timeout)), + Commands.CfgTimezoneShow => ctx.Execute(null, m => m.ViewSystemTimezone(ctx)), + Commands.CfgTimezoneReset => ctx.Execute(null, m => m.ResetSystemTimezone(ctx)), + Commands.CfgTimezoneUpdate(var param, _) => ctx.Execute(null, m => m.EditSystemTimezone(ctx, param.timezone)), + Commands.CfgPingShow => ctx.Execute(null, m => m.ViewSystemPing(ctx)), + Commands.CfgPingUpdate(var param, _) => ctx.Execute(null, m => m.EditSystemPing(ctx, param.toggle)), + Commands.CfgMemberPrivacyShow => ctx.Execute(null, m => m.ViewMemberDefaultPrivacy(ctx)), + Commands.CfgMemberPrivacyUpdate(var param, _) => ctx.Execute(null, m => m.EditMemberDefaultPrivacy(ctx, param.toggle)), + Commands.CfgGroupPrivacyShow => ctx.Execute(null, m => m.ViewGroupDefaultPrivacy(ctx)), + Commands.CfgGroupPrivacyUpdate(var param, _) => ctx.Execute(null, m => m.EditGroupDefaultPrivacy(ctx, param.toggle)), + Commands.CfgShowPrivateInfoShow => ctx.Execute(null, m => m.ViewShowPrivateInfo(ctx)), + Commands.CfgShowPrivateInfoUpdate(var param, _) => ctx.Execute(null, m => m.EditShowPrivateInfo(ctx, param.toggle)), + Commands.CfgCaseSensitiveProxyTagsShow => ctx.Execute(null, m => m.ViewCaseSensitiveProxyTags(ctx)), + Commands.CfgCaseSensitiveProxyTagsUpdate(var param, _) => ctx.Execute(null, m => m.EditCaseSensitiveProxyTags(ctx, param.toggle)), + Commands.CfgProxyErrorMessageShow => ctx.Execute(null, m => m.ViewProxyErrorMessageEnabled(ctx)), + Commands.CfgProxyErrorMessageUpdate(var param, _) => ctx.Execute(null, m => m.EditProxyErrorMessageEnabled(ctx, param.toggle)), + Commands.CfgHidSplitShow => ctx.Execute(null, m => m.ViewHidDisplaySplit(ctx)), + Commands.CfgHidSplitUpdate(var param, _) => ctx.Execute(null, m => m.EditHidDisplaySplit(ctx, param.toggle)), + Commands.CfgHidCapsShow => ctx.Execute(null, m => m.ViewHidDisplayCaps(ctx)), + Commands.CfgHidCapsUpdate(var param, _) => ctx.Execute(null, m => m.EditHidDisplayCaps(ctx, param.toggle)), + Commands.CfgHidPaddingShow => ctx.Execute(null, m => m.ViewHidListPadding(ctx)), + Commands.CfgHidPaddingUpdate(var param, _) => ctx.Execute(null, m => m.EditHidListPadding(ctx, param.padding)), + Commands.CfgCardShowColorHexShow => ctx.Execute(null, m => m.ViewCardShowColorHex(ctx)), + Commands.CfgCardShowColorHexUpdate(var param, _) => ctx.Execute(null, m => m.EditCardShowColorHex(ctx, param.toggle)), + Commands.CfgProxySwitchShow => ctx.Execute(null, m => m.ViewProxySwitch(ctx)), + Commands.CfgProxySwitchUpdate(var param, _) => ctx.Execute(null, m => m.EditProxySwitch(ctx, param.proxy_switch_action)), + Commands.CfgNameFormatShow => ctx.Execute(null, m => m.ViewNameFormat(ctx)), + Commands.CfgNameFormatReset => ctx.Execute(null, m => m.ResetNameFormat(ctx)), + Commands.CfgNameFormatUpdate(var param, _) => ctx.Execute(null, m => m.EditNameFormat(ctx, param.format)), + Commands.CfgServerNameFormatShow(_, var flags) => ctx.Execute(null, m => m.ViewServerNameFormat(ctx, flags.GetReplyFormat())), + Commands.CfgServerNameFormatReset => ctx.Execute(null, m => m.ResetServerNameFormat(ctx)), + Commands.CfgServerNameFormatUpdate(var param, _) => ctx.Execute(null, m => m.EditServerNameFormat(ctx, param.format)), + Commands.CfgLimitsUpdate => ctx.Execute(null, m => m.LimitUpdate(ctx)), Commands.FunThunder => ctx.Execute(null, m => m.Thunder(ctx)), Commands.FunMeow => ctx.Execute(null, m => m.Meow(ctx)), Commands.FunPokemon => ctx.Execute(null, m => m.Mn(ctx)), @@ -187,8 +220,8 @@ public partial class CommandTree ? ctx.Execute(GroupRandom, m => m.Group(ctx, param.target, flags.all, flags.show_embed)) : ctx.Execute(MemberRandom, m => m.Member(ctx, param.target, flags.all, flags.show_embed)), Commands.GroupRandomMember(var param, var flags) => ctx.Execute(GroupMemberRandom, m => m.GroupMember(ctx, param.target, flags)), - Commands.SystemLink => ctx.Execute(Link, m => m.LinkSystem(ctx)), - Commands.SystemUnlink(var param, _) => ctx.Execute(Unlink, m => m.UnlinkAccount(ctx, param.target)), + Commands.SystemLink(var param, _) => ctx.Execute(Link, m => m.LinkSystem(ctx, param.account)), + Commands.SystemUnlink(var param, _) => ctx.Execute(Unlink, m => m.UnlinkAccount(ctx, param.account)), Commands.SystemMembersListSelf(var param, var flags) => ctx.Execute(SystemList, m => m.MemberList(ctx, ctx.System, null, flags)), Commands.SystemMembersSearchSelf(var param, var flags) => ctx.Execute(SystemFind, m => m.MemberList(ctx, ctx.System, param.query, flags)), Commands.SystemMembersList(var param, var flags) => ctx.Execute(SystemList, m => m.MemberList(ctx, param.target, null, flags)), @@ -279,8 +312,6 @@ public partial class CommandTree }; if (ctx.Match("commands", "cmd", "c")) return CommandHelpRoot(ctx); - if (ctx.Match("config", "cfg", "configure")) - return HandleConfigCommand(ctx); if (ctx.Match("serverconfig", "guildconfig", "scfg")) return HandleServerConfigCommand(ctx); if (ctx.Match("log")) @@ -371,49 +402,6 @@ public partial class CommandTree } } - private Task HandleConfigCommand(Context ctx) - { - if (ctx.System == null) - return ctx.Reply($"{Emojis.Error} {Errors.NoSystemError(ctx.DefaultPrefix).Message}"); - - if (!ctx.HasNext()) - return ctx.Execute(null, m => m.ShowConfig(ctx)); - - if (ctx.Match("timezone", "zone", "tz")) - return ctx.Execute(null, m => m.SystemTimezone(ctx)); - if (ctx.Match("ping")) - return ctx.Execute(null, m => m.SystemPing(ctx)); - if (ctx.MatchMultiple(new[] { "private" }, new[] { "member" }) || ctx.Match("mp")) - return ctx.Execute(null, m => m.MemberDefaultPrivacy(ctx)); - if (ctx.MatchMultiple(new[] { "private" }, new[] { "group" }) || ctx.Match("gp")) - return ctx.Execute(null, m => m.GroupDefaultPrivacy(ctx)); - if (ctx.MatchMultiple(new[] { "show" }, new[] { "private" }) || ctx.Match("sp")) - return ctx.Execute(null, m => m.ShowPrivateInfo(ctx)); - if (ctx.MatchMultiple(new[] { "proxy" }, new[] { "case" })) - return ctx.Execute(null, m => m.CaseSensitiveProxyTags(ctx)); - if (ctx.MatchMultiple(new[] { "proxy" }, new[] { "error" }) || ctx.Match("pe")) - return ctx.Execute(null, m => m.ProxyErrorMessageEnabled(ctx)); - if (ctx.MatchMultiple(new[] { "split" }, new[] { "id", "ids" }) || ctx.Match("sid", "sids")) - return ctx.Execute(null, m => m.HidDisplaySplit(ctx)); - if (ctx.MatchMultiple(new[] { "cap", "caps", "capitalize", "capitalise" }, new[] { "id", "ids" }) || ctx.Match("capid", "capids")) - return ctx.Execute(null, m => m.HidDisplayCaps(ctx)); - if (ctx.MatchMultiple(new[] { "pad" }, new[] { "id", "ids" }) || ctx.MatchMultiple(new[] { "id" }, new[] { "pad", "padding" }) || ctx.Match("idpad", "padid", "padids")) - return ctx.Execute(null, m => m.HidListPadding(ctx)); - if (ctx.MatchMultiple(new[] { "show" }, new[] { "color", "colour", "colors", "colours" }) || ctx.Match("showcolor", "showcolour", "showcolors", "showcolours", "colorcode", "colorhex")) - return ctx.Execute(null, m => m.CardShowColorHex(ctx)); - if (ctx.MatchMultiple(new[] { "name" }, new[] { "format" }) || ctx.Match("nameformat", "nf")) - return ctx.Execute(null, m => m.NameFormat(ctx)); - if (ctx.MatchMultiple(new[] { "member", "group" }, new[] { "limit" }) || ctx.Match("limit")) - return ctx.Execute(null, m => m.LimitUpdate(ctx)); - if (ctx.MatchMultiple(new[] { "proxy" }, new[] { "switch" }) || ctx.Match("proxyswitch", "ps")) - return ctx.Execute(null, m => m.ProxySwitch(ctx)); - if (ctx.MatchMultiple(new[] { "server" }, new[] { "name" }, new[] { "format" }) || ctx.MatchMultiple(new[] { "server", "servername" }, new[] { "format", "nameformat", "nf" }) || ctx.Match("snf", "servernf", "servernameformat", "snameformat")) - return ctx.Execute(null, m => m.ServerNameFormat(ctx)); - - // todo: maybe add the list of configuration keys here? - return ctx.Reply($"{Emojis.Error} Could not find a setting with that name. Please see `{ctx.DefaultPrefix}commands config` for the list of possible config settings."); - } - private Task HandleServerConfigCommand(Context ctx) { if (!ctx.HasNext()) diff --git a/PluralKit.Bot/CommandSystem/Context/ContextParametersExt.cs b/PluralKit.Bot/CommandSystem/Context/ContextParametersExt.cs index 53e6de76..61086919 100644 --- a/PluralKit.Bot/CommandSystem/Context/ContextParametersExt.cs +++ b/PluralKit.Bot/CommandSystem/Context/ContextParametersExt.cs @@ -101,6 +101,14 @@ public static class ContextParametersExt ); } + public static async Task ParamResolveProxySwitchAction(this Context ctx, string param_name) + { + return await ctx.Parameters.ResolveParameter( + ctx, param_name, + param => (param as Parameter.ProxySwitchAction)?.action + ); + } + public static async Task ParamResolveToggle(this Context ctx, string param_name) { return await ctx.Parameters.ResolveParameter( diff --git a/PluralKit.Bot/CommandSystem/Parameters.cs b/PluralKit.Bot/CommandSystem/Parameters.cs index d6ae35e4..b359e80b 100644 --- a/PluralKit.Bot/CommandSystem/Parameters.cs +++ b/PluralKit.Bot/CommandSystem/Parameters.cs @@ -26,6 +26,7 @@ public abstract record Parameter() public record Opaque(string value): Parameter; public record Number(int value): Parameter; public record Avatar(ParsedImage avatar): Parameter; + public record ProxySwitchAction(SystemConfig.ProxySwitchAction action): Parameter; } public class Parameters @@ -122,6 +123,19 @@ public class Parameters return new Parameter.SystemPrivacyTarget(systemPrivacy); case uniffi.commands.Parameter.PrivacyLevel privacyLevel: return new Parameter.PrivacyLevel(privacyLevel.level == "public" ? PrivacyLevel.Public : privacyLevel.level == "private" ? PrivacyLevel.Private : throw new PKError($"Invalid privacy level {privacyLevel.level}")); + case uniffi.commands.Parameter.ProxySwitchAction(var action): + SystemConfig.ProxySwitchAction newVal; + + if (action.Equals("off", StringComparison.InvariantCultureIgnoreCase)) + newVal = SystemConfig.ProxySwitchAction.Off; + else if (action.Equals("new", StringComparison.InvariantCultureIgnoreCase) || action.Equals("n", StringComparison.InvariantCultureIgnoreCase) || action.Equals("on", StringComparison.InvariantCultureIgnoreCase)) + newVal = SystemConfig.ProxySwitchAction.New; + else if (action.Equals("add", StringComparison.InvariantCultureIgnoreCase) || action.Equals("a", StringComparison.InvariantCultureIgnoreCase)) + newVal = SystemConfig.ProxySwitchAction.Add; + else + throw new PKError("You must pass either \"new\", \"add\", or \"off\" to this command."); + + return new Parameter.ProxySwitchAction(newVal); case uniffi.commands.Parameter.Toggle toggle: return new Parameter.Toggle(toggle.toggle); case uniffi.commands.Parameter.OpaqueString opaque: diff --git a/PluralKit.Bot/Commands/Config.cs b/PluralKit.Bot/Commands/Config.cs index 65d1cd9e..ff34e3d8 100644 --- a/PluralKit.Bot/Commands/Config.cs +++ b/PluralKit.Bot/Commands/Config.cs @@ -273,25 +273,26 @@ public class Config await ctx.Reply($"{Emojis.Success} Latch timeout set to {newTimeout.ToTimeSpan().Humanize(4)}."); } - public async Task SystemTimezone(Context ctx) + public async Task ViewSystemTimezone(Context ctx) { if (ctx.System == null) throw Errors.NoSystemError(ctx.DefaultPrefix); - if (ctx.MatchClear()) - { - await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { UiTz = "UTC" }); + await ctx.Reply( + $"Your current system time zone is set to **{ctx.Config.UiTz}**. It is currently **{SystemClock.Instance.GetCurrentInstant().FormatZoned(ctx.Config.Zone)}** in that time zone. To change your system time zone, type `{ctx.DefaultPrefix}config tz `."); + } - await ctx.Reply($"{Emojis.Success} System time zone cleared (set to UTC)."); - return; - } + public async Task ResetSystemTimezone(Context ctx) + { + if (ctx.System == null) throw Errors.NoSystemError(ctx.DefaultPrefix); - var zoneStr = ctx.RemainderOrNull(); - if (zoneStr == null) - { - await ctx.Reply( - $"Your current system time zone is set to **{ctx.Config.UiTz}**. It is currently **{SystemClock.Instance.GetCurrentInstant().FormatZoned(ctx.Config.Zone)}** in that time zone. To change your system time zone, type `{ctx.DefaultPrefix}config tz `."); - return; - } + await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { UiTz = "UTC" }); + + await ctx.Reply($"{Emojis.Success} System time zone cleared (set to UTC)."); + } + + public async Task EditSystemTimezone(Context ctx, string zoneStr) + { + if (ctx.System == null) throw Errors.NoSystemError(ctx.DefaultPrefix); var zone = await FindTimeZone(ctx, zoneStr); if (zone == null) throw Errors.InvalidTimeZone(zoneStr); @@ -365,27 +366,24 @@ public class Config }); } - public async Task SystemPing(Context ctx) + public async Task ViewSystemPing(Context ctx) { // note: this is here because this is also used in `pk;system ping`, which does not CheckSystem ctx.CheckSystem(); - // todo: move all the other config settings to this format + await ctx.Reply($"Reaction pings are currently **{EnabledDisabled(ctx.Config.PingsEnabled)}** for your system. " + + $"To {EnabledDisabled(!ctx.Config.PingsEnabled)[..^1]} reaction pings, type `{ctx.DefaultPrefix}config ping {EnabledDisabled(!ctx.Config.PingsEnabled)[..^1]}`."); + } - String Response(bool isError, bool val) - => $"Reaction pings are {(isError ? "already" : "currently")} **{EnabledDisabled(val)}** for your system. " - + $"To {EnabledDisabled(!val)[..^1]} reaction pings, type `{ctx.DefaultPrefix}config ping {EnabledDisabled(!val)[..^1]}`."; - - if (!ctx.HasNext()) - { - await ctx.Reply(Response(false, ctx.Config.PingsEnabled)); - return; - } - - var value = ctx.MatchToggle(true); + public async Task EditSystemPing(Context ctx, bool value) + { + ctx.CheckSystem(); if (ctx.Config.PingsEnabled == value) - await ctx.Reply(Response(true, ctx.Config.PingsEnabled)); + { + await ctx.Reply($"Reaction pings are already **{EnabledDisabled(ctx.Config.PingsEnabled)}** for your system. " + + $"To {EnabledDisabled(!value)[..^1]} reaction pings, type `{ctx.DefaultPrefix}config ping {EnabledDisabled(!value)[..^1]}`."); + } else { await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { PingsEnabled = value }); @@ -393,230 +391,182 @@ public class Config } } - public async Task MemberDefaultPrivacy(Context ctx) + public async Task ViewMemberDefaultPrivacy(Context ctx) { - if (!ctx.HasNext()) - { - if (ctx.Config.MemberDefaultPrivate) { await ctx.Reply($"Newly created members will currently have their privacy settings set to private. To change this, type `{ctx.DefaultPrefix}config private member off`"); } - else { await ctx.Reply($"Newly created members will currently have their privacy settings set to public. To automatically set new members' privacy settings to private, type `{ctx.DefaultPrefix}config private member on`"); } - } + if (ctx.Config.MemberDefaultPrivate) + await ctx.Reply($"Newly created members will currently have their privacy settings set to private. To change this, type `{ctx.DefaultPrefix}config private member off`"); else - { - if (ctx.MatchToggle(false)) - { - await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { MemberDefaultPrivate = true }); - - await ctx.Reply("Newly created members will now have their privacy settings set to private."); - } - else - { - await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { MemberDefaultPrivate = false }); - - await ctx.Reply("Newly created members will now have their privacy settings set to public."); - } - } + await ctx.Reply($"Newly created members will currently have their privacy settings set to public. To automatically set new members' privacy settings to private, type `{ctx.DefaultPrefix}config private member on`"); } - public async Task GroupDefaultPrivacy(Context ctx) + public async Task EditMemberDefaultPrivacy(Context ctx, bool value) { - if (!ctx.HasNext()) - { - if (ctx.Config.GroupDefaultPrivate) { await ctx.Reply($"Newly created groups will currently have their privacy settings set to private. To change this, type `{ctx.DefaultPrefix}config private group off`"); } - else { await ctx.Reply($"Newly created groups will currently have their privacy settings set to public. To automatically set new groups' privacy settings to private, type `{ctx.DefaultPrefix}config private group on`"); } - } + await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { MemberDefaultPrivate = value }); + + if (value) + await ctx.Reply("Newly created members will now have their privacy settings set to private."); else - { - if (ctx.MatchToggle(false)) - { - await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { GroupDefaultPrivate = true }); - - await ctx.Reply("Newly created groups will now have their privacy settings set to private."); - } - else - { - await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { GroupDefaultPrivate = false }); - - await ctx.Reply("Newly created groups will now have their privacy settings set to public."); - } - } + await ctx.Reply("Newly created members will now have their privacy settings set to public."); } - public async Task ShowPrivateInfo(Context ctx) + public async Task ViewGroupDefaultPrivacy(Context ctx) { - if (!ctx.HasNext()) - { - if (ctx.Config.ShowPrivateInfo) await ctx.Reply("Private information is currently **shown** when looking up your own info. Use the `-public` flag to hide it."); - else await ctx.Reply("Private information is currently **hidden** when looking up your own info. Use the `-private` flag to show it."); - return; - } + if (ctx.Config.GroupDefaultPrivate) + await ctx.Reply($"Newly created groups will currently have their privacy settings set to private. To change this, type `{ctx.DefaultPrefix}config private group off`"); + else + await ctx.Reply($"Newly created groups will currently have their privacy settings set to public. To automatically set new groups' privacy settings to private, type `{ctx.DefaultPrefix}config private group on`"); + } - if (ctx.MatchToggle(true)) - { - await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { ShowPrivateInfo = true }); + public async Task EditGroupDefaultPrivacy(Context ctx, bool value) + { + await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { GroupDefaultPrivate = value }); + if (value) + await ctx.Reply("Newly created groups will now have their privacy settings set to private."); + else + await ctx.Reply("Newly created groups will now have their privacy settings set to public."); + } + + public async Task ViewShowPrivateInfo(Context ctx) + { + if (ctx.Config.ShowPrivateInfo) + await ctx.Reply("Private information is currently **shown** when looking up your own info. Use the `-public` flag to hide it."); + else + await ctx.Reply("Private information is currently **hidden** when looking up your own info. Use the `-private` flag to show it."); + } + + public async Task EditShowPrivateInfo(Context ctx, bool value) + { + await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { ShowPrivateInfo = value }); + + if (value) await ctx.Reply("Private information will now be **shown** when looking up your own info. Use the `-public` flag to hide it."); - } else - { - await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { ShowPrivateInfo = false }); - await ctx.Reply("Private information will now be **hidden** when looking up your own info. Use the `-private` flag to show it."); - } } - public async Task CaseSensitiveProxyTags(Context ctx) + public async Task ViewCaseSensitiveProxyTags(Context ctx) { - if (!ctx.HasNext()) - { - if (ctx.Config.CaseSensitiveProxyTags) { await ctx.Reply("Proxy tags are currently case **sensitive**."); } - else { await ctx.Reply("Proxy tags are currently case **insensitive**."); } - return; - } + if (ctx.Config.CaseSensitiveProxyTags) + await ctx.Reply("Proxy tags are currently case **sensitive**."); + else + await ctx.Reply("Proxy tags are currently case **insensitive**."); + } - if (ctx.MatchToggle(true)) - { - await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { CaseSensitiveProxyTags = true }); + public async Task EditCaseSensitiveProxyTags(Context ctx, bool value) + { + await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { CaseSensitiveProxyTags = value }); + if (value) await ctx.Reply("Proxy tags are now case sensitive."); - } else - { - await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { CaseSensitiveProxyTags = false }); - await ctx.Reply("Proxy tags are now case insensitive."); - } } - public async Task ProxyErrorMessageEnabled(Context ctx) + public async Task ViewProxyErrorMessageEnabled(Context ctx) { - if (!ctx.HasNext()) - { - if (ctx.Config.ProxyErrorMessageEnabled) { await ctx.Reply("Proxy error messages are currently **enabled**."); } - else { await ctx.Reply("Proxy error messages are currently **disabled**. Messages that fail to proxy (due to message or attachment size) will not throw an error message."); } - return; - } - - if (ctx.MatchToggle(true)) - { - await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { ProxyErrorMessageEnabled = true }); - - await ctx.Reply("Proxy error messages are now enabled."); - } + if (ctx.Config.ProxyErrorMessageEnabled) + await ctx.Reply("Proxy error messages are currently **enabled**."); else - { - await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { ProxyErrorMessageEnabled = false }); + await ctx.Reply("Proxy error messages are currently **disabled**. Messages that fail to proxy (due to message or attachment size) will not throw an error message."); + } + public async Task EditProxyErrorMessageEnabled(Context ctx, bool value) + { + await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { ProxyErrorMessageEnabled = value }); + + if (value) + await ctx.Reply("Proxy error messages are now enabled."); + else await ctx.Reply("Proxy error messages are now disabled. Messages that fail to proxy (due to message or attachment size) will not throw an error message."); - } } - public async Task HidDisplaySplit(Context ctx) + public async Task ViewHidDisplaySplit(Context ctx) { - if (!ctx.HasNext()) - { - var msg = $"Splitting of 6-character IDs with a hyphen is currently **{EnabledDisabled(ctx.Config.HidDisplaySplit)}**."; - await ctx.Reply(msg); - return; - } - - var newVal = ctx.MatchToggle(false); - await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { HidDisplaySplit = newVal }); - await ctx.Reply($"Splitting of 6-character IDs with a hyphen is now {EnabledDisabled(newVal)}."); + await ctx.Reply($"Splitting of 6-character IDs with a hyphen is currently **{EnabledDisabled(ctx.Config.HidDisplaySplit)}**."); } - public async Task HidDisplayCaps(Context ctx) + public async Task EditHidDisplaySplit(Context ctx, bool value) { - if (!ctx.HasNext()) - { - var msg = $"Displaying IDs as capital letters is currently **{EnabledDisabled(ctx.Config.HidDisplayCaps)}**."; - await ctx.Reply(msg); - return; - } - - var newVal = ctx.MatchToggle(false); - await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { HidDisplayCaps = newVal }); - await ctx.Reply($"Displaying IDs as capital letters is now {EnabledDisabled(newVal)}."); + await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { HidDisplaySplit = value }); + await ctx.Reply($"Splitting of 6-character IDs with a hyphen is now {EnabledDisabled(value)}."); } - public async Task HidListPadding(Context ctx) + public async Task ViewHidDisplayCaps(Context ctx) { - if (!ctx.HasNext()) - { - string message; - switch (ctx.Config.HidListPadding) - { - case SystemConfig.HidPadFormat.None: message = "Padding 5-character IDs in lists is currently disabled."; break; - case SystemConfig.HidPadFormat.Left: message = "5-character IDs displayed in lists will have a padding space added to the beginning."; break; - case SystemConfig.HidPadFormat.Right: message = "5-character IDs displayed in lists will have a padding space added to the end."; break; - default: throw new Exception("unreachable"); - } - await ctx.Reply(message); - return; - } + await ctx.Reply($"Displaying IDs as capital letters is currently **{EnabledDisabled(ctx.Config.HidDisplayCaps)}**."); + } + public async Task EditHidDisplayCaps(Context ctx, bool value) + { + await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { HidDisplayCaps = value }); + await ctx.Reply($"Displaying IDs as capital letters is now {EnabledDisabled(value)}."); + } + + public async Task ViewHidListPadding(Context ctx) + { + string message = ctx.Config.HidListPadding switch + { + SystemConfig.HidPadFormat.None => "Padding 5-character IDs in lists is currently disabled.", + SystemConfig.HidPadFormat.Left => "5-character IDs displayed in lists will have a padding space added to the beginning.", + SystemConfig.HidPadFormat.Right => "5-character IDs displayed in lists will have a padding space added to the end.", + _ => throw new Exception("unreachable") + }; + await ctx.Reply(message); + } + + public async Task EditHidListPadding(Context ctx, string padding) + { var badInputError = "Valid padding settings are `left`, `right`, or `off`."; - var toggleOff = ctx.MatchToggleOrNull(false); - - switch (toggleOff) + if (padding.Equals("off", StringComparison.InvariantCultureIgnoreCase)) { - case true: throw new PKError(badInputError); - case false: - { - await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { HidListPadding = SystemConfig.HidPadFormat.None }); - await ctx.Reply("Padding 5-character IDs in lists has been disabled."); - return; - } + await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { HidListPadding = SystemConfig.HidPadFormat.None }); + await ctx.Reply("Padding 5-character IDs in lists has been disabled."); } - - if (ctx.Match("left", "l")) + else if (padding.Equals("left", StringComparison.InvariantCultureIgnoreCase) || padding.Equals("l", StringComparison.InvariantCultureIgnoreCase)) { await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { HidListPadding = SystemConfig.HidPadFormat.Left }); await ctx.Reply("5-character IDs displayed in lists will now have a padding space added to the beginning."); } - else if (ctx.Match("right", "r")) + else if (padding.Equals("right", StringComparison.InvariantCultureIgnoreCase) || padding.Equals("r", StringComparison.InvariantCultureIgnoreCase)) { await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { HidListPadding = SystemConfig.HidPadFormat.Right }); await ctx.Reply("5-character IDs displayed in lists will now have a padding space added to the end."); } - else throw new PKError(badInputError); + else + { + throw new PKError(badInputError); + } } - public async Task CardShowColorHex(Context ctx) + public async Task ViewCardShowColorHex(Context ctx) { - if (!ctx.HasNext()) - { - var msg = $"Showing color codes on system/member/group cards is currently **{EnabledDisabled(ctx.Config.CardShowColorHex)}**."; - await ctx.Reply(msg); - return; - } - - var newVal = ctx.MatchToggle(false); - await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { CardShowColorHex = newVal }); - await ctx.Reply($"Showing color codes on system/member/group cards is now {EnabledDisabled(newVal)}."); + await ctx.Reply($"Showing color codes on system/member/group cards is currently **{EnabledDisabled(ctx.Config.CardShowColorHex)}**."); } - public async Task ProxySwitch(Context ctx) + public async Task EditCardShowColorHex(Context ctx, bool value) { - if (!ctx.HasNext()) + await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { CardShowColorHex = value }); + await ctx.Reply($"Showing color codes on system/member/group cards is now {EnabledDisabled(value)}."); + } + + public async Task ViewProxySwitch(Context ctx) + { + string msg = ctx.Config.ProxySwitch switch { - string msg = ctx.Config.ProxySwitch switch - { - SystemConfig.ProxySwitchAction.Off => "Currently, when you proxy as a member, no switches are logged or changed.", - SystemConfig.ProxySwitchAction.New => "When you proxy as a member, currently it makes a new switch.", - SystemConfig.ProxySwitchAction.Add => "When you proxy as a member, currently it adds them to the current switch.", - _ => throw new Exception("unreachable"), - }; - await ctx.Reply(msg); - return; - } + SystemConfig.ProxySwitchAction.Off => "Currently, when you proxy as a member, no switches are logged or changed.", + SystemConfig.ProxySwitchAction.New => "When you proxy as a member, currently it makes a new switch.", + SystemConfig.ProxySwitchAction.Add => "When you proxy as a member, currently it adds them to the current switch.", + _ => throw new Exception("unreachable"), + }; + await ctx.Reply(msg); + } - // toggle = false means off, toggle = true means new, otherwise if they said add that means add or if they said new they mean new. If none of those, error - var toggle = ctx.MatchToggleOrNull(false); - var newVal = toggle == false ? SystemConfig.ProxySwitchAction.Off : toggle == true ? SystemConfig.ProxySwitchAction.New : ctx.Match("add", "a") ? SystemConfig.ProxySwitchAction.Add : ctx.Match("new", "n") ? SystemConfig.ProxySwitchAction.New : throw new PKError("You must pass either \"new\", \"add\", or \"off\" to this command."); - - await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { ProxySwitch = newVal }); - switch (newVal) + public async Task EditProxySwitch(Context ctx, SystemConfig.ProxySwitchAction action) + { + await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { ProxySwitch = action }); + switch (action) { case SystemConfig.ProxySwitchAction.Off: await ctx.Reply("Now when you proxy as a member, no switches are logged or changed."); break; case SystemConfig.ProxySwitchAction.New: await ctx.Reply("When you proxy as a member, it now makes a new switch."); break; @@ -625,65 +575,61 @@ public class Config } } - public async Task NameFormat(Context ctx) + public async Task ViewNameFormat(Context ctx) { - var clearFlag = ctx.MatchClear(); - if (!ctx.HasNext() && !clearFlag) - { - await ctx.Reply($"Member names are currently formatted as `{ctx.Config.NameFormat ?? ProxyMember.DefaultFormat}`"); - return; - } + await ctx.Reply($"Member names are currently formatted as `{ctx.Config.NameFormat ?? ProxyMember.DefaultFormat}`"); + } - string formatString; - if (clearFlag) - formatString = ProxyMember.DefaultFormat; - else - formatString = ctx.RemainderOrNull(); + public async Task ResetNameFormat(Context ctx) + { + await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { NameFormat = ProxyMember.DefaultFormat }); + await ctx.Reply($"Member names are now formatted as `{ProxyMember.DefaultFormat}`"); + } + public async Task EditNameFormat(Context ctx, string formatString) + { await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { NameFormat = formatString }); await ctx.Reply($"Member names are now formatted as `{formatString}`"); } - public async Task ServerNameFormat(Context ctx) + public async Task ViewServerNameFormat(Context ctx, ReplyFormat format) { ctx.CheckGuildContext(); - var clearFlag = ctx.MatchClear(); - var format = ctx.MatchFormat(); - // if there's nothing next or what's next is raw/plaintext and we're not clearing, it's a query - if ((!ctx.HasNext() || format != ReplyFormat.Standard) && !clearFlag) - { - var guildCfg = await ctx.Repository.GetSystemGuild(ctx.Guild.Id, ctx.System.Id); - if (guildCfg.NameFormat == null) - await ctx.Reply("You do not have a specific name format set for this server and member names are formatted with your global name format."); - else - switch (format) - { - case ReplyFormat.Raw: - await ctx.Reply($"`{guildCfg.NameFormat}`"); - break; - case ReplyFormat.Plaintext: - var eb = new EmbedBuilder() - .Description($"Showing guild Name Format for system {ctx.System.DisplayHid(ctx.Config)}"); - await ctx.Reply(guildCfg.NameFormat, eb.Build()); - break; - default: - await ctx.Reply($"Your member names in this server are currently formatted as `{guildCfg.NameFormat}`"); - break; - } - return; - } - - string? formatString = null; - if (!clearFlag) - { - formatString = ctx.RemainderOrNull(); - } - await ctx.Repository.UpdateSystemGuild(ctx.System.Id, ctx.Guild.Id, new() { NameFormat = formatString }); - if (formatString == null) - await ctx.Reply($"Member names are now formatted with your global name format in this server."); + var guildCfg = await ctx.Repository.GetSystemGuild(ctx.Guild.Id, ctx.System.Id); + if (guildCfg.NameFormat == null) + await ctx.Reply("You do not have a specific name format set for this server and member names are formatted with your global name format."); else - await ctx.Reply($"Member names are now formatted as `{formatString}` in this server."); + switch (format) + { + case ReplyFormat.Raw: + await ctx.Reply($"`{guildCfg.NameFormat}`"); + break; + case ReplyFormat.Plaintext: + var eb = new EmbedBuilder() + .Description($"Showing guild Name Format for system {ctx.System.DisplayHid(ctx.Config)}"); + await ctx.Reply(guildCfg.NameFormat, eb.Build()); + break; + default: + await ctx.Reply($"Your member names in this server are currently formatted as `{guildCfg.NameFormat}`"); + break; + } + } + + public async Task ResetServerNameFormat(Context ctx) + { + ctx.CheckGuildContext(); + + await ctx.Repository.UpdateSystemGuild(ctx.System.Id, ctx.Guild.Id, new() { NameFormat = null }); + await ctx.Reply($"Member names are now formatted with your global name format in this server."); + } + + public async Task EditServerNameFormat(Context ctx, string formatString) + { + ctx.CheckGuildContext(); + + await ctx.Repository.UpdateSystemGuild(ctx.System.Id, ctx.Guild.Id, new() { NameFormat = formatString }); + await ctx.Reply($"Member names are now formatted as `{formatString}` in this server."); } public Task LimitUpdate(Context ctx) diff --git a/PluralKit.Bot/Commands/SystemLink.cs b/PluralKit.Bot/Commands/SystemLink.cs index 8b4b1881..38a0cc47 100644 --- a/PluralKit.Bot/Commands/SystemLink.cs +++ b/PluralKit.Bot/Commands/SystemLink.cs @@ -1,4 +1,5 @@ using Myriad.Extensions; +using Myriad.Types; using PluralKit.Core; @@ -6,12 +7,10 @@ namespace PluralKit.Bot; public class SystemLink { - public async Task LinkSystem(Context ctx) + public async Task LinkSystem(Context ctx, User account) { ctx.CheckSystem(); - var account = await ctx.MatchUser() ?? - throw new PKSyntaxError("You must pass an account to link with (either ID or @mention)."); var accountIds = await ctx.Repository.GetSystemAccounts(ctx.System.Id); if (accountIds.Contains(account.Id)) throw Errors.AccountAlreadyLinked; diff --git a/crates/command_definitions/src/config.rs b/crates/command_definitions/src/config.rs index b6dca8f6..e8f4d625 100644 --- a/crates/command_definitions/src/config.rs +++ b/crates/command_definitions/src/config.rs @@ -3,13 +3,85 @@ use command_parser::parameter; use super::*; pub fn cmds() -> impl Iterator { - let cfg = ("config", ["cfg"]); + let cfg = ("config", ["cfg", "configure"]); let ap = tokens!(cfg, ("autoproxy", ["ap"])); let ap_account = tokens!(ap, ("account", ["ac"])); let ap_timeout = tokens!(ap, ("timeout", ["tm"])); + let timezone = tokens!(cfg, ("timezone", ["zone", "tz"])); + let ping = tokens!(cfg, ("ping", ["ping"])); + + let priv_ = ("private", ["priv"]); + let member_privacy = tokens!(cfg, priv_, ("member", ["mem"])); + let member_privacy_short = tokens!(cfg, ("mp", ["mp"])); + let group_privacy = tokens!(cfg, priv_, ("group", ["grp"])); + let group_privacy_short = tokens!(cfg, ("gp", ["gp"])); + + let show = ("show", ["show"]); + let show_private = tokens!(cfg, show, priv_); + let show_private_short = tokens!(cfg, ("sp", ["sp"])); + + let proxy = ("proxy", ["px"]); + let proxy_case = tokens!(cfg, proxy, ("case", ["caps", "capitalize", "capitalise"])); + let proxy_error = tokens!(cfg, proxy, ("error", ["errors"])); + let proxy_error_short = tokens!(cfg, ("pe", ["pe"])); + + let id = ("id", ["ids"]); + let split_id = tokens!(cfg, ("split", ["split"]), id); + let split_id_short = tokens!(cfg, ("sid", ["sid", "sids"])); + let cap_id = tokens!(cfg, ("cap", ["caps", "capitalize", "capitalise"]), id); + let cap_id_short = tokens!(cfg, ("capid", ["capid", "capids"])); + + let pad = ("pad", ["padding"]); + let pad_id = tokens!(cfg, pad, id); + let id_pad = tokens!(cfg, id, pad); + let id_pad_short = tokens!(cfg, ("idpad", ["idpad", "padid", "padids"])); + + let show_color = tokens!(cfg, show, ("color", ["colour", "colors", "colours"])); + let show_color_short = tokens!( + cfg, + ( + "showcolor", + [ + "showcolour", + "showcolors", + "showcolours", + "colorcode", + "colorhex" + ] + ) + ); + + let proxy_switch = tokens!(cfg, ("proxy", ["proxy"]), ("switch", ["switch"])); + let proxy_switch_short = tokens!(cfg, ("proxyswitch", ["proxyswitch", "ps"])); + + let format = ("format", ["format"]); + let name_format = tokens!(cfg, ("name", ["name"]), format); + let name_format_short = tokens!(cfg, ("nameformat", ["nameformat", "nf"])); + + let server = ("server", ["server"]); + let server_name_format = tokens!(cfg, server, ("name", ["name"]), format); + let server_format = tokens!( + cfg, + ("server", ["server", "servername"]), + ("format", ["format", "nameformat", "nf"]) + ); + let server_format_short = tokens!( + cfg, + ( + "snf", + ["snf", "servernf", "servernameformat", "snameformat"] + ) + ); + + let limit_ = ("limit", ["limit", "lim"]); + let member_limit = tokens!(cfg, ("member", ["mem"]), limit_); + let group_limit = tokens!(cfg, ("group", ["grp"]), limit_); + let limit = tokens!(cfg, limit_); + [ + command!(cfg => "cfg_show").help("Shows the current configuration"), command!(ap_account => "cfg_ap_account_show") .help("Shows autoproxy status for the account"), command!(ap_account, Toggle => "cfg_ap_account_update") @@ -20,6 +92,115 @@ pub fn cmds() -> impl Iterator { .help("Disables the autoproxy timeout"), command!(ap_timeout, ("timeout", OpaqueString) => "cfg_ap_timeout_update") .help("Sets the autoproxy timeout"), + command!(timezone => "cfg_timezone_show").help("Shows the system timezone"), + command!(timezone, RESET => "cfg_timezone_reset").help("Resets the system timezone"), + command!(timezone, ("timezone", OpaqueString) => "cfg_timezone_update") + .help("Sets the system timezone"), + command!(ping => "cfg_ping_show").help("Shows the ping setting"), + command!(ping, Toggle => "cfg_ping_update").help("Updates the ping setting"), + command!(member_privacy => "cfg_member_privacy_show") + .help("Shows the default privacy for new members"), + command!(member_privacy, Toggle => "cfg_member_privacy_update") + .help("Sets the default privacy for new members"), + command!(member_privacy_short => "cfg_member_privacy_show") + .help("Shows the default privacy for new members"), + command!(member_privacy_short, Toggle => "cfg_member_privacy_update") + .help("Sets the default privacy for new members"), + command!(group_privacy => "cfg_group_privacy_show") + .help("Shows the default privacy for new groups"), + command!(group_privacy, Toggle => "cfg_group_privacy_update") + .help("Sets the default privacy for new groups"), + command!(group_privacy_short => "cfg_group_privacy_show") + .help("Shows the default privacy for new groups"), + command!(group_privacy_short, Toggle => "cfg_group_privacy_update") + .help("Sets the default privacy for new groups"), + command!(show_private => "cfg_show_private_info_show") + .help("Shows whether private info is shown"), + command!(show_private, Toggle => "cfg_show_private_info_update") + .help("Toggles showing private info"), + command!(show_private_short => "cfg_show_private_info_show") + .help("Shows whether private info is shown"), + command!(show_private_short, Toggle => "cfg_show_private_info_update") + .help("Toggles showing private info"), + command!(proxy_case => "cfg_case_sensitive_proxy_tags_show") + .help("Shows whether proxy tags are case-sensitive"), + command!(proxy_case, Toggle => "cfg_case_sensitive_proxy_tags_update") + .help("Toggles case sensitivity for proxy tags"), + command!(proxy_error => "cfg_proxy_error_message_show") + .help("Shows whether proxy error messages are enabled"), + command!(proxy_error, Toggle => "cfg_proxy_error_message_update") + .help("Toggles proxy error messages"), + command!(proxy_error_short => "cfg_proxy_error_message_show") + .help("Shows whether proxy error messages are enabled"), + command!(proxy_error_short, Toggle => "cfg_proxy_error_message_update") + .help("Toggles proxy error messages"), + command!(split_id => "cfg_hid_split_show").help("Shows whether IDs are split in lists"), + command!(split_id, Toggle => "cfg_hid_split_update").help("Toggles splitting IDs in lists"), + command!(split_id_short => "cfg_hid_split_show") + .help("Shows whether IDs are split in lists"), + command!(split_id_short, Toggle => "cfg_hid_split_update") + .help("Toggles splitting IDs in lists"), + command!(cap_id => "cfg_hid_caps_show").help("Shows whether IDs are capitalized in lists"), + command!(cap_id, Toggle => "cfg_hid_caps_update") + .help("Toggles capitalization of IDs in lists"), + command!(cap_id_short => "cfg_hid_caps_show") + .help("Shows whether IDs are capitalized in lists"), + command!(cap_id_short, Toggle => "cfg_hid_caps_update") + .help("Toggles capitalization of IDs in lists"), + command!(pad_id => "cfg_hid_padding_show").help("Shows the ID padding for lists"), + command!(pad_id, ("padding", OpaqueString) => "cfg_hid_padding_update") + .help("Sets the ID padding for lists"), + command!(id_pad => "cfg_hid_padding_show").help("Shows the ID padding for lists"), + command!(id_pad, ("padding", OpaqueString) => "cfg_hid_padding_update") + .help("Sets the ID padding for lists"), + command!(id_pad_short => "cfg_hid_padding_show").help("Shows the ID padding for lists"), + command!(id_pad_short, ("padding", OpaqueString) => "cfg_hid_padding_update") + .help("Sets the ID padding for lists"), + command!(show_color => "cfg_card_show_color_hex_show") + .help("Shows whether color hex codes are shown on cards"), + command!(show_color, Toggle => "cfg_card_show_color_hex_update") + .help("Toggles showing color hex codes on cards"), + command!(show_color_short => "cfg_card_show_color_hex_show") + .help("Shows whether color hex codes are shown on cards"), + command!(show_color_short, Toggle => "cfg_card_show_color_hex_update") + .help("Toggles showing color hex codes on cards"), + command!(proxy_switch => "cfg_proxy_switch_show").help("Shows the proxy switch behavior"), + command!(proxy_switch, ProxySwitchAction => "cfg_proxy_switch_update") + .help("Sets the proxy switch behavior"), + command!(proxy_switch_short => "cfg_proxy_switch_show") + .help("Shows the proxy switch behavior"), + command!(proxy_switch_short, ProxySwitchAction => "cfg_proxy_switch_update") + .help("Sets the proxy switch behavior"), + command!(name_format => "cfg_name_format_show").help("Shows the name format"), + command!(name_format, RESET => "cfg_name_format_reset").help("Resets the name format"), + command!(name_format, ("format", OpaqueString) => "cfg_name_format_update") + .help("Sets the name format"), + command!(name_format_short => "cfg_name_format_show").help("Shows the name format"), + command!(name_format_short, RESET => "cfg_name_format_reset") + .help("Resets the name format"), + command!(name_format_short, ("format", OpaqueString) => "cfg_name_format_update") + .help("Sets the name format"), + command!(server_name_format => "cfg_server_name_format_show") + .help("Shows the server name format"), + command!(server_name_format, RESET => "cfg_server_name_format_reset") + .help("Resets the server name format"), + command!(server_name_format, ("format", OpaqueString) => "cfg_server_name_format_update") + .help("Sets the server name format"), + command!(server_format => "cfg_server_name_format_show") + .help("Shows the server name format"), + command!(server_format, RESET => "cfg_server_name_format_reset") + .help("Resets the server name format"), + command!(server_format, ("format", OpaqueString) => "cfg_server_name_format_update") + .help("Sets the server name format"), + command!(server_format_short => "cfg_server_name_format_show") + .help("Shows the server name format"), + command!(server_format_short, RESET => "cfg_server_name_format_reset") + .help("Resets the server name format"), + command!(server_format_short, ("format", OpaqueString) => "cfg_server_name_format_update") + .help("Sets the server name format"), + command!(member_limit => "cfg_limits_update").help("Refreshes member/group limits"), + command!(group_limit => "cfg_limits_update").help("Refreshes member/group limits"), + command!(limit => "cfg_limits_update").help("Refreshes member/group limits"), ] .into_iter() } diff --git a/crates/command_definitions/src/system.rs b/crates/command_definitions/src/system.rs index 88dbb39b..4e12ceb9 100644 --- a/crates/command_definitions/src/system.rs +++ b/crates/command_definitions/src/system.rs @@ -252,8 +252,8 @@ pub fn edit() -> impl Iterator { .into_iter(); let system_link = [ - command!("link" => "system_link"), - command!("unlink", ("target", OpaqueString) => "system_unlink"), + command!("link", ("account", UserRef) => "system_link"), + command!("unlink", ("account", OpaqueString) => "system_unlink"), ] .into_iter(); diff --git a/crates/command_parser/src/parameter.rs b/crates/command_parser/src/parameter.rs index 04d035ea..77bfde8b 100644 --- a/crates/command_parser/src/parameter.rs +++ b/crates/command_parser/src/parameter.rs @@ -27,6 +27,7 @@ pub enum ParameterValue { PrivacyLevel(String), Toggle(bool), Avatar(String), + ProxySwitchAction(ProxySwitchAction), Null, } @@ -179,6 +180,9 @@ impl Parameter { .parse::() .map(ParameterValue::GuildRef) .map_err(|_| SmolStr::new("invalid guild ID")), + ParameterKind::ProxySwitchAction => ProxySwitchAction::from_str(input) + .map(ParameterValue::ProxySwitchAction) + .map_err(|_| SmolStr::new("invalid proxy switch action, must be new/add/off")), } } } @@ -208,8 +212,9 @@ impl Display for Parameter { ParameterKind::GroupPrivacyTarget => write!(f, ""), ParameterKind::SystemPrivacyTarget => write!(f, ""), ParameterKind::PrivacyLevel => write!(f, "[privacy level]"), - ParameterKind::Toggle => write!(f, "on/off"), + ParameterKind::Toggle => write!(f, ""), ParameterKind::Avatar => write!(f, ""), + ParameterKind::ProxySwitchAction => write!(f, ""), } } } @@ -290,6 +295,7 @@ pub enum ParameterKind { PrivacyLevel, Toggle, Avatar, + ProxySwitchAction, } impl ParameterKind { @@ -313,6 +319,7 @@ impl ParameterKind { ParameterKind::PrivacyLevel => "privacy_level", ParameterKind::Toggle => "toggle", ParameterKind::Avatar => "avatar", + ParameterKind::ProxySwitchAction => "proxy_switch_action", } } } @@ -521,3 +528,35 @@ impl Into for Toggle { } } } + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum ProxySwitchAction { + New, + Add, + Off, +} + +impl AsRef for ProxySwitchAction { + fn as_ref(&self) -> &str { + match self { + ProxySwitchAction::New => "new", + ProxySwitchAction::Add => "add", + ProxySwitchAction::Off => "off", + } + } +} + +impl FromStr for ProxySwitchAction { + type Err = SmolStr; + + fn from_str(s: &str) -> Result { + [ + ProxySwitchAction::New, + ProxySwitchAction::Add, + ProxySwitchAction::Off, + ] + .into_iter() + .find(|action| action.as_ref() == s) + .ok_or_else(|| SmolStr::new("invalid proxy switch action, must be new/add/off")) + } +} diff --git a/crates/commands/src/bin/write_cs_glue.rs b/crates/commands/src/bin/write_cs_glue.rs index f94aed77..d6486a71 100644 --- a/crates/commands/src/bin/write_cs_glue.rs +++ b/crates/commands/src/bin/write_cs_glue.rs @@ -276,6 +276,7 @@ fn get_param_ty(kind: ParameterKind) -> &'static str { ParameterKind::MessageRef => "Message.Reference", ParameterKind::ChannelRef => "Channel", ParameterKind::GuildRef => "Guild", + ParameterKind::ProxySwitchAction => "SystemConfig.ProxySwitchAction", } } @@ -298,6 +299,7 @@ fn get_param_param_ty(kind: ParameterKind) -> &'static str { ParameterKind::MessageRef => "Message", ParameterKind::ChannelRef => "Channel", ParameterKind::GuildRef => "Guild", + ParameterKind::ProxySwitchAction => "ProxySwitchAction", } } diff --git a/crates/commands/src/commands.udl b/crates/commands/src/commands.udl index 7fd3b312..f531f870 100644 --- a/crates/commands/src/commands.udl +++ b/crates/commands/src/commands.udl @@ -25,6 +25,7 @@ interface Parameter { OpaqueInt(i32 raw); Toggle(boolean toggle); Avatar(string avatar); + ProxySwitchAction(string action); Null(); }; dictionary ParsedCommand { diff --git a/crates/commands/src/lib.rs b/crates/commands/src/lib.rs index b91cf137..c78b0c69 100644 --- a/crates/commands/src/lib.rs +++ b/crates/commands/src/lib.rs @@ -75,6 +75,9 @@ pub enum Parameter { Avatar { avatar: String, }, + ProxySwitchAction { + action: String, + }, Null, } @@ -103,6 +106,9 @@ impl From for Parameter { ParameterValue::ChannelRef(channel_id) => Self::ChannelRef { channel_id }, ParameterValue::GuildRef(guild_id) => Self::GuildRef { guild_id }, ParameterValue::Null => Self::Null, + ParameterValue::ProxySwitchAction(action) => Self::ProxySwitchAction { + action: action.as_ref().to_string(), + }, } } }