From 9d4006b05648d06d59ee09a9226f3b0c725b2c5f Mon Sep 17 00:00:00 2001 From: spiral Date: Mon, 2 Aug 2021 17:22:06 -0400 Subject: [PATCH] Add server-specific system tag --- PluralKit.Bot/Commands/CommandTree.cs | 3 + PluralKit.Bot/Commands/SystemEdit.cs | 103 +++++++++++++++++- PluralKit.Bot/Services/EmbedService.cs | 6 + .../Database/Functions/MessageContext.cs | 2 + .../Database/Functions/ProxyMember.cs | 14 ++- .../Database/Functions/functions.sql | 9 +- PluralKit.Core/Database/Migrations/16.sql | 7 ++ .../Database/Utils/DatabaseMigrator.cs | 2 +- .../Models/Patch/SystemGuildPatch.cs | 6 +- docs/content/command-list.md | 1 + docs/content/user-guide.md | 17 +++ 11 files changed, 163 insertions(+), 7 deletions(-) create mode 100644 PluralKit.Core/Database/Migrations/16.sql diff --git a/PluralKit.Bot/Commands/CommandTree.cs b/PluralKit.Bot/Commands/CommandTree.cs index 6bea8129..645529f6 100644 --- a/PluralKit.Bot/Commands/CommandTree.cs +++ b/PluralKit.Bot/Commands/CommandTree.cs @@ -15,6 +15,7 @@ namespace PluralKit.Bot public static Command SystemDesc = new Command("system description", "system description [description]", "Changes your system's description"); public static Command SystemColor = new Command("system color", "system color [color]", "Changes your system's color"); public static Command SystemTag = new Command("system tag", "system tag [tag]", "Changes your system's tag"); + public static Command SystemServerTag = new Command("system servertag", "system servertag [tag|enable|disable]", "Changes your system's tag in the current server"); public static Command SystemAvatar = new Command("system icon", "system icon [url|@mention]", "Changes your system's icon"); public static Command SystemBannerImage = new Command("system banner", "system banner [url]", "Set the system's banner image"); public static Command SystemDelete = new Command("system delete", "system delete", "Deletes your system"); @@ -243,6 +244,8 @@ namespace PluralKit.Bot await ctx.Execute(SystemRename, m => m.Name(ctx)); else if (ctx.Match("tag")) await ctx.Execute(SystemTag, m => m.Tag(ctx)); + else if (ctx.Match("servertag")) + await ctx.Execute(SystemServerTag, m => m.ServerTag(ctx)); else if (ctx.Match("description", "desc", "bio")) await ctx.Execute(SystemDesc, m => m.Description(ctx)); else if (ctx.Match("color", "colour")) diff --git a/PluralKit.Bot/Commands/SystemEdit.cs b/PluralKit.Bot/Commands/SystemEdit.cs index da042646..0589a9e0 100644 --- a/PluralKit.Bot/Commands/SystemEdit.cs +++ b/PluralKit.Bot/Commands/SystemEdit.cs @@ -157,7 +157,7 @@ namespace PluralKit.Bot var newTag = ctx.RemainderOrNull(skipFlags: false); if (newTag != null) if (newTag.Length > Limits.MaxSystemTagLength) - throw Errors.SystemNameTooLongError(newTag.Length); + throw Errors.SystemTagTooLongError(newTag.Length); var patch = new SystemPatch {Tag = newTag}; await _db.Execute(conn => _repo.UpdateSystem(conn, ctx.System.Id, patch)); @@ -165,6 +165,107 @@ namespace PluralKit.Bot await ctx.Reply($"{Emojis.Success} System tag changed. Member names will now end with {newTag.AsCode()} when proxied."); } } + + public async Task ServerTag(Context ctx) + { + ctx.CheckSystem().CheckGuildContext(); + + var setDisabledWarning = $"{Emojis.Warn} Your system tag is currently **disabled** in this server. No tag will be applied when proxying.\nTo re-enable the system tag in the current server, type `pk;s servertag -enable`."; + + async Task Show() + { + if (ctx.MessageContext.SystemGuildTag != null) + { + var msg = $"Your current system tag in '{ctx.Guild.Name}' is {ctx.MessageContext.SystemGuildTag.AsCode()}"; + if (!ctx.MessageContext.TagEnabled) + msg += ", but it is currently **disabled**. To re-enable it, type `pk;s servertag -enable`."; + else + msg += ". To change it, type `pk;s tag `. To clear it, type `pk;s tag -clear`."; + + await ctx.Reply(msg); + return; + } + + else if (!ctx.MessageContext.TagEnabled) + await ctx.Reply($"Your global system tag is {ctx.System.Tag}, but it is **disabled** in this server. To re-enable it, type `pk;s servertag -enable`"); + else + await ctx.Reply($"You currently have no system tag specific to the server '{ctx.Guild.Name}'. To set one, type `pk;s servertag `. To disable the system tag in the current server, type `pk;s servertag -disable`."); + } + + async Task Set() + { + var newTag = ctx.RemainderOrNull(skipFlags: false); + if (newTag != null && newTag.Length > Limits.MaxSystemTagLength) + throw Errors.SystemTagTooLongError(newTag.Length); + + var patch = new SystemGuildPatch {Tag = newTag}; + await _db.Execute(conn => _repo.UpsertSystemGuild(conn, ctx.System.Id, ctx.Guild.Id, patch)); + + await ctx.Reply($"{Emojis.Success} System server tag changed. Member names will now end with {newTag.AsCode()} when proxied in the current server '{ctx.Guild.Name}'."); + + if (!ctx.MessageContext.TagEnabled) + await ctx.Reply(setDisabledWarning); + } + + async Task Clear() + { + var patch = new SystemGuildPatch {Tag = null}; + await _db.Execute(conn => _repo.UpsertSystemGuild(conn, ctx.System.Id, ctx.Guild.Id, patch)); + + await ctx.Reply($"{Emojis.Success} System server tag cleared. Member names will now end with the global system tag, if there is one set."); + + if (!ctx.MessageContext.TagEnabled) + await ctx.Reply(setDisabledWarning); + } + + async Task EnableDisable(bool newValue) + { + var patch = new SystemGuildPatch {TagEnabled = newValue}; + await _db.Execute(conn => _repo.UpsertSystemGuild(conn, ctx.System.Id, ctx.Guild.Id, patch)); + + await ctx.Reply(PrintEnableDisableResult(newValue, newValue != ctx.MessageContext.TagEnabled)); + } + + string PrintEnableDisableResult(bool newValue, bool changedValue) + { + var opStr = newValue ? "enabled" : "disabled"; + var str = ""; + + if (!changedValue) + str = $"{Emojis.Note} The system tag is already {opStr} in this server."; + else + str = $"{Emojis.Success} System tag {opStr} in this server."; + + if (newValue == true) + { + if (ctx.MessageContext.TagEnabled) + if (ctx.MessageContext.SystemGuildTag == null) + str += $" However, you do not have a system tag specific to this server. Messages will be proxied using your global system tag, if there is one set."; + else + str += $" Your current system tag in '{ctx.Guild.Name}' is {ctx.MessageContext.SystemGuildTag.AsCode()}."; + else + { + if (ctx.MessageContext.SystemGuildTag != null) + str += $" Member names will now end with the server-specific tag {ctx.MessageContext.SystemGuildTag.AsCode()} when proxied in the current server '{ctx.Guild.Name}'."; + else + str += $" Member names will now end with the global system tag when proxied in the current server, if there is one set."; + } + } + + return str; + } + + if (await ctx.MatchClear("your system's server tag")) + await Clear(); + else if (ctx.Match("disable") || ctx.MatchFlag("disable")) + await EnableDisable(false); + else if (ctx.Match("enable") || ctx.MatchFlag("enable")) + await EnableDisable(true); + else if (!ctx.HasNext(skipFlags: false)) + await Show(); + else + await Set(); + } public async Task Avatar(Context ctx) { diff --git a/PluralKit.Bot/Services/EmbedService.cs b/PluralKit.Bot/Services/EmbedService.cs index 95306542..6cd8c177 100644 --- a/PluralKit.Bot/Services/EmbedService.cs +++ b/PluralKit.Bot/Services/EmbedService.cs @@ -84,6 +84,12 @@ namespace PluralKit.Bot { if (system.Tag != null) eb.Field(new("Tag", system.Tag.EscapeMarkdown(), true)); + if (cctx.MessageContext.SystemGuildTag != null && cctx.MessageContext.TagEnabled) + eb.Field(new($"Tag (in server '{cctx.Guild.Name}')", cctx.MessageContext.SystemGuildTag.EscapeMarkdown(), true)); + + if (!cctx.MessageContext.TagEnabled) + eb.Field(new($"Tag (in server '{cctx.Guild.Name}')", "*(tag is disabled in this server)*")); + if (!system.Color.EmptyOrNull()) eb.Field(new("Color", $"#{system.Color}", true)); eb.Field(new("Linked accounts", string.Join("\n", users).Truncate(1000), true)); diff --git a/PluralKit.Core/Database/Functions/MessageContext.cs b/PluralKit.Core/Database/Functions/MessageContext.cs index a3a6444f..aee600c7 100644 --- a/PluralKit.Core/Database/Functions/MessageContext.cs +++ b/PluralKit.Core/Database/Functions/MessageContext.cs @@ -23,6 +23,8 @@ namespace PluralKit.Core public MemberId[] LastSwitchMembers { get; } = new MemberId[0]; public Instant? LastSwitchTimestamp { get; } public string? SystemTag { get; } + public string? SystemGuildTag { get; } + public bool TagEnabled { get; } public string? SystemAvatar { get; } public bool AllowAutoproxy { get; } public int? LatchTimeout { get; } diff --git a/PluralKit.Core/Database/Functions/ProxyMember.cs b/PluralKit.Core/Database/Functions/ProxyMember.cs index 681ef179..072821cd 100644 --- a/PluralKit.Core/Database/Functions/ProxyMember.cs +++ b/PluralKit.Core/Database/Functions/ProxyMember.cs @@ -23,10 +23,18 @@ namespace PluralKit.Core public bool AllowAutoproxy { get; } public string? Color { get; } - public string ProxyName(MessageContext ctx) => ctx.SystemTag != null - ? $"{ServerName ?? DisplayName ?? Name} {ctx.SystemTag}" - : ServerName ?? DisplayName ?? Name; + public string ProxyName(MessageContext ctx) + { + var memberName = ServerName ?? DisplayName ?? Name; + if (!ctx.TagEnabled) + return memberName; + if (ctx.SystemGuildTag != null) + return $"{memberName} {ctx.SystemGuildTag}"; + else if (ctx.SystemTag != null) + return $"{memberName} {ctx.SystemTag}"; + else return memberName; + } public string? ProxyAvatar(MessageContext ctx) => ServerAvatar ?? Avatar ?? ctx.SystemAvatar; public ProxyMember() { } diff --git a/PluralKit.Core/Database/Functions/functions.sql b/PluralKit.Core/Database/Functions/functions.sql index 55628d49..d1b40656 100644 --- a/PluralKit.Core/Database/Functions/functions.sql +++ b/PluralKit.Core/Database/Functions/functions.sql @@ -14,6 +14,8 @@ last_switch_members int[], last_switch_timestamp timestamp, system_tag text, + system_guild_tag text, + tag_enabled bool, system_avatar text, allow_autoproxy bool, latch_timeout integer @@ -21,7 +23,10 @@ as $$ -- CTEs to query "static" (accessible only through args) data with - system as (select systems.*, allow_autoproxy as account_autoproxy from accounts inner join systems on systems.id = accounts.system where accounts.uid = account_id), + system as (select systems.*, system_guild.tag as guild_tag, system_guild.tag_enabled as tag_enabled, allow_autoproxy as account_autoproxy from accounts + left join systems on systems.id = accounts.system + left join system_guild on system_guild.system = accounts.system and system_guild.guild = guild_id + where accounts.uid = account_id), guild as (select * from servers where id = guild_id), last_message as (select * from messages where messages.guild = guild_id and messages.sender = account_id order by mid desc limit 1) select @@ -39,6 +44,8 @@ as $$ system_last_switch.members as last_switch_members, system_last_switch.timestamp as last_switch_timestamp, system.tag as system_tag, + system.guild_tag as system_guild_tag, + system.tag_enabled as tag_enabled, system.avatar_url as system_avatar, system.account_autoproxy as allow_autoproxy, system.latch_timeout as latch_timeout diff --git a/PluralKit.Core/Database/Migrations/16.sql b/PluralKit.Core/Database/Migrations/16.sql new file mode 100644 index 00000000..2bd1f013 --- /dev/null +++ b/PluralKit.Core/Database/Migrations/16.sql @@ -0,0 +1,7 @@ +-- SCHEMA VERSION 16: 2021-08-02 -- +-- Add server-specific system tag -- + +alter table system_guild add column tag text default null; +alter table system_guild add column tag_enabled bool not null default true; + +update info set schema_version = 16; \ No newline at end of file diff --git a/PluralKit.Core/Database/Utils/DatabaseMigrator.cs b/PluralKit.Core/Database/Utils/DatabaseMigrator.cs index c299eda6..ea9353ea 100644 --- a/PluralKit.Core/Database/Utils/DatabaseMigrator.cs +++ b/PluralKit.Core/Database/Utils/DatabaseMigrator.cs @@ -12,7 +12,7 @@ namespace PluralKit.Core internal class DatabaseMigrator { private const string RootPath = "PluralKit.Core.Database"; // "resource path" root for SQL files - private const int TargetSchemaVersion = 15; + private const int TargetSchemaVersion = 16; private readonly ILogger _logger; public DatabaseMigrator(ILogger logger) diff --git a/PluralKit.Core/Models/Patch/SystemGuildPatch.cs b/PluralKit.Core/Models/Patch/SystemGuildPatch.cs index 51b68e2a..eb2cf499 100644 --- a/PluralKit.Core/Models/Patch/SystemGuildPatch.cs +++ b/PluralKit.Core/Models/Patch/SystemGuildPatch.cs @@ -6,10 +6,14 @@ namespace PluralKit.Core public Partial ProxyEnabled { get; set; } public Partial AutoproxyMode { get; set; } public Partial AutoproxyMember { get; set; } + public Partial Tag { get; set; } + public Partial TagEnabled { get; set; } public override UpdateQueryBuilder Apply(UpdateQueryBuilder b) => b .With("proxy_enabled", ProxyEnabled) .With("autoproxy_mode", AutoproxyMode) - .With("autoproxy_member", AutoproxyMember); + .With("autoproxy_member", AutoproxyMember) + .With("tag", Tag) + .With("tag_enabled", TagEnabled); } } \ No newline at end of file diff --git a/docs/content/command-list.md b/docs/content/command-list.md index 601749f4..efa76e98 100644 --- a/docs/content/command-list.md +++ b/docs/content/command-list.md @@ -42,6 +42,7 @@ Some arguments indicate the use of specific Discord features. These include: - `pk;system privacy` - Displays your system's current privacy settings. - `pk;system privacy ` - Changes your systems privacy settings. - `pk;system tag [tag]` - Changes the system tag of your system. +- `pk;system servertag [tag|-enable|-disable]` - Changes your system's tag in the current server, or disables it for the current server. - `pk;system timezone [location]` - Changes the time zone of your system. - `pk;system proxy [server id] [on|off]` - Toggles message proxying for a specific server. - `pk;system delete` - Deletes your system. diff --git a/docs/content/user-guide.md b/docs/content/user-guide.md index ab0bd18f..b75fbb90 100644 --- a/docs/content/user-guide.md +++ b/docs/content/user-guide.md @@ -74,6 +74,23 @@ If you want to remove your system tag, just type `pk;system tag` with no extra p to bump it over that limit. PluralKit will warn you if you have a member name/tag combination that will bring the combined username above the limit. You can either make the member name or the system tag shorter to solve this. +### System server tags +If you'd like to set a system tag (as above), but only for a specific server, you can set the *system server tag*. This will override the global system tag, but only in the server you set it in. For example: + +``` +pk;system servertag 🛰️ +``` + +The server tag applies to the same server you run the command in, so this command doesn't function in DMs. + +To remove an existing server-specific system tag, use the command `pk;system servertag -clear`. + +::: tip +It is possible to disable the system tag for a specific server. Use the command `pk;system servertag -disable`. + +To re-enable it, use the command `pk;system servertag -enable`. +::: + ### Adding or removing Discord accounts to the system If you have multiple Discord accounts you want to use the same system on, you don't need to create multiple systems. Instead, you can *link* the same system to multiple accounts.