Merge pull request #295 from Spectralitree/morecolors
Add system and group colors
This commit is contained in:
commit
183f74e0ae
2
.gitignore
vendored
2
.gitignore
vendored
@ -17,4 +17,4 @@ pluralkit.*.conf
|
|||||||
*.DotSettings.user
|
*.DotSettings.user
|
||||||
|
|
||||||
# Generated
|
# Generated
|
||||||
logs/
|
logs/
|
||||||
|
@ -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 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 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 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 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 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");
|
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 <group> rename <new name>", "Renames a group");
|
public static Command GroupRename = new Command("group rename", "group <group> rename <new name>", "Renames a group");
|
||||||
public static Command GroupDisplayName = new Command("group displayname", "group <group> displayname [display name]", "Changes a group's display name");
|
public static Command GroupDisplayName = new Command("group displayname", "group <group> displayname [display name]", "Changes a group's display name");
|
||||||
public static Command GroupDesc = new Command("group description", "group <group> description [description]", "Changes a group's description");
|
public static Command GroupDesc = new Command("group description", "group <group> description [description]", "Changes a group's description");
|
||||||
|
public static Command GroupColor = new Command("group color", "group <group> color [color]", "Changes a group's color");
|
||||||
public static Command GroupAdd = new Command("group add", "group <group> add <member> [member 2] [member 3...]", "Adds one or more members to a group");
|
public static Command GroupAdd = new Command("group add", "group <group> add <member> [member 2] [member 3...]", "Adds one or more members to a group");
|
||||||
public static Command GroupRemove = new Command("group remove", "group <group> remove <member> [member 2] [member 3...]", "Removes one or more members from a group");
|
public static Command GroupRemove = new Command("group remove", "group <group> remove <member> [member 2] [member 3...]", "Removes one or more members from a group");
|
||||||
public static Command GroupPrivacy = new Command("group privacy", "group <group> privacy <description|icon|visibility|all> <public|private>", "Changes a group's privacy settings");
|
public static Command GroupPrivacy = new Command("group privacy", "group <group> privacy <description|icon|visibility|all> <public|private>", "Changes a group's privacy settings");
|
||||||
@ -88,7 +90,7 @@ namespace PluralKit.Bot
|
|||||||
public static Command PermCheck = new Command("permcheck", "permcheck <guild>", "Checks whether a server's permission setup is correct");
|
public static Command PermCheck = new Command("permcheck", "permcheck <guild>", "Checks whether a server's permission setup is correct");
|
||||||
|
|
||||||
public static Command[] SystemCommands = {
|
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
|
SystemList, SystemFronter, SystemFrontHistory, SystemFrontPercent, SystemPrivacy, SystemProxy
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -101,7 +103,7 @@ namespace PluralKit.Bot
|
|||||||
public static Command[] GroupCommands =
|
public static Command[] GroupCommands =
|
||||||
{
|
{
|
||||||
GroupInfo, GroupList, GroupNew, GroupAdd, GroupRemove, GroupMemberList, GroupRename, GroupDesc,
|
GroupInfo, GroupList, GroupNew, GroupAdd, GroupRemove, GroupMemberList, GroupRename, GroupDesc,
|
||||||
GroupIcon, GroupPrivacy, GroupDelete
|
GroupIcon, GroupColor, GroupPrivacy, GroupDelete
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Command[] GroupCommandsTargeted =
|
public static Command[] GroupCommandsTargeted =
|
||||||
@ -217,6 +219,8 @@ namespace PluralKit.Bot
|
|||||||
await ctx.Execute<SystemEdit>(SystemTag, m => m.Tag(ctx));
|
await ctx.Execute<SystemEdit>(SystemTag, m => m.Tag(ctx));
|
||||||
else if (ctx.Match("description", "desc", "bio"))
|
else if (ctx.Match("description", "desc", "bio"))
|
||||||
await ctx.Execute<SystemEdit>(SystemDesc, m => m.Description(ctx));
|
await ctx.Execute<SystemEdit>(SystemDesc, m => m.Description(ctx));
|
||||||
|
else if (ctx.Match("color", "colour"))
|
||||||
|
await ctx.Execute<SystemEdit>(SystemColor, m => m.Color(ctx));
|
||||||
else if (ctx.Match("avatar", "picture", "icon", "image", "pic", "pfp"))
|
else if (ctx.Match("avatar", "picture", "icon", "image", "pic", "pfp"))
|
||||||
await ctx.Execute<SystemEdit>(SystemAvatar, m => m.Avatar(ctx));
|
await ctx.Execute<SystemEdit>(SystemAvatar, m => m.Avatar(ctx));
|
||||||
else if (ctx.Match("delete", "remove", "destroy", "erase", "yeet"))
|
else if (ctx.Match("delete", "remove", "destroy", "erase", "yeet"))
|
||||||
@ -397,6 +401,8 @@ namespace PluralKit.Bot
|
|||||||
await ctx.Execute<Groups>(GroupDelete, g => g.DeleteGroup(ctx, target));
|
await ctx.Execute<Groups>(GroupDelete, g => g.DeleteGroup(ctx, target));
|
||||||
else if (ctx.Match("avatar", "picture", "icon", "image", "pic", "pfp"))
|
else if (ctx.Match("avatar", "picture", "icon", "image", "pic", "pfp"))
|
||||||
await ctx.Execute<Groups>(GroupIcon, g => g.GroupIcon(ctx, target));
|
await ctx.Execute<Groups>(GroupIcon, g => g.GroupIcon(ctx, target));
|
||||||
|
else if (ctx.Match("color", "colour"))
|
||||||
|
await ctx.Execute<Groups>(GroupColor, g => g.GroupColor(ctx, target));
|
||||||
else if (!ctx.HasNext())
|
else if (!ctx.HasNext())
|
||||||
await ctx.Execute<Groups>(GroupInfo, g => g.ShowGroupCard(ctx, target));
|
await ctx.Execute<Groups>(GroupInfo, g => g.ShowGroupCard(ctx, target));
|
||||||
else
|
else
|
||||||
|
@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Dapper;
|
using Dapper;
|
||||||
@ -224,6 +225,53 @@ namespace PluralKit.Bot
|
|||||||
else
|
else
|
||||||
await ShowIcon();
|
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<string>.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 <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<string>.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)
|
public async Task ListSystemGroups(Context ctx, PKSystem system)
|
||||||
{
|
{
|
||||||
@ -263,7 +311,7 @@ namespace PluralKit.Bot
|
|||||||
}
|
}
|
||||||
|
|
||||||
var title = system.Name != null ? $"Groups of {system.Name} (`{system.Hid}`)" : $"Groups of `{system.Hid}`";
|
var title = system.Name != null ? $"Groups of {system.Name} (`{system.Hid}`)" : $"Groups of `{system.Hid}`";
|
||||||
await ctx.Paginate(groups.ToAsyncEnumerable(), groups.Count, 25, title, Renderer);
|
await ctx.Paginate(groups.ToAsyncEnumerable(), groups.Count, 25, title, ctx.System.Color, Renderer);
|
||||||
|
|
||||||
Task Renderer(EmbedBuilder eb, IEnumerable<ListedGroup> page)
|
Task Renderer(EmbedBuilder eb, IEnumerable<ListedGroup> page)
|
||||||
{
|
{
|
||||||
@ -342,7 +390,7 @@ namespace PluralKit.Bot
|
|||||||
if (opts.Search != null)
|
if (opts.Search != null)
|
||||||
title.Append($" matching **{opts.Search}**");
|
title.Append($" matching **{opts.Search}**");
|
||||||
|
|
||||||
await ctx.RenderMemberList(ctx.LookupContextFor(target.System), _db, target.System, title.ToString(), opts);
|
await ctx.RenderMemberList(ctx.LookupContextFor(target.System), _db, target.System, title.ToString(), target.Color, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum AddRemoveOperation
|
public enum AddRemoveOperation
|
||||||
|
@ -78,7 +78,7 @@ namespace PluralKit.Bot
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task RenderMemberList(this Context ctx, LookupContext lookupCtx, IDatabase db, SystemId system, string embedTitle, MemberListOptions opts)
|
public static async Task RenderMemberList(this Context ctx, LookupContext lookupCtx, IDatabase db, SystemId system, string embedTitle, string color, MemberListOptions opts)
|
||||||
{
|
{
|
||||||
// We take an IDatabase instead of a IPKConnection so we don't keep the handle open for the entire runtime
|
// We take an IDatabase instead of a IPKConnection so we don't keep the handle open for the entire runtime
|
||||||
// We wanna release it as soon as the member list is actually *fetched*, instead of potentially minutes later (paginate timeout)
|
// We wanna release it as soon as the member list is actually *fetched*, instead of potentially minutes later (paginate timeout)
|
||||||
@ -87,7 +87,7 @@ namespace PluralKit.Bot
|
|||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var itemsPerPage = opts.Type == ListType.Short ? 25 : 5;
|
var itemsPerPage = opts.Type == ListType.Short ? 25 : 5;
|
||||||
await ctx.Paginate(members.ToAsyncEnumerable(), members.Count, itemsPerPage, embedTitle, Renderer);
|
await ctx.Paginate(members.ToAsyncEnumerable(), members.Count, itemsPerPage, embedTitle, color, Renderer);
|
||||||
|
|
||||||
// Base renderer, dispatches based on type
|
// Base renderer, dispatches based on type
|
||||||
Task Renderer(EmbedBuilder eb, IEnumerable<ListedMember> page)
|
Task Renderer(EmbedBuilder eb, IEnumerable<ListedMember> page)
|
||||||
|
@ -107,6 +107,7 @@ namespace PluralKit.Bot
|
|||||||
|
|
||||||
await ctx.Paginate(channels.ToAsyncEnumerable(), channels.Count, 25,
|
await ctx.Paginate(channels.ToAsyncEnumerable(), channels.Count, 25,
|
||||||
$"Blacklisted channels for {ctx.Guild.Name}",
|
$"Blacklisted channels for {ctx.Guild.Name}",
|
||||||
|
null,
|
||||||
(eb, l) =>
|
(eb, l) =>
|
||||||
{
|
{
|
||||||
string CategoryName(ulong? id) =>
|
string CategoryName(ulong? id) =>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Myriad.Builders;
|
using Myriad.Builders;
|
||||||
@ -91,6 +92,47 @@ namespace PluralKit.Bot
|
|||||||
await ctx.Reply($"{Emojis.Success} System description changed.");
|
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<string>.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 <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<string>.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)
|
public async Task Tag(Context ctx)
|
||||||
{
|
{
|
||||||
|
@ -69,6 +69,7 @@ namespace PluralKit.Bot
|
|||||||
totalSwitches,
|
totalSwitches,
|
||||||
10,
|
10,
|
||||||
embedTitle,
|
embedTitle,
|
||||||
|
system.Color,
|
||||||
async (builder, switches) =>
|
async (builder, switches) =>
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
@ -20,7 +20,7 @@ namespace PluralKit.Bot
|
|||||||
ctx.CheckSystemPrivacy(target, target.MemberListPrivacy);
|
ctx.CheckSystemPrivacy(target, target.MemberListPrivacy);
|
||||||
|
|
||||||
var opts = ctx.ParseMemberListOptions(ctx.LookupContextFor(target));
|
var opts = ctx.ParseMemberListOptions(ctx.LookupContextFor(target));
|
||||||
await ctx.RenderMemberList(ctx.LookupContextFor(target), _db, target.Id, GetEmbedTitle(target, opts), opts);
|
await ctx.RenderMemberList(ctx.LookupContextFor(target), _db, target.Id, GetEmbedTitle(target, opts), target.Color, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetEmbedTitle(PKSystem target, MemberListOptions opts)
|
private string GetEmbedTitle(PKSystem target, MemberListOptions opts)
|
||||||
|
@ -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);
|
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()
|
var eb = new EmbedBuilder()
|
||||||
.Title(system.Name)
|
.Title(system.Name)
|
||||||
.Thumbnail(new(system.AvatarUrl))
|
.Thumbnail(new(system.AvatarUrl))
|
||||||
.Footer(new($"System ID: {system.Hid} | Created on {system.Created.FormatZoned(system)}"))
|
.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);
|
var latestSwitch = await _repo.GetLatestSwitch(conn, system.Id);
|
||||||
if (latestSwitch != null && system.FrontPrivacy.CanAccess(ctx))
|
if (latestSwitch != null && system.FrontPrivacy.CanAccess(ctx))
|
||||||
@ -68,7 +79,10 @@ namespace PluralKit.Bot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (system.Tag != null)
|
if (system.Tag != null)
|
||||||
eb.Field(new("Tag", system.Tag.EscapeMarkdown()));
|
eb.Field(new("Tag", system.Tag.EscapeMarkdown(), true));
|
||||||
|
|
||||||
|
if (!system.Color.EmptyOrNull()) eb.Field(new("Color", $"#{system.Color}", true));
|
||||||
|
|
||||||
eb.Field(new("Linked accounts", string.Join("\n", users).Truncate(1000), true));
|
eb.Field(new("Linked accounts", string.Join("\n", users).Truncate(1000), true));
|
||||||
|
|
||||||
if (system.MemberListPrivacy.CanAccess(ctx))
|
if (system.MemberListPrivacy.CanAccess(ctx))
|
||||||
@ -187,20 +201,34 @@ namespace PluralKit.Bot {
|
|||||||
if (system.Name != null)
|
if (system.Name != null)
|
||||||
nameField = $"{nameField} ({system.Name})";
|
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()
|
var eb = new EmbedBuilder()
|
||||||
.Author(new(nameField, IconUrl: DiscordUtils.WorkaroundForUrlBug(target.IconFor(pctx))))
|
.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)}"));
|
.Footer(new($"System ID: {system.Hid} | Group ID: {target.Hid} | Created on {target.Created.FormatZoned(system)}"));
|
||||||
|
|
||||||
if (target.DisplayName != null)
|
if (target.DisplayName != null)
|
||||||
eb.Field(new("Display Name", target.DisplayName));
|
eb.Field(new("Display Name", target.DisplayName, true));
|
||||||
|
|
||||||
|
if (!target.Color.EmptyOrNull()) eb.Field(new("Color", $"#{target.Color}", true));
|
||||||
|
|
||||||
if (target.ListPrivacy.CanAccess(pctx))
|
if (target.ListPrivacy.CanAccess(pctx))
|
||||||
{
|
{
|
||||||
if (memberCount == 0 && pctx == LookupContext.ByOwner)
|
if (memberCount == 0 && pctx == LookupContext.ByOwner)
|
||||||
// Only suggest the add command if this is actually the owner lol
|
// Only suggest the add command if this is actually the owner lol
|
||||||
eb.Field(new("Members (0)", $"Add one with `pk;group {target.Reference()} add <member>`!", true));
|
eb.Field(new("Members (0)", $"Add one with `pk;group {target.Reference()} add <member>`!", false));
|
||||||
else
|
else
|
||||||
eb.Field(new($"Members ({memberCount})", $"(see `pk;group {target.Reference()} list`)", true));
|
eb.Field(new($"Members ({memberCount})", $"(see `pk;group {target.Reference()} list`)", false));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target.DescriptionFor(pctx) is { } desc)
|
if (target.DescriptionFor(pctx) is { } desc)
|
||||||
@ -299,7 +327,6 @@ namespace PluralKit.Bot {
|
|||||||
var eb = new EmbedBuilder()
|
var eb = new EmbedBuilder()
|
||||||
.Color(DiscordUtils.Gray)
|
.Color(DiscordUtils.Gray)
|
||||||
.Footer(new($"Since {breakdown.RangeStart.FormatZoned(tz)} ({actualPeriod.FormatDuration()} ago)"));
|
.Footer(new($"Since {breakdown.RangeStart.FormatZoned(tz)} ({actualPeriod.FormatDuration()} ago)"));
|
||||||
|
|
||||||
var maxEntriesToDisplay = 24; // max 25 fields allowed in embed - reserve 1 for "others"
|
var maxEntriesToDisplay = 24; // max 25 fields allowed in embed - reserve 1 for "others"
|
||||||
|
|
||||||
// We convert to a list of pairs so we can add the no-fronter value
|
// We convert to a list of pairs so we can add the no-fronter value
|
||||||
|
@ -96,7 +96,7 @@ namespace PluralKit.Bot {
|
|||||||
return string.Equals(msg.Content, expectedReply, StringComparison.InvariantCultureIgnoreCase);
|
return string.Equals(msg.Content, expectedReply, StringComparison.InvariantCultureIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task Paginate<T>(this Context ctx, IAsyncEnumerable<T> items, int totalCount, int itemsPerPage, string title, Func<EmbedBuilder, IEnumerable<T>, Task> renderer) {
|
public static async Task Paginate<T>(this Context ctx, IAsyncEnumerable<T> items, int totalCount, int itemsPerPage, string title, string color, Func<EmbedBuilder, IEnumerable<T>, Task> renderer) {
|
||||||
// TODO: make this generic enough we can use it in Choose<T> below
|
// TODO: make this generic enough we can use it in Choose<T> below
|
||||||
|
|
||||||
var buffer = new List<T>();
|
var buffer = new List<T>();
|
||||||
@ -111,6 +111,8 @@ namespace PluralKit.Bot {
|
|||||||
|
|
||||||
var eb = new EmbedBuilder();
|
var eb = new EmbedBuilder();
|
||||||
eb.Title(pageCount > 1 ? $"[{page+1}/{pageCount}] {title}" : title);
|
eb.Title(pageCount > 1 ? $"[{page+1}/{pageCount}] {title}" : title);
|
||||||
|
if (color != null)
|
||||||
|
eb.Color(color.ToDiscordColor());
|
||||||
await renderer(eb, buffer.Skip(page*itemsPerPage).Take(itemsPerPage));
|
await renderer(eb, buffer.Skip(page*itemsPerPage).Take(itemsPerPage));
|
||||||
return eb.Build();
|
return eb.Build();
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ namespace PluralKit.Core
|
|||||||
internal class Database: IDatabase
|
internal class Database: IDatabase
|
||||||
{
|
{
|
||||||
private const string RootPath = "PluralKit.Core.Database"; // "resource path" root for SQL files
|
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 CoreConfig _config;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
7
PluralKit.Core/Database/Migrations/13.sql
Normal file
7
PluralKit.Core/Database/Migrations/13.sql
Normal file
@ -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;
|
@ -13,6 +13,7 @@ namespace PluralKit.Core
|
|||||||
public string? DisplayName { get; private set; }
|
public string? DisplayName { get; private set; }
|
||||||
public string? Description { get; private set; }
|
public string? Description { get; private set; }
|
||||||
public string? Icon { get; private set; }
|
public string? Icon { get; private set; }
|
||||||
|
public string? Color { get; private set; }
|
||||||
|
|
||||||
public PrivacyLevel DescriptionPrivacy { get; private set; }
|
public PrivacyLevel DescriptionPrivacy { get; private set; }
|
||||||
public PrivacyLevel IconPrivacy { get; private set; }
|
public PrivacyLevel IconPrivacy { get; private set; }
|
||||||
|
@ -14,6 +14,7 @@ namespace PluralKit.Core {
|
|||||||
public string Description { get; }
|
public string Description { get; }
|
||||||
public string Tag { get; }
|
public string Tag { get; }
|
||||||
public string AvatarUrl { get; }
|
public string AvatarUrl { get; }
|
||||||
|
public string Color { get; }
|
||||||
public string Token { get; }
|
public string Token { get; }
|
||||||
public Instant Created { get; }
|
public Instant Created { get; }
|
||||||
public string UiTz { get; set; }
|
public string UiTz { get; set; }
|
||||||
|
@ -7,6 +7,7 @@ namespace PluralKit.Core
|
|||||||
public Partial<string?> DisplayName { get; set; }
|
public Partial<string?> DisplayName { get; set; }
|
||||||
public Partial<string?> Description { get; set; }
|
public Partial<string?> Description { get; set; }
|
||||||
public Partial<string?> Icon { get; set; }
|
public Partial<string?> Icon { get; set; }
|
||||||
|
public Partial<string?> Color { get; set; }
|
||||||
|
|
||||||
public Partial<PrivacyLevel> DescriptionPrivacy { get; set; }
|
public Partial<PrivacyLevel> DescriptionPrivacy { get; set; }
|
||||||
public Partial<PrivacyLevel> IconPrivacy { get; set; }
|
public Partial<PrivacyLevel> IconPrivacy { get; set; }
|
||||||
@ -18,6 +19,7 @@ namespace PluralKit.Core
|
|||||||
.With("display_name", DisplayName)
|
.With("display_name", DisplayName)
|
||||||
.With("description", Description)
|
.With("description", Description)
|
||||||
.With("icon", Icon)
|
.With("icon", Icon)
|
||||||
|
.With("color", Color)
|
||||||
.With("description_privacy", DescriptionPrivacy)
|
.With("description_privacy", DescriptionPrivacy)
|
||||||
.With("icon_privacy", IconPrivacy)
|
.With("icon_privacy", IconPrivacy)
|
||||||
.With("list_privacy", ListPrivacy)
|
.With("list_privacy", ListPrivacy)
|
||||||
|
@ -7,6 +7,7 @@ namespace PluralKit.Core
|
|||||||
public Partial<string?> Description { get; set; }
|
public Partial<string?> Description { get; set; }
|
||||||
public Partial<string?> Tag { get; set; }
|
public Partial<string?> Tag { get; set; }
|
||||||
public Partial<string?> AvatarUrl { get; set; }
|
public Partial<string?> AvatarUrl { get; set; }
|
||||||
|
public Partial<string?> Color { get; set; }
|
||||||
public Partial<string?> Token { get; set; }
|
public Partial<string?> Token { get; set; }
|
||||||
public Partial<string> UiTz { get; set; }
|
public Partial<string> UiTz { get; set; }
|
||||||
public Partial<PrivacyLevel> DescriptionPrivacy { get; set; }
|
public Partial<PrivacyLevel> DescriptionPrivacy { get; set; }
|
||||||
@ -22,6 +23,7 @@ namespace PluralKit.Core
|
|||||||
.With("description", Description)
|
.With("description", Description)
|
||||||
.With("tag", Tag)
|
.With("tag", Tag)
|
||||||
.With("avatar_url", AvatarUrl)
|
.With("avatar_url", AvatarUrl)
|
||||||
|
.With("color", Color)
|
||||||
.With("token", Token)
|
.With("token", Token)
|
||||||
.With("ui_tz", UiTz)
|
.With("ui_tz", UiTz)
|
||||||
.With("description_privacy", DescriptionPrivacy)
|
.With("description_privacy", DescriptionPrivacy)
|
||||||
|
Loading…
Reference in New Issue
Block a user