From 1cb554e9c5a6d4f686acd3d481b2740a7ae73ff4 Mon Sep 17 00:00:00 2001 From: Petal Ladenson Date: Mon, 12 Jan 2026 15:31:23 -0700 Subject: [PATCH 1/2] refactor: all instances of generic 'blacklist' to 'proxy blacklist' --- PluralKit.Bot/CommandMeta/CommandHelp.cs | 10 +++++----- PluralKit.Bot/CommandMeta/CommandTree.cs | 8 ++++---- PluralKit.Bot/Commands/ServerConfig.cs | 8 ++++---- PluralKit.Bot/Proxy/ProxyService.cs | 4 ++-- PluralKit.Core/Database/Functions/MessageContext.cs | 2 +- PluralKit.Core/Database/Utils/DatabaseMigrator.cs | 2 +- PluralKit.Core/Models/GuildConfig.cs | 2 +- PluralKit.Core/Models/Patch/GuildPatch.cs | 4 ++-- crates/migrate/data/functions.sql | 6 +++--- crates/migrate/data/migrations/54.sql | 6 ++++++ 10 files changed, 29 insertions(+), 23 deletions(-) create mode 100644 crates/migrate/data/migrations/54.sql diff --git a/PluralKit.Bot/CommandMeta/CommandHelp.cs b/PluralKit.Bot/CommandMeta/CommandHelp.cs index 65fa79b6..5f3314b7 100644 --- a/PluralKit.Bot/CommandMeta/CommandHelp.cs +++ b/PluralKit.Bot/CommandMeta/CommandHelp.cs @@ -106,9 +106,9 @@ public partial class CommandTree public static Command LogEnable = new Command("serverconfig log blacklist remove", "serverconfig log blacklist remove all| [channel 2] [channel 3...]", "Enables message logging in certain channels"); public static Command LogDisable = new Command("serverconfig log blacklist add", "serverconfig log blacklist add all| [channel 2] [channel 3...]", "Disables message logging in certain channels"); public static Command LogShow = new Command("serverconfig log blacklist", "serverconfig log blacklist", "Displays the current list of channels where logging is disabled"); - public static Command BlacklistShow = new Command("serverconfig proxy blacklist", "serverconfig proxy blacklist", "Displays the current list of channels where message proxying is disabled"); - public static Command BlacklistAdd = new Command("serverconfig proxy blacklist add", "serverconfig proxy blacklist add all| [channel 2] [channel 3...]", "Disables message proxying in certain channels"); - public static Command BlacklistRemove = new Command("serverconfig proxy blacklist remove", "serverconfig proxy blacklist remove all| [channel 2] [channel 3...]", "Enables message proxying in certain channels"); + public static Command ProxyBlacklistShow = new Command("serverconfig proxy blacklist", "serverconfig proxy blacklist", "Displays the current list of channels where message proxying is disabled"); + public static Command ProxyBlacklistAdd = new Command("serverconfig proxy blacklist add", "serverconfig proxy blacklist add all| [channel 2] [channel 3...]", "Disables message proxying in certain channels"); + public static Command ProxyBlacklistRemove = new Command("serverconfig proxy blacklist remove", "serverconfig proxy blacklist remove all| [channel 2] [channel 3...]", "Enables message proxying in certain channels"); public static Command ServerConfigLogClean = new Command("serverconfig log cleanup", "serverconfig log cleanup [on|off]", "Toggles whether to clean up other bots' log channels"); public static Command ServerConfigInvalidCommandResponse = new Command("serverconfig invalid command error", "serverconfig invalid command error [on|off]", "Sets whether to show an error message when an unknown command is sent"); public static Command ServerConfigRequireSystemTag = new Command("serverconfig require tag", "serverconfig require tag [on|off]", "Sets whether server users are required to have a system tag on proxied messages"); @@ -160,7 +160,7 @@ public partial class CommandTree ServerConfigLogClean, ServerConfigInvalidCommandResponse, ServerConfigRequireSystemTag, ServerConfigSuppressNotifications, LogChannel, LogChannelClear, LogShow, LogDisable, LogEnable, - BlacklistShow, BlacklistAdd, BlacklistRemove + ProxyBlacklistShow, ProxyBlacklistAdd, ProxyBlacklistRemove }; public static Command[] AutoproxyCommands = @@ -170,5 +170,5 @@ public partial class CommandTree public static Command[] LogCommands = { LogChannel, LogChannelClear, LogEnable, LogDisable, LogShow }; - public static Command[] BlacklistCommands = { BlacklistAdd, BlacklistRemove, BlacklistShow }; + public static Command[] ProxyBlacklistCommands = { ProxyBlacklistAdd, ProxyBlacklistRemove, ProxyBlacklistShow }; } \ No newline at end of file diff --git a/PluralKit.Bot/CommandMeta/CommandTree.cs b/PluralKit.Bot/CommandMeta/CommandTree.cs index d1ab6da0..0a56c20f 100644 --- a/PluralKit.Bot/CommandMeta/CommandTree.cs +++ b/PluralKit.Bot/CommandMeta/CommandTree.cs @@ -69,11 +69,11 @@ public partial class CommandTree 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); + return ctx.Execute(ProxyBlacklistAdd, m => m.SetProxyBlacklisted(ctx, true), true); else if (ctx.Match("disable", "off", "remove", "allow")) - return ctx.Execute(BlacklistRemove, m => m.SetProxyBlacklisted(ctx, false), true); + return ctx.Execute(ProxyBlacklistRemove, m => m.SetProxyBlacklisted(ctx, false), true); else if (ctx.Match("list", "show")) - return ctx.Execute(BlacklistShow, m => m.ShowProxyBlacklisted(ctx), true); + return ctx.Execute(ProxyBlacklistShow, m => m.ShowProxyBlacklisted(ctx), true); else return ctx.Reply($"{Emojis.Warn} Blacklist commands have moved to `{ctx.DefaultPrefix}serverconfig`."); if (ctx.Match("proxy")) @@ -530,7 +530,7 @@ public partial class CommandTree break; case "blacklist": case "bl": - await PrintCommandList(ctx, "channel blacklisting", BlacklistCommands); + await PrintCommandList(ctx, "channel proxy blacklisting", ProxyBlacklistCommands); break; case "config": case "cfg": diff --git a/PluralKit.Bot/Commands/ServerConfig.cs b/PluralKit.Bot/Commands/ServerConfig.cs index ef648438..0219c8c6 100644 --- a/PluralKit.Bot/Commands/ServerConfig.cs +++ b/PluralKit.Bot/Commands/ServerConfig.cs @@ -73,7 +73,7 @@ public class ServerConfig items.Add(new( "proxy blacklist", "Channels where message proxying is disabled", - ChannelListMessage(ctx.GuildConfig!.Blacklist.Length, "proxy blacklist"), + ChannelListMessage(ctx.GuildConfig!.ProxyBlacklist.Length, "proxy blacklist"), ChannelListMessage(0, "proxy blacklist") )); @@ -197,7 +197,7 @@ public class ServerConfig var blacklist = await ctx.Repository.GetGuild(ctx.Guild.Id); // Resolve all channels from the cache and order by position - var channels = (await Task.WhenAll(blacklist.Blacklist + var channels = (await Task.WhenAll(blacklist.ProxyBlacklist .Select(id => _cache.TryGetChannel(ctx.Guild.Id, id)))) .Where(c => c != null) .OrderBy(c => c.Position) @@ -314,13 +314,13 @@ public class ServerConfig var guild = await ctx.Repository.GetGuild(ctx.Guild.Id); - var blacklist = guild.Blacklist.ToHashSet(); + var blacklist = guild.ProxyBlacklist.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.Repository.UpdateGuild(ctx.Guild.Id, new GuildPatch { ProxyBlacklist = blacklist.ToArray() }); await ctx.Reply( $"{Emojis.Success} Channels {(shouldAdd ? "added to" : "removed from")} the proxy blacklist."); diff --git a/PluralKit.Bot/Proxy/ProxyService.cs b/PluralKit.Bot/Proxy/ProxyService.cs index ee6108af..5cf1e45b 100644 --- a/PluralKit.Bot/Proxy/ProxyService.cs +++ b/PluralKit.Bot/Proxy/ProxyService.cs @@ -184,7 +184,7 @@ public class ProxyService throw new ProxyChecksFailedException("This message is the initial message in a forum post, which PluralKit is unable to proxy correctly."); // Make sure proxying is enabled here - if (ctx.InBlacklist) + if (ctx.InProxyBlacklist) throw new ProxyChecksFailedException( "Proxying was disabled in this channel by a server administrator (via the proxy blacklist)."); @@ -290,7 +290,7 @@ public class ProxyService await _repo.GetMessageContext(msg.Sender, msg.Guild!.Value, rootChannel.Id, msg.Channel); // Make sure proxying is enabled here - if (ctx.InBlacklist) + if (ctx.InProxyBlacklist) throw new ProxyChecksFailedException( "Proxying was disabled in this channel by a server administrator (via the proxy blacklist)."); diff --git a/PluralKit.Core/Database/Functions/MessageContext.cs b/PluralKit.Core/Database/Functions/MessageContext.cs index 78fa4cb3..876dabc2 100644 --- a/PluralKit.Core/Database/Functions/MessageContext.cs +++ b/PluralKit.Core/Database/Functions/MessageContext.cs @@ -32,7 +32,7 @@ public class MessageContext public Instant? LastSwitchTimestamp { get; } public ulong? LogChannel { get; } - public bool InBlacklist { get; } + public bool InProxyBlacklist { get; } public bool InLogBlacklist { get; } public bool LogCleanupEnabled { get; } public bool RequireSystemTag { get; } diff --git a/PluralKit.Core/Database/Utils/DatabaseMigrator.cs b/PluralKit.Core/Database/Utils/DatabaseMigrator.cs index d4d58093..1161cf31 100644 --- a/PluralKit.Core/Database/Utils/DatabaseMigrator.cs +++ b/PluralKit.Core/Database/Utils/DatabaseMigrator.cs @@ -9,7 +9,7 @@ namespace PluralKit.Core; internal class DatabaseMigrator { private const string RootPath = "PluralKit.Core.Database"; // "resource path" root for SQL files - private const int TargetSchemaVersion = 52; + private const int TargetSchemaVersion = 54; private readonly ILogger _logger; public DatabaseMigrator(ILogger logger) diff --git a/PluralKit.Core/Models/GuildConfig.cs b/PluralKit.Core/Models/GuildConfig.cs index a71dee45..9e6cf6a6 100644 --- a/PluralKit.Core/Models/GuildConfig.cs +++ b/PluralKit.Core/Models/GuildConfig.cs @@ -5,7 +5,7 @@ public class GuildConfig public ulong Id { get; } public ulong? LogChannel { get; } public ulong[] LogBlacklist { get; } - public ulong[] Blacklist { get; } + public ulong[] ProxyBlacklist { get; } public bool LogCleanupEnabled { get; } public bool InvalidCommandResponseEnabled { get; } public bool RequireSystemTag { get; } diff --git a/PluralKit.Core/Models/Patch/GuildPatch.cs b/PluralKit.Core/Models/Patch/GuildPatch.cs index ae75e835..f814e909 100644 --- a/PluralKit.Core/Models/Patch/GuildPatch.cs +++ b/PluralKit.Core/Models/Patch/GuildPatch.cs @@ -6,7 +6,7 @@ public class GuildPatch: PatchObject { public Partial LogChannel { get; set; } public Partial LogBlacklist { get; set; } - public Partial Blacklist { get; set; } + public Partial ProxyBlacklist { get; set; } public Partial LogCleanupEnabled { get; set; } public Partial InvalidCommandResponseEnabled { get; set; } public Partial RequireSystemTag { get; set; } @@ -15,7 +15,7 @@ public class GuildPatch: PatchObject public override Query Apply(Query q) => q.ApplyPatch(wrapper => wrapper .With("log_channel", LogChannel) .With("log_blacklist", LogBlacklist) - .With("blacklist", Blacklist) + .With("proxy_blacklist", ProxyBlacklist) .With("log_cleanup_enabled", LogCleanupEnabled) .With("invalid_command_response_enabled", InvalidCommandResponseEnabled) .With("require_system_tag", RequireSystemTag) diff --git a/crates/migrate/data/functions.sql b/crates/migrate/data/functions.sql index 16be5519..6ec03ee8 100644 --- a/crates/migrate/data/functions.sql +++ b/crates/migrate/data/functions.sql @@ -23,7 +23,7 @@ create function message_context(account_id bigint, guild_id bigint, channel_id b last_switch_timestamp timestamp, log_channel bigint, - in_blacklist bool, + in_proxy_blacklist bool, in_log_blacklist bool, log_cleanup_enabled bool, require_system_tag bool, @@ -62,8 +62,8 @@ as $$ -- servers table servers.log_channel as log_channel, - ((channel_id = any (servers.blacklist)) - or (thread_id = any (servers.blacklist))) as in_blacklist, + ((channel_id = any (servers.proxy_blacklist)) + or (thread_id = any (servers.proxy_blacklist))) as in_proxy_blacklist, ((channel_id = any (servers.log_blacklist)) or (thread_id = any (servers.log_blacklist))) as in_log_blacklist, coalesce(servers.log_cleanup_enabled, false) as log_cleanup_enabled, diff --git a/crates/migrate/data/migrations/54.sql b/crates/migrate/data/migrations/54.sql new file mode 100644 index 00000000..2bdf66a8 --- /dev/null +++ b/crates/migrate/data/migrations/54.sql @@ -0,0 +1,6 @@ +-- database version 54 +-- rename blacklist column to proxy blacklist + +alter table servers rename column blacklist to proxy_blacklist; + +update info set schema_version = 54; \ No newline at end of file From a3aa02e779205b5ef7f9a19538a26c98961a223e Mon Sep 17 00:00:00 2001 From: Petal Ladenson Date: Mon, 12 Jan 2026 17:14:12 -0700 Subject: [PATCH 2/2] feat: add command blacklisting --- PluralKit.Bot/CommandMeta/CommandHelp.cs | 6 +- PluralKit.Bot/CommandMeta/CommandTree.cs | 9 ++ PluralKit.Bot/Commands/ServerConfig.cs | 94 ++++++++++++++++++- PluralKit.Bot/Handlers/MessageCreated.cs | 17 +++- .../Database/Functions/MessageContext.cs | 1 + .../Database/Utils/DatabaseMigrator.cs | 2 +- PluralKit.Core/Models/GuildConfig.cs | 1 + PluralKit.Core/Models/Patch/GuildPatch.cs | 2 + crates/migrate/data/functions.sql | 5 +- crates/migrate/data/migrations/55.sql | 6 ++ docs/content/command-list.md | 3 + docs/content/staff/disabling.md | 17 +++- 12 files changed, 155 insertions(+), 8 deletions(-) create mode 100644 crates/migrate/data/migrations/55.sql diff --git a/PluralKit.Bot/CommandMeta/CommandHelp.cs b/PluralKit.Bot/CommandMeta/CommandHelp.cs index 5f3314b7..d1b72a87 100644 --- a/PluralKit.Bot/CommandMeta/CommandHelp.cs +++ b/PluralKit.Bot/CommandMeta/CommandHelp.cs @@ -109,6 +109,9 @@ public partial class CommandTree public static Command ProxyBlacklistShow = new Command("serverconfig proxy blacklist", "serverconfig proxy blacklist", "Displays the current list of channels where message proxying is disabled"); public static Command ProxyBlacklistAdd = new Command("serverconfig proxy blacklist add", "serverconfig proxy blacklist add all| [channel 2] [channel 3...]", "Disables message proxying in certain channels"); public static Command ProxyBlacklistRemove = new Command("serverconfig proxy blacklist remove", "serverconfig proxy blacklist remove all| [channel 2] [channel 3...]", "Enables message proxying in certain channels"); + public static Command CommandBlacklistShow = new Command("serverconfig command blacklist", "serverconfig command blacklist", "Displays the current list of channels where running text commands is disabled"); + public static Command CommandBlacklistAdd = new Command("serverconfig command blacklist add", "serverconfig command blacklist add all| [channel 2] [channel 3...]", "Disables running text commands in certain channels"); + public static Command CommandBlacklistRemove = new Command("serverconfig command blacklist remove", "serverconfig command blacklist remove all| [channel 2] [channel 3...]", "Enables running text commands in certain channels"); public static Command ServerConfigLogClean = new Command("serverconfig log cleanup", "serverconfig log cleanup [on|off]", "Toggles whether to clean up other bots' log channels"); public static Command ServerConfigInvalidCommandResponse = new Command("serverconfig invalid command error", "serverconfig invalid command error [on|off]", "Sets whether to show an error message when an unknown command is sent"); public static Command ServerConfigRequireSystemTag = new Command("serverconfig require tag", "serverconfig require tag [on|off]", "Sets whether server users are required to have a system tag on proxied messages"); @@ -160,7 +163,8 @@ public partial class CommandTree ServerConfigLogClean, ServerConfigInvalidCommandResponse, ServerConfigRequireSystemTag, ServerConfigSuppressNotifications, LogChannel, LogChannelClear, LogShow, LogDisable, LogEnable, - ProxyBlacklistShow, ProxyBlacklistAdd, ProxyBlacklistRemove + ProxyBlacklistShow, ProxyBlacklistAdd, ProxyBlacklistRemove, + CommandBlacklistShow, CommandBlacklistAdd, CommandBlacklistRemove }; public static Command[] AutoproxyCommands = diff --git a/PluralKit.Bot/CommandMeta/CommandTree.cs b/PluralKit.Bot/CommandMeta/CommandTree.cs index 0a56c20f..392676f0 100644 --- a/PluralKit.Bot/CommandMeta/CommandTree.cs +++ b/PluralKit.Bot/CommandMeta/CommandTree.cs @@ -642,6 +642,15 @@ public partial class CommandTree else return ctx.Execute(null, m => m.ShowProxyBlacklisted(ctx)); } + if (ctx.MatchMultiple(new[] { "command" }, new[] { "blacklist" })) + { + if (ctx.Match("enable", "on", "add", "deny")) + return ctx.Execute(null, m => m.SetCommandBlacklisted(ctx, true)); + else if (ctx.Match("disable", "off", "remove", "allow")) + return ctx.Execute(null, m => m.SetCommandBlacklisted(ctx, false)); + else + return ctx.Execute(null, m => m.ShowCommandBlacklisted(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."); diff --git a/PluralKit.Bot/Commands/ServerConfig.cs b/PluralKit.Bot/Commands/ServerConfig.cs index 0219c8c6..c3f53b59 100644 --- a/PluralKit.Bot/Commands/ServerConfig.cs +++ b/PluralKit.Bot/Commands/ServerConfig.cs @@ -77,6 +77,13 @@ public class ServerConfig ChannelListMessage(0, "proxy blacklist") )); + items.Add(new( + "command blacklist", + "Channels where running text commands is disabled", + ChannelListMessage(ctx.GuildConfig!.CommandBlacklist.Length, "command blacklist"), + ChannelListMessage(0, "command blacklist") + )); + await ctx.Paginate( items.ToAsyncEnumerable(), items.Count, @@ -210,7 +217,57 @@ public class ServerConfig } await ctx.Paginate(channels.ToAsyncEnumerable(), channels.Count, 25, - $"Blacklisted channels for {ctx.Guild.Name}", + $"Blacklisted channels for proxying in {ctx.Guild.Name}", + null, + async (eb, l) => + { + async Task CategoryName(ulong? id) => + id != null ? (await _cache.GetChannel(ctx.Guild.Id, id.Value)).Name : "(no category)"; + + ulong? lastCategory = null; + + var fieldValue = new StringBuilder(); + foreach (var channel in l) + { + if (lastCategory != channel!.ParentId && fieldValue.Length > 0) + { + eb.Field(new Embed.Field(await CategoryName(lastCategory), fieldValue.ToString())); + fieldValue.Clear(); + } + else + { + fieldValue.Append("\n"); + } + + fieldValue.Append(channel.Mention()); + lastCategory = channel.ParentId; + } + + eb.Field(new Embed.Field(await CategoryName(lastCategory), fieldValue.ToString())); + }); + } + + public async Task ShowCommandBlacklisted(Context ctx) + { + await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); + + var blacklist = await ctx.Repository.GetGuild(ctx.Guild.Id); + + // Resolve all channels from the cache and order by position + var channels = (await Task.WhenAll(blacklist.CommandBlacklist + .Select(id => _cache.TryGetChannel(ctx.Guild.Id, id)))) + .Where(c => c != null) + .OrderBy(c => c.Position) + .ToList(); + + if (channels.Count == 0) + { + await ctx.Reply("This server has no channels where running text commands is disabled."); + return; + } + + await ctx.Paginate(channels.ToAsyncEnumerable(), channels.Count, 25, + $"Blacklisted channels for running text commands in {ctx.Guild.Name}", null, async (eb, l) => { @@ -323,7 +380,40 @@ public class ServerConfig await ctx.Repository.UpdateGuild(ctx.Guild.Id, new GuildPatch { ProxyBlacklist = blacklist.ToArray() }); await ctx.Reply( - $"{Emojis.Success} Channels {(shouldAdd ? "added to" : "removed from")} the proxy blacklist."); + $"{Emojis.Success} Channel(s) {(shouldAdd ? "added to" : "removed from")} the proxy blacklist."); + } + + public async Task SetCommandBlacklisted(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.CommandBlacklist.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 { CommandBlacklist = blacklist.ToArray() }); + + await ctx.Reply( + $"{Emojis.Success} Channel(s) {(shouldAdd ? "added to" : "removed from")} the command blacklist."); } public async Task SetLogBlacklisted(Context ctx, bool shouldAdd) diff --git a/PluralKit.Bot/Handlers/MessageCreated.cs b/PluralKit.Bot/Handlers/MessageCreated.cs index a14d024b..387d8659 100644 --- a/PluralKit.Bot/Handlers/MessageCreated.cs +++ b/PluralKit.Bot/Handlers/MessageCreated.cs @@ -140,7 +140,22 @@ public class MessageCreated: IEventHandler var config = system != null ? await _repo.GetSystemConfig(system.Id) : null; var guildConfig = guild != null ? await _repo.GetGuild(guild.Id) : null; - await _tree.ExecuteCommand(new Context(_services, shardId, guild, channel, evt, cmdStart, system, config, guildConfig, _config.Prefixes ?? BotConfig.DefaultPrefixes)); + var ctx = new Context(_services, shardId, guild, channel, evt, cmdStart, system, config, guildConfig, _config.Prefixes ?? BotConfig.DefaultPrefixes); + + // If we're in a guild we need to check if this channel is on the command blacklist + if (guild is not null) + { + // If we're in a thread we want to check the root channel and the thread + var rootChannel = channel.IsThread() ? await _rest.GetChannelOrNull(channel.ParentId!.Value) : channel; + var msgCtx = await _repo.GetMessageContext(evt.Author.Id, guild.Id, rootChannel.Id, channel.Id != rootChannel.Id ? channel.Id : default); + // If the channel is in the command blacklist, then check if author has Manage Server + // If they do, we let the command run regardless + // If they don't a PK Error gets thrown here and caught in the catch + if (msgCtx.InCommandBlacklist) + await ctx.CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server"); ; + } + + await _tree.ExecuteCommand(ctx); } catch (PKError) { diff --git a/PluralKit.Core/Database/Functions/MessageContext.cs b/PluralKit.Core/Database/Functions/MessageContext.cs index 876dabc2..99b6b94a 100644 --- a/PluralKit.Core/Database/Functions/MessageContext.cs +++ b/PluralKit.Core/Database/Functions/MessageContext.cs @@ -33,6 +33,7 @@ public class MessageContext public ulong? LogChannel { get; } public bool InProxyBlacklist { get; } + public bool InCommandBlacklist { get; } public bool InLogBlacklist { get; } public bool LogCleanupEnabled { get; } public bool RequireSystemTag { get; } diff --git a/PluralKit.Core/Database/Utils/DatabaseMigrator.cs b/PluralKit.Core/Database/Utils/DatabaseMigrator.cs index 1161cf31..9886c21a 100644 --- a/PluralKit.Core/Database/Utils/DatabaseMigrator.cs +++ b/PluralKit.Core/Database/Utils/DatabaseMigrator.cs @@ -9,7 +9,7 @@ namespace PluralKit.Core; internal class DatabaseMigrator { private const string RootPath = "PluralKit.Core.Database"; // "resource path" root for SQL files - private const int TargetSchemaVersion = 54; + private const int TargetSchemaVersion = 55; private readonly ILogger _logger; public DatabaseMigrator(ILogger logger) diff --git a/PluralKit.Core/Models/GuildConfig.cs b/PluralKit.Core/Models/GuildConfig.cs index 9e6cf6a6..71a4370b 100644 --- a/PluralKit.Core/Models/GuildConfig.cs +++ b/PluralKit.Core/Models/GuildConfig.cs @@ -6,6 +6,7 @@ public class GuildConfig public ulong? LogChannel { get; } public ulong[] LogBlacklist { get; } public ulong[] ProxyBlacklist { get; } + public ulong[] CommandBlacklist { get; } public bool LogCleanupEnabled { get; } public bool InvalidCommandResponseEnabled { get; } public bool RequireSystemTag { get; } diff --git a/PluralKit.Core/Models/Patch/GuildPatch.cs b/PluralKit.Core/Models/Patch/GuildPatch.cs index f814e909..9a54fc97 100644 --- a/PluralKit.Core/Models/Patch/GuildPatch.cs +++ b/PluralKit.Core/Models/Patch/GuildPatch.cs @@ -7,6 +7,7 @@ public class GuildPatch: PatchObject public Partial LogChannel { get; set; } public Partial LogBlacklist { get; set; } public Partial ProxyBlacklist { get; set; } + public Partial CommandBlacklist { get; set; } public Partial LogCleanupEnabled { get; set; } public Partial InvalidCommandResponseEnabled { get; set; } public Partial RequireSystemTag { get; set; } @@ -16,6 +17,7 @@ public class GuildPatch: PatchObject .With("log_channel", LogChannel) .With("log_blacklist", LogBlacklist) .With("proxy_blacklist", ProxyBlacklist) + .With("command_blacklist", CommandBlacklist) .With("log_cleanup_enabled", LogCleanupEnabled) .With("invalid_command_response_enabled", InvalidCommandResponseEnabled) .With("require_system_tag", RequireSystemTag) diff --git a/crates/migrate/data/functions.sql b/crates/migrate/data/functions.sql index 6ec03ee8..8e21d1b3 100644 --- a/crates/migrate/data/functions.sql +++ b/crates/migrate/data/functions.sql @@ -24,6 +24,7 @@ create function message_context(account_id bigint, guild_id bigint, channel_id b log_channel bigint, in_proxy_blacklist bool, + in_command_blacklist bool, in_log_blacklist bool, log_cleanup_enabled bool, require_system_tag bool, @@ -61,9 +62,11 @@ as $$ system_last_switch.timestamp as last_switch_timestamp, -- servers table - servers.log_channel as log_channel, + servers.log_channel as log_channel, ((channel_id = any (servers.proxy_blacklist)) or (thread_id = any (servers.proxy_blacklist))) as in_proxy_blacklist, + ((channel_id = any (servers.command_blacklist)) + or (thread_id = any (servers.command_blacklist))) as in_command_blacklist, ((channel_id = any (servers.log_blacklist)) or (thread_id = any (servers.log_blacklist))) as in_log_blacklist, coalesce(servers.log_cleanup_enabled, false) as log_cleanup_enabled, diff --git a/crates/migrate/data/migrations/55.sql b/crates/migrate/data/migrations/55.sql new file mode 100644 index 00000000..87e26416 --- /dev/null +++ b/crates/migrate/data/migrations/55.sql @@ -0,0 +1,6 @@ +-- database version 55 +-- add command blacklist option for servers + +alter table servers add column command_blacklist bigint[] not null default array[]::bigint[]; + +update info set schema_version = 55; \ No newline at end of file diff --git a/docs/content/command-list.md b/docs/content/command-list.md index 80abf707..dfd25a89 100644 --- a/docs/content/command-list.md +++ b/docs/content/command-list.md @@ -167,6 +167,9 @@ You can have a space after `pk;`, e.g. `pk;system` and `pk; system` will do the - `pk;serverconfig proxy blacklist` - Displays the current proxy blacklist - `pk;serverconfig proxy blacklist add all| [channel 2] [channel 3...]` - Adds certain channels to the proxy blacklist - `pk;serverconfig proxy blacklist remove all| [channel 2] [channel 3...]` - Removes certain channels from the proxy blacklist +- `pk;serverconfig command blacklist` - Displays the current command blacklist +- `pk;serverconfig command blacklist add all| [channel 2] [channel 3...]` - Adds certain channels to the command blacklist +- `pk;serverconfig command blacklist remove all| [channel 2] [channel 3...]` - Removes certain channels from the command blacklist ## Utility - `pk;message ` - Looks up information about a proxied message by its message ID or link. diff --git a/docs/content/staff/disabling.md b/docs/content/staff/disabling.md index c585ffc4..07c1110b 100644 --- a/docs/content/staff/disabling.md +++ b/docs/content/staff/disabling.md @@ -1,4 +1,7 @@ -# Disabling proxying in a channel +# Disabling bot functionality +You can use the blacklist commands to disable proxying or text commands in some channels of your server. [You can also disable PluralKit by taking away its permissions.](/staff/permissions) + +## Disabling proxying in a channel It's possible to block a channel from being used for proxying. To do so, use the `pk;serverconfig proxy blacklist` command. For example: pk;serverconfig proxy blacklist add #admin-channel #mod-channel #welcome @@ -6,4 +9,14 @@ It's possible to block a channel from being used for proxying. To do so, use the pk;serverconfig proxy blacklist remove #general-two pk;serverconfig proxy blacklist remove all -This requires you to have the *Manage Server* permission on the server. \ No newline at end of file +This requires you to have the *Manage Server* permission on the server. + +## Disabling commands in a channel +It's possible to block a channel from being used for text commands. To do so, use the `pk;serverconfig command blacklist` command. For example: + + pk;serverconfig command blacklist add #admin-channel #mod-channel #welcome + pk;serverconfig command blacklist add all + pk;serverconfig command blacklist remove #general-two + pk;serverconfig command blacklist remove all + +This requires you to have the *Manage Server* permission on the server. If you have the *Manage Server* permission on the server you **will not be affected by the command blacklist** and will always be able to run commands. \ No newline at end of file