diff --git a/PluralKit.Bot/CommandMeta/CommandTree.cs b/PluralKit.Bot/CommandMeta/CommandTree.cs index 000c3d27..1aefe854 100644 --- a/PluralKit.Bot/CommandMeta/CommandTree.cs +++ b/PluralKit.Bot/CommandMeta/CommandTree.cs @@ -281,6 +281,24 @@ public partial class CommandTree Commands.MessageReproxy(var param, _) => ctx.Execute(MessageReproxy, m => m.ReproxyMessage(ctx, param.msg.MessageId, param.member)), Commands.Import(var param, _) => ctx.Execute(Import, m => m.Import(ctx, param.url)), Commands.Export(_, _) => ctx.Execute(Export, m => m.Export(ctx)), + Commands.ServerConfigShow => ctx.Execute(null, m => m.ShowConfig(ctx)), + Commands.ServerConfigLogChannelShow => ctx.Execute(null, m => m.ShowLogChannel(ctx)), + Commands.ServerConfigLogChannelSet(var param, _) => ctx.Execute(null, m => m.SetLogChannel(ctx, param.channel)), + Commands.ServerConfigLogChannelClear => ctx.Execute(null, m => m.ClearLogChannel(ctx)), + Commands.ServerConfigLogCleanupShow => ctx.Execute(null, m => m.ShowLogCleanup(ctx)), + Commands.ServerConfigLogCleanupSet(var param, _) => ctx.Execute(null, m => m.SetLogCleanup(ctx, param.toggle)), + Commands.ServerConfigLogBlacklistShow => ctx.Execute(null, m => m.ShowLogBlacklist(ctx)), + Commands.ServerConfigLogBlacklistAdd(var param, var flags) => ctx.Execute(null, m => m.AddLogBlacklist(ctx, param.channel, flags.all)), + Commands.ServerConfigLogBlacklistRemove(var param, var flags) => ctx.Execute(null, m => m.RemoveLogBlacklist(ctx, param.channel, flags.all)), + Commands.ServerConfigProxyBlacklistShow => ctx.Execute(null, m => m.ShowProxyBlacklist(ctx)), + Commands.ServerConfigProxyBlacklistAdd(var param, var flags) => ctx.Execute(null, m => m.AddProxyBlacklist(ctx, param.channel, flags.all)), + Commands.ServerConfigProxyBlacklistRemove(var param, var flags) => ctx.Execute(null, m => m.RemoveProxyBlacklist(ctx, param.channel, flags.all)), + Commands.ServerConfigInvalidCommandResponseShow => ctx.Execute(null, m => m.ShowInvalidCommandResponse(ctx)), + Commands.ServerConfigInvalidCommandResponseSet(var param, _) => ctx.Execute(null, m => m.SetInvalidCommandResponse(ctx, param.toggle)), + Commands.ServerConfigRequireSystemTagShow => ctx.Execute(null, m => m.ShowRequireSystemTag(ctx)), + Commands.ServerConfigRequireSystemTagSet(var param, _) => ctx.Execute(null, m => m.SetRequireSystemTag(ctx, param.toggle)), + Commands.ServerConfigSuppressNotificationsShow => ctx.Execute(null, m => m.ShowSuppressNotifications(ctx)), + Commands.ServerConfigSuppressNotificationsSet(var param, _) => ctx.Execute(null, m => m.SetSuppressNotifications(ctx, param.toggle)), Commands.AdminUpdateSystemId(var param, _) => ctx.Execute(null, m => m.UpdateSystemId(ctx, param.target, param.new_hid)), Commands.AdminUpdateMemberId(var param, _) => ctx.Execute(null, m => m.UpdateMemberId(ctx, param.target, param.new_hid)), Commands.AdminUpdateGroupId(var param, _) => ctx.Execute(null, m => m.UpdateGroupId(ctx, param.target, param.new_hid)), @@ -310,32 +328,9 @@ public partial class CommandTree ctx.Reply( $"{Emojis.Error} Parsed command {ctx.Parameters.Callback().AsCode()} not implemented in PluralKit.Bot!"), }; + // Legacy command routing - these are kept for backwards compatibility until fully migrated to new system if (ctx.Match("commands", "cmd", "c")) return CommandHelpRoot(ctx); - if (ctx.Match("serverconfig", "guildconfig", "scfg")) - return HandleServerConfigCommand(ctx); - if (ctx.Match("log")) - if (ctx.Match("channel")) - return ctx.Execute(LogChannel, m => m.SetLogChannel(ctx), true); - else if (ctx.Match("enable", "on")) - return ctx.Execute(LogEnable, m => m.SetLogEnabled(ctx, true), true); - else if (ctx.Match("disable", "off")) - return ctx.Execute(LogDisable, m => m.SetLogEnabled(ctx, false), true); - else if (ctx.Match("list", "show")) - return ctx.Execute(LogShow, m => m.ShowLogDisabledChannels(ctx), true); - else - return ctx.Reply($"{Emojis.Warn} Message logging commands have moved to `{ctx.DefaultPrefix}serverconfig`."); - if (ctx.Match("logclean")) - return ctx.Execute(ServerConfigLogClean, m => m.SetLogCleanup(ctx), true); - if (ctx.Match("blacklist", "bl")) - if (ctx.Match("enable", "on", "add", "deny")) - return ctx.Execute(BlacklistAdd, m => m.SetProxyBlacklisted(ctx, true), true); - else if (ctx.Match("disable", "off", "remove", "allow")) - return ctx.Execute(BlacklistRemove, m => m.SetProxyBlacklisted(ctx, false), true); - else if (ctx.Match("list", "show")) - return ctx.Execute(BlacklistShow, m => m.ShowProxyBlacklisted(ctx), true); - else - return ctx.Reply($"{Emojis.Warn} Blacklist commands have moved to `{ctx.DefaultPrefix}serverconfig`."); if (ctx.Match("invite")) return ctx.Execute(Invite, m => m.Invite(ctx)); if (ctx.Match("stats", "status")) return ctx.Execute(null, m => m.Stats(ctx)); } @@ -401,42 +396,4 @@ public partial class CommandTree break; } } - - private Task HandleServerConfigCommand(Context ctx) - { - if (!ctx.HasNext()) - return ctx.Execute(null, m => m.ShowConfig(ctx)); - - if (ctx.MatchMultiple(new[] { "log" }, new[] { "cleanup", "clean" }) || ctx.Match("logclean")) - return ctx.Execute(null, m => m.SetLogCleanup(ctx)); - if (ctx.MatchMultiple(new[] { "invalid", "unknown" }, new[] { "command" }, new[] { "error", "response" }) || ctx.Match("invalidcommanderror", "unknowncommanderror")) - return ctx.Execute(null, m => m.InvalidCommandResponse(ctx)); - if (ctx.MatchMultiple(new[] { "require", "enforce" }, new[] { "tag", "systemtag" }) || ctx.Match("requiretag", "enforcetag")) - return ctx.Execute(null, m => m.RequireSystemTag(ctx)); - if (ctx.MatchMultiple(new[] { "suppress" }, new[] { "notifications" }) || ctx.Match("proxysilent")) - return ctx.Execute(null, m => m.SuppressNotifications(ctx)); - if (ctx.MatchMultiple(new[] { "log" }, new[] { "channel" })) - return ctx.Execute(null, m => m.SetLogChannel(ctx)); - if (ctx.MatchMultiple(new[] { "log" }, new[] { "blacklist" })) - { - if (ctx.Match("enable", "on", "add", "deny")) - return ctx.Execute(null, m => m.SetLogBlacklisted(ctx, true)); - else if (ctx.Match("disable", "off", "remove", "allow")) - return ctx.Execute(null, m => m.SetLogBlacklisted(ctx, false)); - else - return ctx.Execute(null, m => m.ShowLogDisabledChannels(ctx)); - } - if (ctx.MatchMultiple(new[] { "proxy", "proxying" }, new[] { "blacklist" })) - { - if (ctx.Match("enable", "on", "add", "deny")) - return ctx.Execute(null, m => m.SetProxyBlacklisted(ctx, true)); - else if (ctx.Match("disable", "off", "remove", "allow")) - return ctx.Execute(null, m => m.SetProxyBlacklisted(ctx, false)); - else - return ctx.Execute(null, m => m.ShowProxyBlacklisted(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 serverconfig` for the list of possible config settings."); - } } \ No newline at end of file diff --git a/PluralKit.Bot/Commands/ServerConfig.cs b/PluralKit.Bot/Commands/ServerConfig.cs index ef648438..e7b24a3c 100644 --- a/PluralKit.Bot/Commands/ServerConfig.cs +++ b/PluralKit.Bot/Commands/ServerConfig.cs @@ -110,34 +110,27 @@ public class ServerConfig ); } - public async Task SetLogChannel(Context ctx) + public async Task ShowLogChannel(Context ctx) { await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); var settings = await ctx.Repository.GetGuild(ctx.Guild.Id); - if (ctx.MatchClear() && await ctx.ConfirmClear("the server log channel")) + if (settings.LogChannel == null) { - await ctx.Repository.UpdateGuild(ctx.Guild.Id, new GuildPatch { LogChannel = null }); - await ctx.Reply($"{Emojis.Success} Proxy logging channel cleared."); + await ctx.Reply("This server does not have a log channel set."); return; } - if (!ctx.HasNext()) - { - if (settings.LogChannel == null) - { - await ctx.Reply("This server does not have a log channel set."); - return; - } + await ctx.Reply($"This server's log channel is currently set to <#{settings.LogChannel}>."); + } - await ctx.Reply($"This server's log channel is currently set to <#{settings.LogChannel}>."); - return; - } + public async Task SetLogChannel(Context ctx, Channel channel) + { + await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); + + if (channel.GuildId != ctx.Guild.Id) + throw Errors.ChannelNotFound(channel.Id.ToString()); - Channel channel = null; - var channelString = ctx.PeekArgument(); - channel = await ctx.MatchChannel(); - if (channel == null || channel.GuildId != ctx.Guild.Id) throw Errors.ChannelNotFound(channelString); if (channel.Type != Channel.ChannelType.GuildText && channel.Type != Channel.ChannelType.GuildPublicThread && channel.Type != Channel.ChannelType.GuildPrivateThread) throw new PKError("PluralKit cannot log messages to this type of channel."); @@ -151,46 +144,18 @@ public class ServerConfig await ctx.Reply($"{Emojis.Success} Proxy logging channel set to <#{channel.Id}>."); } - // legacy behaviour: enable/disable logging for commands - // new behaviour is add/remove from log blacklist (see #LogBlacklistNew) - public async Task SetLogEnabled(Context ctx, bool enable) + public async Task ClearLogChannel(Context ctx) { await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); - var affectedChannels = new List(); - if (ctx.Match("all")) - affectedChannels = (await _cache.GetGuildChannels(ctx.Guild.Id)) - .Where(x => x.Type == Channel.ChannelType.GuildText).ToList(); - else if (!ctx.HasNext()) throw new PKSyntaxError("You must pass one or more #channels."); - else - while (ctx.HasNext()) - { - var channelString = ctx.PeekArgument(); - var channel = await ctx.MatchChannel(); - if (channel == null || channel.GuildId != ctx.Guild.Id) throw Errors.ChannelNotFound(channelString); - affectedChannels.Add(channel); - } + if (!await ctx.ConfirmClear("the server log channel")) + return; - ulong? logChannel = null; - var config = await ctx.Repository.GetGuild(ctx.Guild.Id); - logChannel = config.LogChannel; - - var blacklist = config.LogBlacklist.ToHashSet(); - if (enable) - blacklist.ExceptWith(affectedChannels.Select(c => c.Id)); - else - blacklist.UnionWith(affectedChannels.Select(c => c.Id)); - - await ctx.Repository.UpdateGuild(ctx.Guild.Id, new GuildPatch { LogBlacklist = blacklist.ToArray() }); - - await ctx.Reply( - $"{Emojis.Success} Message logging for the given channels {(enable ? "enabled" : "disabled")}." + - (logChannel == null - ? $"\n{Emojis.Warn} Please note that no logging channel is set, so there is nowhere to log messages to. You can set a logging channel using `{ctx.DefaultPrefix}serverconfig log channel #your-log-channel`." - : "")); + await ctx.Repository.UpdateGuild(ctx.Guild.Id, new GuildPatch { LogChannel = null }); + await ctx.Reply($"{Emojis.Success} Proxy logging channel cleared."); } - public async Task ShowProxyBlacklisted(Context ctx) + public async Task ShowProxyBlacklist(Context ctx) { await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); @@ -240,14 +205,73 @@ public class ServerConfig }); } - public async Task ShowLogDisabledChannels(Context ctx) + public async Task AddProxyBlacklist(Context ctx, Channel? channel, bool all) + { + await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); + + var affectedChannels = new List(); + if (all) + { + affectedChannels = (await _cache.GetGuildChannels(ctx.Guild.Id)) + .Where(x => DiscordUtils.IsValidGuildChannel(x)).ToList(); + } + else if (channel != null) + { + if (channel.GuildId != ctx.Guild.Id) + throw Errors.ChannelNotFound(channel.Id.ToString()); + affectedChannels.Add(channel); + } + else + { + throw new PKSyntaxError("You must specify a channel or use the --all flag."); + } + + var guild = await ctx.Repository.GetGuild(ctx.Guild.Id); + var blacklist = guild.Blacklist.ToHashSet(); + blacklist.UnionWith(affectedChannels.Select(c => c.Id)); + + await ctx.Repository.UpdateGuild(ctx.Guild.Id, new GuildPatch { Blacklist = blacklist.ToArray() }); + + await ctx.Reply($"{Emojis.Success} {(all ? "All channels" : "Channel")} added to the proxy blacklist."); + } + + public async Task RemoveProxyBlacklist(Context ctx, Channel? channel, bool all) + { + await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); + + var affectedChannels = new List(); + if (all) + { + affectedChannels = (await _cache.GetGuildChannels(ctx.Guild.Id)) + .Where(x => DiscordUtils.IsValidGuildChannel(x)).ToList(); + } + else if (channel != null) + { + if (channel.GuildId != ctx.Guild.Id) + throw Errors.ChannelNotFound(channel.Id.ToString()); + affectedChannels.Add(channel); + } + else + { + throw new PKSyntaxError("You must specify a channel or use the --all flag."); + } + + var guild = await ctx.Repository.GetGuild(ctx.Guild.Id); + var blacklist = guild.Blacklist.ToHashSet(); + blacklist.ExceptWith(affectedChannels.Select(c => c.Id)); + + await ctx.Repository.UpdateGuild(ctx.Guild.Id, new GuildPatch { Blacklist = blacklist.ToArray() }); + + await ctx.Reply($"{Emojis.Success} {(all ? "All channels" : "Channel")} removed from the proxy blacklist."); + } + + public async Task ShowLogBlacklist(Context ctx) { await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); var config = await ctx.Repository.GetGuild(ctx.Guild.Id); // Resolve all channels from the cache and order by position - // todo: GetAllChannels? var channels = (await Task.WhenAll(config.LogBlacklist .Select(id => _cache.TryGetChannel(ctx.Guild.Id, id)))) .Where(c => c != null) @@ -291,78 +315,75 @@ public class ServerConfig }); } - - - public async Task SetProxyBlacklisted(Context ctx, bool shouldAdd) + public async Task AddLogBlacklist(Context ctx, Channel? channel, bool all) { await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); var affectedChannels = new List(); - if (ctx.Match("all")) + if (all) + { affectedChannels = (await _cache.GetGuildChannels(ctx.Guild.Id)) - // All the channel types you can proxy in .Where(x => DiscordUtils.IsValidGuildChannel(x)).ToList(); - else if (!ctx.HasNext()) throw new PKSyntaxError("You must pass one or more #channels."); + } + else if (channel != null) + { + if (channel.GuildId != ctx.Guild.Id) + throw Errors.ChannelNotFound(channel.Id.ToString()); + affectedChannels.Add(channel); + } else - while (ctx.HasNext()) - { - var channelString = ctx.PeekArgument(); - var channel = await ctx.MatchChannel(); - if (channel == null || channel.GuildId != ctx.Guild.Id) throw Errors.ChannelNotFound(channelString); - affectedChannels.Add(channel); - } + { + throw new PKSyntaxError("You must specify a channel or use the --all flag."); + } var guild = await ctx.Repository.GetGuild(ctx.Guild.Id); - - var blacklist = guild.Blacklist.ToHashSet(); - if (shouldAdd) - blacklist.UnionWith(affectedChannels.Select(c => c.Id)); - else - blacklist.ExceptWith(affectedChannels.Select(c => c.Id)); - - await ctx.Repository.UpdateGuild(ctx.Guild.Id, new GuildPatch { Blacklist = blacklist.ToArray() }); - - await ctx.Reply( - $"{Emojis.Success} Channels {(shouldAdd ? "added to" : "removed from")} the proxy blacklist."); - } - - public async Task SetLogBlacklisted(Context ctx, bool shouldAdd) - { - await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); - - var affectedChannels = new List(); - if (ctx.Match("all")) - affectedChannels = (await _cache.GetGuildChannels(ctx.Guild.Id)) - // All the channel types you can proxy in - .Where(x => DiscordUtils.IsValidGuildChannel(x)).ToList(); - else if (!ctx.HasNext()) throw new PKSyntaxError("You must pass one or more #channels."); - else - while (ctx.HasNext()) - { - var channelString = ctx.PeekArgument(); - var channel = await ctx.MatchChannel(); - if (channel == null || channel.GuildId != ctx.Guild.Id) throw Errors.ChannelNotFound(channelString); - affectedChannels.Add(channel); - } - - var guild = await ctx.Repository.GetGuild(ctx.Guild.Id); - var blacklist = guild.LogBlacklist.ToHashSet(); - if (shouldAdd) - blacklist.UnionWith(affectedChannels.Select(c => c.Id)); - else - blacklist.ExceptWith(affectedChannels.Select(c => c.Id)); + blacklist.UnionWith(affectedChannels.Select(c => c.Id)); await ctx.Repository.UpdateGuild(ctx.Guild.Id, new GuildPatch { LogBlacklist = blacklist.ToArray() }); await ctx.Reply( - $"{Emojis.Success} Channels {(shouldAdd ? "added to" : "removed from")} the logging blacklist." + + $"{Emojis.Success} {(all ? "All channels" : "Channel")} added to the logging blacklist." + (guild.LogChannel == null ? $"\n{Emojis.Warn} Please note that no logging channel is set, so there is nowhere to log messages to. You can set a logging channel using `{ctx.DefaultPrefix}serverconfig log channel #your-log-channel`." : "")); } - public async Task SetLogCleanup(Context ctx) + public async Task RemoveLogBlacklist(Context ctx, Channel? channel, bool all) + { + await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); + + var affectedChannels = new List(); + if (all) + { + affectedChannels = (await _cache.GetGuildChannels(ctx.Guild.Id)) + .Where(x => DiscordUtils.IsValidGuildChannel(x)).ToList(); + } + else if (channel != null) + { + if (channel.GuildId != ctx.Guild.Id) + throw Errors.ChannelNotFound(channel.Id.ToString()); + affectedChannels.Add(channel); + } + else + { + throw new PKSyntaxError("You must specify a channel or use the --all flag."); + } + + var guild = await ctx.Repository.GetGuild(ctx.Guild.Id); + var blacklist = guild.LogBlacklist.ToHashSet(); + blacklist.ExceptWith(affectedChannels.Select(c => c.Id)); + + await ctx.Repository.UpdateGuild(ctx.Guild.Id, new GuildPatch { LogBlacklist = blacklist.ToArray() }); + + await ctx.Reply( + $"{Emojis.Success} {(all ? "All channels" : "Channel")} removed from the logging blacklist." + + (guild.LogChannel == null + ? $"\n{Emojis.Warn} Please note that no logging channel is set, so there is nowhere to log messages to. You can set a logging channel using `{ctx.DefaultPrefix}serverconfig log channel #your-log-channel`." + : "")); + } + + public async Task ShowLogCleanup(Context ctx) { var botList = string.Join(", ", LoggerCleanService.Bots.Select(b => b.Name).OrderBy(x => x.ToLowerInvariant())); var eb = new EmbedBuilder() @@ -377,74 +398,77 @@ public class ServerConfig } await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); - bool? newValue = ctx.MatchToggleOrNull(); - if (newValue == null) - { - if (ctx.GuildConfig!.LogCleanupEnabled) - eb.Description( - $"Log cleanup is currently **on** for this server. To disable it, type `{ctx.DefaultPrefix}serverconfig logclean off`."); - else - eb.Description( - $"Log cleanup is currently **off** for this server. To enable it, type `{ctx.DefaultPrefix}serverconfig logclean on`."); - await ctx.Reply(embed: eb.Build()); - return; - } + if (ctx.GuildConfig!.LogCleanupEnabled) + eb.Description( + $"Log cleanup is currently **on** for this server. To disable it, type `{ctx.DefaultPrefix}serverconfig logclean off`."); + else + eb.Description( + $"Log cleanup is currently **off** for this server. To enable it, type `{ctx.DefaultPrefix}serverconfig logclean on`."); - await ctx.Repository.UpdateGuild(ctx.Guild.Id, new GuildPatch { LogCleanupEnabled = newValue.Value }); + await ctx.Reply(embed: eb.Build()); + } - if (newValue.Value) + public async Task SetLogCleanup(Context ctx, bool value) + { + await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); + + var botList = string.Join(", ", LoggerCleanService.Bots.Select(b => b.Name).OrderBy(x => x.ToLowerInvariant())); + + await ctx.Repository.UpdateGuild(ctx.Guild.Id, new GuildPatch { LogCleanupEnabled = value }); + + if (value) await ctx.Reply( $"{Emojis.Success} Log cleanup has been **enabled** for this server. Messages deleted by PluralKit will now be cleaned up from logging channels managed by the following bots:\n- **{botList}**\n\n{Emojis.Note} Make sure PluralKit has the **Manage Messages** permission in the channels in question.\n{Emojis.Note} Also, make sure to blacklist the logging channel itself from the bots in question to prevent conflicts."); else await ctx.Reply($"{Emojis.Success} Log cleanup has been **disabled** for this server."); } - public async Task InvalidCommandResponse(Context ctx) + public async Task ShowInvalidCommandResponse(Context ctx) { await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); - if (!ctx.HasNext()) - { - var msg = $"Error responses for unknown/invalid commands are currently **{EnabledDisabled(ctx.GuildConfig!.InvalidCommandResponseEnabled)}**."; - await ctx.Reply(msg); - return; - } - - var newVal = ctx.MatchToggle(false); - await ctx.Repository.UpdateGuild(ctx.Guild.Id, new() { InvalidCommandResponseEnabled = newVal }); - await ctx.Reply($"Error responses for unknown/invalid commands are now {EnabledDisabled(newVal)}."); + var msg = $"Error responses for unknown/invalid commands are currently **{EnabledDisabled(ctx.GuildConfig!.InvalidCommandResponseEnabled)}**."; + await ctx.Reply(msg); } - public async Task RequireSystemTag(Context ctx) + public async Task SetInvalidCommandResponse(Context ctx, bool value) { await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); - if (!ctx.HasNext()) - { - var msg = $"System tags are currently **{(ctx.GuildConfig!.RequireSystemTag ? "required" : "not required")}** for PluralKit users in this server."; - await ctx.Reply(msg); - return; - } - - var newVal = ctx.MatchToggle(false); - await ctx.Repository.UpdateGuild(ctx.Guild.Id, new() { RequireSystemTag = newVal }); - await ctx.Reply($"System tags are now **{(newVal ? "required" : "not required")}** for PluralKit users in this server."); + await ctx.Repository.UpdateGuild(ctx.Guild.Id, new() { InvalidCommandResponseEnabled = value }); + await ctx.Reply($"Error responses for unknown/invalid commands are now {EnabledDisabled(value)}."); } - public async Task SuppressNotifications(Context ctx) + public async Task ShowRequireSystemTag(Context ctx) { await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); - if (!ctx.HasNext()) - { - var msg = $"Suppressing notifications for proxied messages is currently **{EnabledDisabled(ctx.GuildConfig!.SuppressNotifications)}**."; - await ctx.Reply(msg); - return; - } + var msg = $"System tags are currently **{(ctx.GuildConfig!.RequireSystemTag ? "required" : "not required")}** for PluralKit users in this server."; + await ctx.Reply(msg); + } - var newVal = ctx.MatchToggle(false); - await ctx.Repository.UpdateGuild(ctx.Guild.Id, new() { SuppressNotifications = newVal }); - await ctx.Reply($"Suppressing notifications for proxied messages is now {EnabledDisabled(newVal)}."); + public async Task SetRequireSystemTag(Context ctx, bool value) + { + await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); + + await ctx.Repository.UpdateGuild(ctx.Guild.Id, new() { RequireSystemTag = value }); + await ctx.Reply($"System tags are now **{(value ? "required" : "not required")}** for PluralKit users in this server."); + } + + public async Task ShowSuppressNotifications(Context ctx) + { + await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); + + var msg = $"Suppressing notifications for proxied messages is currently **{EnabledDisabled(ctx.GuildConfig!.SuppressNotifications)}**."; + await ctx.Reply(msg); + } + + public async Task SetSuppressNotifications(Context ctx, bool value) + { + await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); + + await ctx.Repository.UpdateGuild(ctx.Guild.Id, new() { SuppressNotifications = value }); + await ctx.Reply($"Suppressing notifications for proxied messages is now {EnabledDisabled(value)}."); } } \ No newline at end of file diff --git a/crates/command_definitions/src/lib.rs b/crates/command_definitions/src/lib.rs index 2fbc00fb..3445d6a6 100644 --- a/crates/command_definitions/src/lib.rs +++ b/crates/command_definitions/src/lib.rs @@ -31,6 +31,7 @@ pub fn all() -> impl Iterator { .chain(group::cmds()) .chain(member::cmds()) .chain(config::cmds()) + .chain(server_config::cmds()) .chain(fun::cmds()) .chain(switch::cmds()) .chain(random::cmds()) @@ -40,6 +41,7 @@ pub fn all() -> impl Iterator { .chain(message::cmds()) .chain(import_export::cmds()) .chain(admin::cmds()) + .chain(misc::cmds()) .map(|cmd| { cmd.hidden_flag(("plaintext", ["pt"])) .hidden_flag(("raw", ["r"])) diff --git a/crates/command_definitions/src/misc.rs b/crates/command_definitions/src/misc.rs index 8b137891..a649599d 100644 --- a/crates/command_definitions/src/misc.rs +++ b/crates/command_definitions/src/misc.rs @@ -1 +1,5 @@ +use super::*; +pub fn cmds() -> impl Iterator { + [].into_iter() +} diff --git a/crates/command_definitions/src/server_config.rs b/crates/command_definitions/src/server_config.rs index 8b137891..7119d528 100644 --- a/crates/command_definitions/src/server_config.rs +++ b/crates/command_definitions/src/server_config.rs @@ -1 +1,149 @@ +use super::*; +pub fn cmds() -> impl Iterator { + let server_config = ("serverconfig", ["guildconfig", "scfg", "gcfg"]); + + let log = tokens!(server_config, ("log", ["log", "logging"])); + let log_channel = tokens!(log, ("channel", ["ch", "chan"])); + let log_cleanup = tokens!(log, ("cleanup", ["clean"])); + let log_cleanup_short = tokens!(server_config, ("logclean", ["logclean", "logcleanup"])); + let log_blacklist = tokens!(log, ("blacklist", ["bl", "ignore"])); + + let proxy = tokens!(server_config, ("proxy", ["proxy", "proxying"])); + let proxy_blacklist = tokens!(proxy, ("blacklist", ["bl", "ignore", "disable"])); + + let invalid = tokens!( + server_config, + ("invalid", ["invalid", "unknown"]), + ("command", ["command", "cmd"]), + ("error", ["error", "response"]) + ); + let invalid_short = tokens!( + server_config, + ( + "invalidcommanderror", + ["invalidcommanderror", "unknowncommanderror", "ice"] + ) + ); + + let require_tag = tokens!( + server_config, + ("require", ["require", "enforce"]), + ("tag", ["tag", "systemtag"]) + ); + let require_tag_short = tokens!(server_config, ("requiretag", ["requiretag", "enforcetag"])); + + let suppress = tokens!( + server_config, + ("suppress", ["suppress"]), + ("notifications", ["notifications", "notifs"]) + ); + let suppress_short = tokens!(server_config, ("proxysilent", ["proxysilent", "silent"])); + + // Common tokens for add/remove operations + let add = ("add", ["enable", "on", "deny"]); + let remove = ("remove", ["disable", "off", "allow"]); + + // Log channel commands + let log_channel_cmds = [ + command!(log_channel => "server_config_log_channel_show") + .help("Shows the current log channel"), + 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") + .help("Clears the log channel"), + ] + .into_iter(); + + // Log cleanup commands + let log_cleanup_cmds = [ + command!(log_cleanup => "server_config_log_cleanup_show") + .help("Shows whether log cleanup is enabled"), + command!(log_cleanup, Toggle => "server_config_log_cleanup_set") + .help("Enables or disables log cleanup"), + command!(log_cleanup_short => "server_config_log_cleanup_show") + .help("Shows whether log cleanup is enabled"), + command!(log_cleanup_short, Toggle => "server_config_log_cleanup_set") + .help("Enables or disables log cleanup"), + ] + .into_iter(); + + // Log blacklist commands + let log_blacklist_cmds = [ + command!(log_blacklist => "server_config_log_blacklist_show") + .help("Shows channels where logging is disabled"), + command!(log_blacklist, add, Optional(("channel", ChannelRef)) => "server_config_log_blacklist_add") + .flag(("all", ["a"])) + .help("Adds a channel (or all channels with --all) to the log blacklist"), + command!(log_blacklist, remove, Optional(("channel", ChannelRef)) => "server_config_log_blacklist_remove") + .flag(("all", ["a"])) + .help("Removes a channel (or all channels with --all) from the log blacklist"), + ] + .into_iter(); + + // Proxy blacklist commands + let proxy_blacklist_cmds = [ + command!(proxy_blacklist => "server_config_proxy_blacklist_show") + .help("Shows channels where proxying is disabled"), + command!(proxy_blacklist, add, Optional(("channel", ChannelRef)) => "server_config_proxy_blacklist_add") + .flag(("all", ["a"])) + .help("Adds a channel (or all channels with --all) to the proxy blacklist"), + command!(proxy_blacklist, remove, Optional(("channel", ChannelRef)) => "server_config_proxy_blacklist_remove") + .flag(("all", ["a"])) + .help("Removes a channel (or all channels with --all) from the proxy blacklist"), + ] + .into_iter(); + + // Invalid command error commands + let invalid_cmds = [ + command!(invalid => "server_config_invalid_command_response_show") + .help("Shows whether error responses for invalid commands are enabled"), + command!(invalid, Toggle => "server_config_invalid_command_response_set") + .help("Enables or disables error responses for invalid commands"), + command!(invalid_short => "server_config_invalid_command_response_show") + .help("Shows whether error responses for invalid commands are enabled"), + command!(invalid_short, Toggle => "server_config_invalid_command_response_set") + .help("Enables or disables error responses for invalid commands"), + ] + .into_iter(); + + // Require system tag commands + let require_tag_cmds = [ + command!(require_tag => "server_config_require_system_tag_show") + .help("Shows whether system tags are required"), + command!(require_tag, Toggle => "server_config_require_system_tag_set") + .help("Requires or unrequires system tags for proxied messages"), + command!(require_tag_short => "server_config_require_system_tag_show") + .help("Shows whether system tags are required"), + command!(require_tag_short, Toggle => "server_config_require_system_tag_set") + .help("Requires or unrequires system tags for proxied messages"), + ] + .into_iter(); + + // Suppress notifications commands + let suppress_cmds = [ + command!(suppress => "server_config_suppress_notifications_show") + .help("Shows whether notifications are suppressed for proxied messages"), + command!(suppress, Toggle => "server_config_suppress_notifications_set") + .help("Enables or disables notification suppression for proxied messages"), + command!(suppress_short => "server_config_suppress_notifications_show") + .help("Shows whether notifications are suppressed for proxied messages"), + command!(suppress_short, Toggle => "server_config_suppress_notifications_set") + .help("Enables or disables notification suppression for proxied messages"), + ] + .into_iter(); + + // Main config overview + let main_cmd = [command!(server_config => "server_config_show") + .help("Shows the current server configuration")] + .into_iter(); + + main_cmd + .chain(log_channel_cmds) + .chain(log_cleanup_cmds) + .chain(log_blacklist_cmds) + .chain(proxy_blacklist_cmds) + .chain(invalid_cmds) + .chain(require_tag_cmds) + .chain(suppress_cmds) +}