From 3603d52e9eac33bdc87a9ba0fd0768ec8746848e Mon Sep 17 00:00:00 2001 From: Spectralitree Date: Sun, 28 Mar 2021 12:02:41 +0200 Subject: [PATCH] Add group and system colors --- .gitignore | 3 +- PluralKit.Bot/Commands/CommandTree.cs | 10 ++++- PluralKit.Bot/Commands/Groups.cs | 48 ++++++++++++++++++++++ PluralKit.Bot/Commands/SystemEdit.cs | 42 +++++++++++++++++++ PluralKit.Bot/Services/EmbedService.cs | 25 ++++++++++- PluralKit.Core/Database/Database.cs | 2 +- PluralKit.Core/Database/Migrations/13.sql | 7 ++++ PluralKit.Core/Models/PKGroup.cs | 1 + PluralKit.Core/Models/PKSystem.cs | 1 + PluralKit.Core/Models/Patch/GroupPatch.cs | 2 + PluralKit.Core/Models/Patch/SystemPatch.cs | 2 + 11 files changed, 138 insertions(+), 5 deletions(-) create mode 100644 PluralKit.Core/Database/Migrations/13.sql diff --git a/.gitignore b/.gitignore index 35c2cd6f..764fd1b3 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,5 @@ pluralkit.*.conf *.DotSettings.user # Generated -logs/ \ No newline at end of file +logs/ +*.dll diff --git a/PluralKit.Bot/Commands/CommandTree.cs b/PluralKit.Bot/Commands/CommandTree.cs index ad763670..a36f9090 100644 --- a/PluralKit.Bot/Commands/CommandTree.cs +++ b/PluralKit.Bot/Commands/CommandTree.cs @@ -13,6 +13,7 @@ namespace PluralKit.Bot public static Command SystemNew = new Command("system new", "system new [name]", "Creates a new system"); public static Command SystemRename = new Command("system name", "system rename [name]", "Renames your system"); 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 SystemAvatar = new Command("system icon", "system icon [url|@mention]", "Changes your system's icon"); public static Command SystemDelete = new Command("system delete", "system delete", "Deletes your system"); @@ -55,6 +56,7 @@ namespace PluralKit.Bot public static Command GroupRename = new Command("group rename", "group rename ", "Renames a group"); public static Command GroupDisplayName = new Command("group displayname", "group displayname [display name]", "Changes a group's display name"); public static Command GroupDesc = new Command("group description", "group description [description]", "Changes a group's description"); + public static Command GroupColor = new Command("group color", "group color [color]", "Changes a group's color"); public static Command GroupAdd = new Command("group add", "group add [member 2] [member 3...]", "Adds one or more members to a group"); public static Command GroupRemove = new Command("group remove", "group remove [member 2] [member 3...]", "Removes one or more members from a group"); public static Command GroupPrivacy = new Command("group privacy", "group privacy ", "Changes a group's privacy settings"); @@ -89,7 +91,7 @@ namespace PluralKit.Bot public static Command PermCheck = new Command("permcheck", "permcheck ", "Checks whether a server's permission setup is correct"); public static Command[] SystemCommands = { - SystemInfo, SystemNew, SystemRename, SystemTag, SystemDesc, SystemAvatar, SystemDelete, SystemTimezone, + SystemInfo, SystemNew, SystemRename, SystemTag, SystemDesc, SystemAvatar, SystemColor, SystemDelete, SystemTimezone, SystemList, SystemFronter, SystemFrontHistory, SystemFrontPercent, SystemPrivacy, SystemProxy }; @@ -102,7 +104,7 @@ namespace PluralKit.Bot public static Command[] GroupCommands = { GroupInfo, GroupList, GroupNew, GroupAdd, GroupRemove, GroupMemberList, GroupRename, GroupDesc, - GroupIcon, GroupPrivacy, GroupDelete + GroupIcon, GroupColor, GroupPrivacy, GroupDelete }; public static Command[] GroupCommandsTargeted = @@ -218,6 +220,8 @@ namespace PluralKit.Bot await ctx.Execute(SystemTag, m => m.Tag(ctx)); else if (ctx.Match("description", "desc", "bio")) await ctx.Execute(SystemDesc, m => m.Description(ctx)); + else if (ctx.Match("color", "colour")) + await ctx.Execute(SystemColor, m => m.Color(ctx)); else if (ctx.Match("avatar", "picture", "icon", "image", "pic", "pfp")) await ctx.Execute(SystemAvatar, m => m.Avatar(ctx)); else if (ctx.Match("delete", "remove", "destroy", "erase", "yeet")) @@ -398,6 +402,8 @@ namespace PluralKit.Bot await ctx.Execute(GroupDelete, g => g.DeleteGroup(ctx, target)); else if (ctx.Match("avatar", "picture", "icon", "image", "pic", "pfp")) await ctx.Execute(GroupIcon, g => g.GroupIcon(ctx, target)); + else if (ctx.Match("color", "colour")) + await ctx.Execute(GroupColor, g => g.GroupColor(ctx, target)); else if (ctx.Match("fp", "frontpercent", "front%", "frontbreakdown")) await ctx.Execute(GroupFrontPercent, g => g.GroupFrontPercent(ctx, target)); else if (!ctx.HasNext()) diff --git a/PluralKit.Bot/Commands/Groups.cs b/PluralKit.Bot/Commands/Groups.cs index 4259dff8..6c68bb24 100644 --- a/PluralKit.Bot/Commands/Groups.cs +++ b/PluralKit.Bot/Commands/Groups.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using System.Threading.Tasks; using Dapper; @@ -226,6 +227,53 @@ namespace PluralKit.Bot else await ShowIcon(); } + public async Task GroupColor(Context ctx, PKGroup target) + { + var color = ctx.RemainderOrNull(); + if (await ctx.MatchClear()) + { + ctx.CheckOwnGroup(target); + + var patch = new GroupPatch {Color = Partial.Null()}; + await _db.Execute(conn => _repo.UpdateGroup(conn, target.Id, patch)); + + await ctx.Reply($"{Emojis.Success} Group color cleared."); + } + else if (!ctx.HasNext()) + { + + if (target.Color == null) + if (ctx.System?.Id == target.System) + await ctx.Reply( + $"This group does not have a color set. To set one, type `pk;group {target.Reference()} color `."); + else + await ctx.Reply("This group does not have a color set."); + else + await ctx.Reply(embed: new EmbedBuilder() + .Title("Group color") + .Color(target.Color.ToDiscordColor()) + .Thumbnail(new($"https://fakeimg.pl/256x256/{target.Color}/?text=%20")) + .Description($"This group's color is **#{target.Color}**." + + (ctx.System?.Id == target.System ? $" To clear it, type `pk;group {target.Reference()} color -clear`." : "")) + .Build()); + } + else + { + ctx.CheckOwnGroup(target); + + if (color.StartsWith("#")) color = color.Substring(1); + if (!Regex.IsMatch(color, "^[0-9a-fA-F]{6}$")) throw Errors.InvalidColorError(color); + + var patch = new GroupPatch {Color = Partial.Present(color.ToLowerInvariant())}; + await _db.Execute(conn => _repo.UpdateGroup(conn, target.Id, patch)); + + await ctx.Reply(embed: new EmbedBuilder() + .Title($"{Emojis.Success} Group color changed.") + .Color(color.ToDiscordColor()) + .Thumbnail(new($"https://fakeimg.pl/256x256/{color}/?text=%20")) + .Build()); + } + } public async Task ListSystemGroups(Context ctx, PKSystem system) { diff --git a/PluralKit.Bot/Commands/SystemEdit.cs b/PluralKit.Bot/Commands/SystemEdit.cs index 7895b932..915d3bd8 100644 --- a/PluralKit.Bot/Commands/SystemEdit.cs +++ b/PluralKit.Bot/Commands/SystemEdit.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Text.RegularExpressions; using System.Threading.Tasks; using Myriad.Builders; @@ -91,6 +92,47 @@ namespace PluralKit.Bot await ctx.Reply($"{Emojis.Success} System description changed."); } } + + public async Task Color(Context ctx) { + ctx.CheckSystem(); + + if (await ctx.MatchClear()) + { + var patch = new SystemPatch {Color = Partial.Null()}; + await _db.Execute(conn => _repo.UpdateSystem(conn, ctx.System.Id, patch)); + + await ctx.Reply($"{Emojis.Success} System color cleared."); + } + else if (!ctx.HasNext()) + { + if (ctx.System.Color == null) + await ctx.Reply( + $"Your system does not have a color set. To set one, type `pk;system color `."); + else + await ctx.Reply(embed: new EmbedBuilder() + .Title("System color") + .Color(ctx.System.Color.ToDiscordColor()) + .Thumbnail(new($"https://fakeimg.pl/256x256/{ctx.System.Color}/?text=%20")) + .Description($"Your system's color is **#{ctx.System.Color}**. To clear it, type `pk;s color -clear`.") + .Build()); + } + else + { + var color = ctx.RemainderOrNull(); + + if (color.StartsWith("#")) color = color.Substring(1); + if (!Regex.IsMatch(color, "^[0-9a-fA-F]{6}$")) throw Errors.InvalidColorError(color); + + var patch = new SystemPatch {Color = Partial.Present(color.ToLowerInvariant())}; + await _db.Execute(conn => _repo.UpdateSystem(conn, ctx.System.Id, patch)); + + await ctx.Reply(embed: new EmbedBuilder() + .Title($"{Emojis.Success} Member color changed.") + .Color(color.ToDiscordColor()) + .Thumbnail(new($"https://fakeimg.pl/256x256/{color}/?text=%20")) + .Build()); + } + } public async Task Tag(Context ctx) { diff --git a/PluralKit.Bot/Services/EmbedService.cs b/PluralKit.Bot/Services/EmbedService.cs index 5528f1cf..c0ec8265 100644 --- a/PluralKit.Bot/Services/EmbedService.cs +++ b/PluralKit.Bot/Services/EmbedService.cs @@ -53,11 +53,22 @@ namespace PluralKit.Bot { var memberCount = cctx.MatchPrivateFlag(ctx) ? await _repo.GetSystemMemberCount(conn, system.Id, PrivacyLevel.Public) : await _repo.GetSystemMemberCount(conn, system.Id); + uint color; + try + { + color = system.Color?.ToDiscordColor() ?? DiscordUtils.Gray; + } + catch (ArgumentException) + { + // There's no API for system colors yet, but defaulting to a blank color in advance can't be a bad idea + color = DiscordUtils.Gray; + } + var eb = new EmbedBuilder() .Title(system.Name) .Thumbnail(new(system.AvatarUrl)) .Footer(new($"System ID: {system.Hid} | Created on {system.Created.FormatZoned(system)}")) - .Color(DiscordUtils.Gray); + .Color(color); var latestSwitch = await _repo.GetLatestSwitch(conn, system.Id); if (latestSwitch != null && system.FrontPrivacy.CanAccess(ctx)) @@ -187,8 +198,20 @@ namespace PluralKit.Bot { if (system.Name != null) nameField = $"{nameField} ({system.Name})"; + uint color; + try + { + color = target.Color?.ToDiscordColor() ?? DiscordUtils.Gray; + } + catch (ArgumentException) + { + // There's no API for group colors yet, but defaulting to a blank color regardless + color = DiscordUtils.Gray; + } + var eb = new EmbedBuilder() .Author(new(nameField, IconUrl: DiscordUtils.WorkaroundForUrlBug(target.IconFor(pctx)))) + .Color(color) .Footer(new($"System ID: {system.Hid} | Group ID: {target.Hid} | Created on {target.Created.FormatZoned(system)}")); if (target.DisplayName != null) diff --git a/PluralKit.Core/Database/Database.cs b/PluralKit.Core/Database/Database.cs index 72a8591e..043b9e68 100644 --- a/PluralKit.Core/Database/Database.cs +++ b/PluralKit.Core/Database/Database.cs @@ -19,7 +19,7 @@ namespace PluralKit.Core internal class Database: IDatabase { private const string RootPath = "PluralKit.Core.Database"; // "resource path" root for SQL files - private const int TargetSchemaVersion = 12; + private const int TargetSchemaVersion = 13; private readonly CoreConfig _config; private readonly ILogger _logger; diff --git a/PluralKit.Core/Database/Migrations/13.sql b/PluralKit.Core/Database/Migrations/13.sql new file mode 100644 index 00000000..0ada9d65 --- /dev/null +++ b/PluralKit.Core/Database/Migrations/13.sql @@ -0,0 +1,7 @@ +-- SCHEMA VERSION 13: 2021-03-28 -- +-- Add system and group colors -- + +alter table systems add column color char(6); +alter table groups add column color char(6); + +update info set schema_version = 13; \ No newline at end of file diff --git a/PluralKit.Core/Models/PKGroup.cs b/PluralKit.Core/Models/PKGroup.cs index 7a45e900..21bea358 100644 --- a/PluralKit.Core/Models/PKGroup.cs +++ b/PluralKit.Core/Models/PKGroup.cs @@ -13,6 +13,7 @@ namespace PluralKit.Core public string? DisplayName { get; private set; } public string? Description { get; private set; } public string? Icon { get; private set; } + public string? Color { get; private set; } public PrivacyLevel DescriptionPrivacy { get; private set; } public PrivacyLevel IconPrivacy { get; private set; } diff --git a/PluralKit.Core/Models/PKSystem.cs b/PluralKit.Core/Models/PKSystem.cs index 436f9cc9..88d42266 100644 --- a/PluralKit.Core/Models/PKSystem.cs +++ b/PluralKit.Core/Models/PKSystem.cs @@ -14,6 +14,7 @@ namespace PluralKit.Core { public string Description { get; } public string Tag { get; } public string AvatarUrl { get; } + public string Color { get; } public string Token { get; } public Instant Created { get; } public string UiTz { get; set; } diff --git a/PluralKit.Core/Models/Patch/GroupPatch.cs b/PluralKit.Core/Models/Patch/GroupPatch.cs index 2f154c90..ee624df8 100644 --- a/PluralKit.Core/Models/Patch/GroupPatch.cs +++ b/PluralKit.Core/Models/Patch/GroupPatch.cs @@ -7,6 +7,7 @@ namespace PluralKit.Core public Partial DisplayName { get; set; } public Partial Description { get; set; } public Partial Icon { get; set; } + public Partial Color { get; set; } public Partial DescriptionPrivacy { get; set; } public Partial IconPrivacy { get; set; } @@ -18,6 +19,7 @@ namespace PluralKit.Core .With("display_name", DisplayName) .With("description", Description) .With("icon", Icon) + .With("color", Color) .With("description_privacy", DescriptionPrivacy) .With("icon_privacy", IconPrivacy) .With("list_privacy", ListPrivacy) diff --git a/PluralKit.Core/Models/Patch/SystemPatch.cs b/PluralKit.Core/Models/Patch/SystemPatch.cs index 7c3a9551..0f787749 100644 --- a/PluralKit.Core/Models/Patch/SystemPatch.cs +++ b/PluralKit.Core/Models/Patch/SystemPatch.cs @@ -7,6 +7,7 @@ namespace PluralKit.Core public Partial Description { get; set; } public Partial Tag { get; set; } public Partial AvatarUrl { get; set; } + public Partial Color { get; set; } public Partial Token { get; set; } public Partial UiTz { get; set; } public Partial DescriptionPrivacy { get; set; } @@ -22,6 +23,7 @@ namespace PluralKit.Core .With("description", Description) .With("tag", Tag) .With("avatar_url", AvatarUrl) + .With("color", Color) .With("token", Token) .With("ui_tz", UiTz) .With("description_privacy", DescriptionPrivacy)