diff --git a/PluralKit.Bot/CommandMeta/CommandHelp.cs b/PluralKit.Bot/CommandMeta/CommandHelp.cs index 3938a0d9..6138f4ed 100644 --- a/PluralKit.Bot/CommandMeta/CommandHelp.cs +++ b/PluralKit.Bot/CommandMeta/CommandHelp.cs @@ -55,6 +55,7 @@ public partial class CommandTree public static Command MemberAutoproxy = new Command("member autoproxy", "member autoproxy [on|off]", "Sets whether a member will be autoproxied when autoproxy is set to latch or front mode."); public static Command MemberKeepProxy = new Command("member keepproxy", "member keepproxy [on|off]", "Sets whether to include a member's proxy tags when proxying"); public static Command MemberTts = new Command("member text-to-speech", "member text-to-speech [on|off]", "Sets whether to send a member's messages as text-to-speech messages."); + public static Command MemberServerKeepProxy = new Command("member server keepproxy", "member serverkeepproxy [on|off]", "Sets whether to include a member's proxy tags when proxying in the current server."); public static Command MemberRandom = new Command("system random", "system [system] random", "Shows the info card of a randomly selected member in a system."); public static Command MemberId = new Command("member id", "member [member] id", "Prints a member's id."); public static Command MemberPrivacy = new Command("member privacy", "member privacy ", "Changes a members's privacy settings"); @@ -153,4 +154,4 @@ public partial class CommandTree public static Command[] LogCommands = { LogChannel, LogChannelClear, LogEnable, LogDisable, LogShow }; public static Command[] BlacklistCommands = { BlacklistAdd, BlacklistRemove, BlacklistShow }; -} \ No newline at end of file +} diff --git a/PluralKit.Bot/CommandMeta/CommandTree.cs b/PluralKit.Bot/CommandMeta/CommandTree.cs index c09447ea..0ac03515 100644 --- a/PluralKit.Bot/CommandMeta/CommandTree.cs +++ b/PluralKit.Bot/CommandMeta/CommandTree.cs @@ -338,6 +338,8 @@ public partial class CommandTree await ctx.Execute(MemberKeepProxy, m => m.KeepProxy(ctx, target)); else if (ctx.Match("texttospeech", "text-to-speech", "tts")) await ctx.Execute(MemberTts, m => m.Tts(ctx, target)); + else if (ctx.Match("serverkeepproxy", "servershowtags", "guildshowtags", "guildkeeptags", "serverkeeptags", "skp")) + await ctx.Execute(MemberServerKeepProxy, m => m.ServerKeepProxy(ctx, target)); else if (ctx.Match("id")) await ctx.Execute(MemberId, m => m.DisplayId(ctx, target)); else if (ctx.Match("privacy")) @@ -538,4 +540,4 @@ public partial class CommandTree // todo: maybe add the list of configuration keys here? return ctx.Reply($"{Emojis.Error} Could not find a setting with that name. Please see `pk;commands config` for the list of possible config settings."); } -} \ No newline at end of file +} diff --git a/PluralKit.Bot/Commands/MemberEdit.cs b/PluralKit.Bot/Commands/MemberEdit.cs index 51589f3c..35f7704d 100644 --- a/PluralKit.Bot/Commands/MemberEdit.cs +++ b/PluralKit.Bot/Commands/MemberEdit.cs @@ -494,6 +494,7 @@ public class MemberEdit public async Task KeepProxy(Context ctx, PKMember target) { ctx.CheckSystem().CheckOwnMember(target); + var memberGuildConfig = await ctx.Repository.GetMemberGuild(ctx.Guild.Id, target.Id); bool newValue; if (ctx.Match("on", "enabled", "true", "yes")) @@ -510,12 +511,19 @@ public class MemberEdit } else { + string keepProxyStatusMessage = ""; + if (target.KeepProxy) - await ctx.Reply( - "This member has keepproxy **enabled**, which means proxy tags will be **included** in the resulting message when proxying."); + keepProxyStatusMessage += "This member has keepproxy **enabled**. Proxy tags will be **included** in the resulting message when proxying."; else - await ctx.Reply( - "This member has keepproxy **disabled**, which means proxy tags will **not** be included in the resulting message when proxying."); + keepProxyStatusMessage += "This member has keepproxy **disabled**. Proxy tags will **not** be included in the resulting message when proxying."; + + if (memberGuildConfig.KeepProxy.HasValue && memberGuildConfig.KeepProxy.Value) + keepProxyStatusMessage += $"\n{Emojis.Warn} This member has keepproxy **enabled in this server**, which means proxy tags will **always** be included when proxying in this server, regardless of the global keepproxy."; + else if (memberGuildConfig.KeepProxy.HasValue && !memberGuildConfig.KeepProxy.Value) + keepProxyStatusMessage += $"\n{Emojis.Warn} This member has keepproxy **disabled in this server**, which means proxy tags will **never** be included when proxying in this server, regardless of the global keepproxy."; + + await ctx.Reply(keepProxyStatusMessage); return; } @@ -524,12 +532,88 @@ public class MemberEdit var patch = new MemberPatch { KeepProxy = Partial.Present(newValue) }; await ctx.Repository.UpdateMember(target.Id, patch); + string keepProxyUpdateMessage = ""; + if (newValue) - await ctx.Reply( - $"{Emojis.Success} Member proxy tags will now be included in the resulting message when proxying."); + keepProxyUpdateMessage += $"{Emojis.Success} this member now has keepproxy **enabled**. Member proxy tags will be **included** in the resulting message when proxying."; else - await ctx.Reply( - $"{Emojis.Success} Member proxy tags will now not be included in the resulting message when proxying."); + keepProxyUpdateMessage += $"{Emojis.Success} this member now has keepproxy **disabled**. Member proxy tags will be **included** in the resulting message when proxying."; + + if (memberGuildConfig.KeepProxy.HasValue && memberGuildConfig.KeepProxy.Value) + keepProxyUpdateMessage += $"\n{Emojis.Warn} This member has keepproxy **enabled in this server**, which means proxy tags will **always** be included when proxying in this server, regardless of the global keepproxy."; + else if (memberGuildConfig.KeepProxy.HasValue && !memberGuildConfig.KeepProxy.Value) + keepProxyUpdateMessage += $"\n{Emojis.Warn} This member has keepproxy **disabled in this server**, which means proxy tags will **never** be included when proxying in this server, regardless of the global keepproxy."; + + await ctx.Reply(keepProxyUpdateMessage); + } + + public async Task ServerKeepProxy(Context ctx, PKMember target) + { + ctx.CheckGuildContext(); + ctx.CheckSystem().CheckOwnMember(target); + + var memberGuildConfig = await ctx.Repository.GetMemberGuild(ctx.Guild.Id, target.Id); + + bool? newValue; + if (ctx.Match("on", "enabled", "true", "yes")) + { + newValue = true; + } + else if (ctx.Match("off", "disabled", "false", "no")) + { + newValue = false; + } + else if (ctx.MatchClear()) + { + newValue = null; + } + else if (ctx.HasNext()) + { + throw new PKSyntaxError("You must pass either \"on\" or \"off\"."); + } + else + { + if (memberGuildConfig.KeepProxy.HasValue) + if (memberGuildConfig.KeepProxy.Value) + await ctx.Reply( + "This member has keepproxy **enabled** in the current server, which means proxy tags will be **included** in the resulting message when proxying."); + else + await ctx.Reply( + "This member has keepproxy **disabled** in the current server, which means proxy tags will **not** be included in the resulting message when proxying."); + else + { + var noServerKeepProxySetMessage = "This member does not have a server keepproxy override set."; + if (target.KeepProxy) + noServerKeepProxySetMessage += " The global keepproxy is **enabled**, which means proxy tags will be **included** when proxying."; + else + noServerKeepProxySetMessage += " The global keepproxy is **disabled**, which means proxy tags will **not** be included when proxying."; + + await ctx.Reply(noServerKeepProxySetMessage); + } + return; + } + + var patch = new MemberGuildPatch { KeepProxy = Partial.Present(newValue) }; + await ctx.Repository.UpdateMemberGuild(target.Id, ctx.Guild.Id, patch); + + if (newValue.HasValue) + if (newValue.Value) + await ctx.Reply( + $"{Emojis.Success} Member proxy tags will now be **included** in the resulting message when proxying **in the current server**."); + else + await ctx.Reply( + $"{Emojis.Success} Member proxy tags will now **not** be included in the resulting message when proxying **in the current server**."); + else + { + var serverKeepProxyClearedMessage = $"{Emojis.Success} Cleared server keepproxy settings for this member."; + + if (target.KeepProxy) + serverKeepProxyClearedMessage += " Member proxy tags will now be **included** in the resulting message when proxying."; + else + serverKeepProxyClearedMessage += " Member proxy tags will now **not** be included in the resulting message when proxying."; + + await ctx.Reply(serverKeepProxyClearedMessage); + } } public async Task Tts(Context ctx, PKMember target) diff --git a/PluralKit.Bot/Proxy/ProxyMatch.cs b/PluralKit.Bot/Proxy/ProxyMatch.cs index 663e0679..db233c9f 100644 --- a/PluralKit.Bot/Proxy/ProxyMatch.cs +++ b/PluralKit.Bot/Proxy/ProxyMatch.cs @@ -9,13 +9,22 @@ public struct ProxyMatch public string? Content; public ProxyTag? ProxyTags; + private bool ShouldKeepProxy() + { + if (Member.ServerKeepProxy != null && Member.ServerKeepProxy.Value) + return true; + else if (Member.KeepProxy && !(Member.ServerKeepProxy != null && !Member.ServerKeepProxy.Value)) + return true; + else return false; + } + public string? ProxyContent { get { // Add the proxy tags into the proxied message if that option is enabled // Also check if the member has any proxy tags - some cases autoproxy can return a member with no tags - if (Member.KeepProxy && Content != null && ProxyTags != null) + if (ShouldKeepProxy() && ProxyTags != null && Content != null) return $"{ProxyTags.Value.Prefix}{Content}{ProxyTags.Value.Suffix}"; return Content; diff --git a/PluralKit.Core/Database/Functions/ProxyMember.cs b/PluralKit.Core/Database/Functions/ProxyMember.cs index d42a865e..9a62a579 100644 --- a/PluralKit.Core/Database/Functions/ProxyMember.cs +++ b/PluralKit.Core/Database/Functions/ProxyMember.cs @@ -18,6 +18,7 @@ public class ProxyMember public IReadOnlyCollection ProxyTags { get; } = new ProxyTag[0]; public bool KeepProxy { get; } public bool Tts { get; } + public bool? ServerKeepProxy { get; } public string? ServerName { get; } public string? DisplayName { get; } @@ -44,4 +45,4 @@ public class ProxyMember } public string? ProxyAvatar(MessageContext ctx) => ServerAvatar ?? WebhookAvatar ?? Avatar ?? ctx.SystemGuildAvatar ?? ctx.SystemAvatar; -} \ No newline at end of file +} diff --git a/PluralKit.Core/Database/Functions/functions.sql b/PluralKit.Core/Database/Functions/functions.sql index e1a2e827..152e85b5 100644 --- a/PluralKit.Core/Database/Functions/functions.sql +++ b/PluralKit.Core/Database/Functions/functions.sql @@ -69,6 +69,7 @@ create function proxy_members(account_id bigint, guild_id bigint) proxy_tags proxy_tag[], keep_proxy bool, tts bool, + server_keep_proxy bool, server_name text, display_name text, @@ -89,6 +90,7 @@ as $$ members.proxy_tags as proxy_tags, members.keep_proxy as keep_proxy, members.tts as tts, + member_guild.keep_proxy as server_keep_proxy, -- Name info member_guild.display_name as server_name, @@ -154,4 +156,4 @@ begin if not exists (select 1 from groups where hid = new_hid) then return new_hid; end if; end loop; end -$$ language plpgsql volatile; \ No newline at end of file +$$ language plpgsql volatile; diff --git a/PluralKit.Core/Database/Migrations/40.sql b/PluralKit.Core/Database/Migrations/40.sql new file mode 100644 index 00000000..9a577a83 --- /dev/null +++ b/PluralKit.Core/Database/Migrations/40.sql @@ -0,0 +1,6 @@ +-- database version 40 +-- add per-server keepproxy toggle + +alter table member_guild add column keep_proxy bool default null; + +update info set schema_version = 40; \ No newline at end of file diff --git a/PluralKit.Core/Database/Utils/DatabaseMigrator.cs b/PluralKit.Core/Database/Utils/DatabaseMigrator.cs index d0f8a4e3..0d23591b 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 = 39; + private const int TargetSchemaVersion = 40; private readonly ILogger _logger; public DatabaseMigrator(ILogger logger) diff --git a/PluralKit.Core/Models/MemberGuildSettings.cs b/PluralKit.Core/Models/MemberGuildSettings.cs index 0374b4b8..1fb7b20d 100644 --- a/PluralKit.Core/Models/MemberGuildSettings.cs +++ b/PluralKit.Core/Models/MemberGuildSettings.cs @@ -9,6 +9,7 @@ public class MemberGuildSettings public ulong Guild { get; } public string? DisplayName { get; } public string? AvatarUrl { get; } + public bool? KeepProxy { get; } } public static class MemberGuildExt @@ -19,6 +20,7 @@ public static class MemberGuildExt o.Add("display_name", settings.DisplayName); o.Add("avatar_url", settings.AvatarUrl); + o.Add("keep_proxy", settings.KeepProxy); return o; } diff --git a/PluralKit.Core/Models/Patch/MemberGuildPatch.cs b/PluralKit.Core/Models/Patch/MemberGuildPatch.cs index e5dfec2d..64c1fdaa 100644 --- a/PluralKit.Core/Models/Patch/MemberGuildPatch.cs +++ b/PluralKit.Core/Models/Patch/MemberGuildPatch.cs @@ -10,10 +10,12 @@ public class MemberGuildPatch: PatchObject { public Partial DisplayName { get; set; } public Partial AvatarUrl { get; set; } + public Partial KeepProxy { get; set; } public override Query Apply(Query q) => q.ApplyPatch(wrapper => wrapper .With("display_name", DisplayName) .With("avatar_url", AvatarUrl) + .With("keep_proxy", KeepProxy) ); public new void AssertIsValid() @@ -36,6 +38,9 @@ public class MemberGuildPatch: PatchObject if (o.ContainsKey("avatar_url")) patch.AvatarUrl = o.Value("avatar_url").NullIfEmpty(); + if (o.ContainsKey("keep_proxy")) + patch.KeepProxy = o.Value("keep_proxy"); + return patch; } @@ -51,6 +56,9 @@ public class MemberGuildPatch: PatchObject if (AvatarUrl.IsPresent) o.Add("avatar_url", AvatarUrl.Value); + if (KeepProxy.IsPresent) + o.Add("keep_proxy", KeepProxy.Value); + return o; } } \ No newline at end of file diff --git a/docs/content/command-list.md b/docs/content/command-list.md index c03234ee..30cc254e 100644 --- a/docs/content/command-list.md +++ b/docs/content/command-list.md @@ -92,6 +92,7 @@ You can have a space after `pk;`, e.g. `pk;system` and `pk; system` will do the - `pk;member proxy remove [tags]` - Removes a proxy tag from a member. - `pk;member autoproxy [on|off]` - Sets whether a member will be autoproxied when autoproxy is set to latch or front mode. - `pk;member keepproxy [on|off]` - Sets whether to include a member's proxy tags in the proxied message. +- `pk;member serverkeepproxy [on|off]` - Sets whether to include a member's proxy tag in the proxied message in a specific server. - `pk;member tts [on|off]` - Sets whether to send a member's messages as text-to-speech messages. - `pk;member pronouns [pronouns]` - Changes the pronouns of a member. - `pk;member color [color]` - Changes the color of a member. @@ -180,4 +181,4 @@ You can have a space after `pk;`, e.g. `pk;system` and `pk; system` will do the - `pk;system help` - Lists system-related commands. - `pk;member help` - Lists member-related commands. - `pk;switch help` - Lists switch-related commands. -- `pk;commands` - Shows inline command documentation, or directs you to this page. \ No newline at end of file +- `pk;commands` - Shows inline command documentation, or directs you to this page.