mirror of
https://github.com/PluralKit/PluralKit.git
synced 2026-02-17 11:10:13 +00:00
feat: started adding system guild avatar and system guild name, they can be set and used but are not shown in system cards.
This commit is contained in:
parent
83af1f04a7
commit
ef5bcc8b49
10 changed files with 172 additions and 4 deletions
|
|
@ -5,12 +5,14 @@ public partial class CommandTree
|
|||
public static Command SystemInfo = new Command("system", "system [system]", "Looks up information about a 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 [system] rename [name]", "Renames your system");
|
||||
public static Command SystemServerName = new Command("system servername", "system [system] servername [name]", "Changes your system displayname for this server");
|
||||
public static Command SystemDesc = new Command("system description", "system [system] description [description]", "Changes your system's description");
|
||||
public static Command SystemColor = new Command("system color", "system [system] color [color]", "Changes your system's color");
|
||||
public static Command SystemTag = new Command("system tag", "system [system] tag [tag]", "Changes your system's tag");
|
||||
public static Command SystemPronouns = new Command("system pronouns", "system [system] pronouns [pronouns]", "Changes your system's pronouns");
|
||||
public static Command SystemServerTag = new Command("system servertag", "system [system] servertag [tag|enable|disable]", "Changes your system's tag in the current server");
|
||||
public static Command SystemAvatar = new Command("system icon", "system [system] icon [url|@mention]", "Changes your system's icon");
|
||||
public static Command SystemServerAvatar = new Command("system serveravatar", "system [system] serveravatar [tag]", "Changes your system's icon in the current server");
|
||||
public static Command SystemBannerImage = new Command("system banner", "system [system] banner [url]", "Set the system's banner image");
|
||||
public static Command SystemDelete = new Command("system delete", "system [system] delete", "Deletes your system");
|
||||
public static Command SystemProxy = new Command("system proxy", "system proxy [server id] [on|off]", "Enables or disables message proxying in a specific server");
|
||||
|
|
@ -107,7 +109,7 @@ public partial class CommandTree
|
|||
|
||||
public static Command[] SystemCommands =
|
||||
{
|
||||
SystemInfo, SystemNew, SystemRename, SystemTag, SystemDesc, SystemAvatar, SystemBannerImage, SystemColor,
|
||||
SystemInfo, SystemNew, SystemRename, SystemServerName, SystemTag, SystemDesc, SystemAvatar, SystemServerAvatar, SystemBannerImage, SystemColor,
|
||||
SystemDelete, SystemList, SystemFronter, SystemFrontHistory, SystemFrontPercent, SystemPrivacy, SystemProxy
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -220,6 +220,9 @@ public partial class CommandTree
|
|||
{
|
||||
if (ctx.Match("name", "rename", "changename", "rn"))
|
||||
await ctx.CheckSystem(target).Execute<SystemEdit>(SystemRename, m => m.Name(ctx, target));
|
||||
else if (ctx.Match("servername", "sn", "sname", "snick", "snickname", "servernick", "servernickname",
|
||||
"serverdisplayname", "guildname", "guildnick", "guildnickname", "serverdn"))
|
||||
await ctx.Execute<SystemEdit>(SystemServerName, m => m.ServerName(ctx, target));
|
||||
else if (ctx.Match("tag", "t"))
|
||||
await ctx.CheckSystem(target).Execute<SystemEdit>(SystemTag, m => m.Tag(ctx, target));
|
||||
else if (ctx.Match("servertag", "st", "stag", "deer"))
|
||||
|
|
@ -234,6 +237,9 @@ public partial class CommandTree
|
|||
await ctx.CheckSystem(target).Execute<SystemEdit>(SystemBannerImage, m => m.BannerImage(ctx, target));
|
||||
else if (ctx.Match("avatar", "picture", "icon", "image", "pic", "pfp"))
|
||||
await ctx.CheckSystem(target).Execute<SystemEdit>(SystemAvatar, m => m.Avatar(ctx, target));
|
||||
else if (ctx.Match("serveravatar", "sa", "servericon", "serverimage", "serverpfp", "serverpic", "savatar", "spic",
|
||||
"guildavatar", "guildpic", "guildicon", "sicon", "spfp"))
|
||||
await ctx.CheckSystem(target).Execute<SystemEdit>(SystemServerAvatar, m => m.ServerAvatar(ctx, target));
|
||||
else if (ctx.Match("list", "l", "members", "ls"))
|
||||
await ctx.CheckSystem(target).Execute<SystemList>(SystemList, m => m.MemberList(ctx, target));
|
||||
else if (ctx.Match("find", "search", "query", "fd", "s"))
|
||||
|
|
@ -319,7 +325,7 @@ public partial class CommandTree
|
|||
else
|
||||
await ctx.Execute<GroupMember>(MemberGroups, m => m.ListMemberGroups(ctx, target));
|
||||
else if (ctx.Match("serveravatar", "sa", "servericon", "serverimage", "serverpfp", "serverpic", "savatar", "spic",
|
||||
"guildavatar", "guildpic", "guildicon", "sicon"))
|
||||
"guildavatar", "guildpic", "guildicon", "sicon", "spfp"))
|
||||
await ctx.Execute<MemberAvatar>(MemberServerAvatar, m => m.ServerAvatar(ctx, target));
|
||||
else if (ctx.Match("displayname", "dn", "dname", "nick", "nickname", "dispname"))
|
||||
await ctx.Execute<MemberEdit>(MemberDisplayName, m => m.DisplayName(ctx, target));
|
||||
|
|
|
|||
|
|
@ -76,6 +76,58 @@ public class SystemEdit
|
|||
}
|
||||
}
|
||||
|
||||
public async Task ServerName(Context ctx, PKSystem target)
|
||||
{
|
||||
var isOwnSystem = target.Id == ctx.System?.Id;
|
||||
|
||||
var noNameSetMessage = $"{(isOwnSystem ? "Your" : "This")} system does not have a name specific to this server.";
|
||||
if (isOwnSystem)
|
||||
noNameSetMessage += " Type `pk;system servername <name>` to set one.";
|
||||
|
||||
var settings = await ctx.Repository.GetSystemGuild(ctx.Guild.Id, target.Id);
|
||||
|
||||
if (ctx.MatchRaw())
|
||||
{
|
||||
if (settings.DisplayName != null)
|
||||
await ctx.Reply($"```\n{settings.DisplayName}\n```");
|
||||
else
|
||||
await ctx.Reply(noNameSetMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ctx.HasNext(false))
|
||||
{
|
||||
if (settings.DisplayName != null)
|
||||
await ctx.Reply(
|
||||
$"{(isOwnSystem ? "Your" : "This")} system's name for this server is currently **{settings.DisplayName}**."
|
||||
+ (isOwnSystem ? " Type `pk;system servername -clear` to clear it." : "")
|
||||
+ $" Using {settings.DisplayName.Length}/{Limits.MaxSystemNameLength} characters.");
|
||||
else
|
||||
await ctx.Reply(noNameSetMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.CheckSystem().CheckOwnSystem(target);
|
||||
|
||||
if (ctx.MatchClear() && await ctx.ConfirmClear("your system's name for this server"))
|
||||
{
|
||||
await ctx.Repository.UpdateSystemGuild(target.Id, ctx.Guild.Id, new SystemGuildPatch { DisplayName = null });
|
||||
|
||||
await ctx.Reply($"{Emojis.Success} System name for this server cleared.");
|
||||
}
|
||||
else
|
||||
{
|
||||
var newSystemGuildName = ctx.RemainderOrNull(false).NormalizeLineEndSpacing();
|
||||
|
||||
if (newSystemGuildName.Length > Limits.MaxSystemNameLength)
|
||||
throw Errors.StringTooLongError("System name for this server", newSystemGuildName.Length, Limits.MaxSystemNameLength);
|
||||
|
||||
await ctx.Repository.UpdateSystemGuild(target.Id, ctx.Guild.Id, new SystemGuildPatch { DisplayName = newSystemGuildName });
|
||||
|
||||
await ctx.Reply($"{Emojis.Success} System name for this server changed (using {newSystemGuildName.Length}/{Limits.MaxSystemNameLength} characters).");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Description(Context ctx, PKSystem target)
|
||||
{
|
||||
ctx.CheckSystemPrivacy(target.Id, target.DescriptionPrivacy);
|
||||
|
|
@ -471,6 +523,78 @@ public class SystemEdit
|
|||
await ShowIcon();
|
||||
}
|
||||
|
||||
public async Task ServerAvatar(Context ctx, PKSystem target)
|
||||
{
|
||||
|
||||
async Task ClearIcon()
|
||||
{
|
||||
ctx.CheckOwnSystem(target);
|
||||
|
||||
await ctx.Repository.UpdateSystemGuild(target.Id, ctx.Guild.Id, new SystemGuildPatch { AvatarUrl = null });
|
||||
await ctx.Reply($"{Emojis.Success} System server avatar cleared.");
|
||||
}
|
||||
|
||||
async Task SetIcon(ParsedImage img)
|
||||
{
|
||||
ctx.CheckOwnSystem(target);
|
||||
|
||||
await AvatarUtils.VerifyAvatarOrThrow(_client, img.Url);
|
||||
|
||||
await ctx.Repository.UpdateSystemGuild(target.Id, ctx.Guild.Id, new SystemGuildPatch { AvatarUrl = img.Url });
|
||||
|
||||
var msg = img.Source switch
|
||||
{
|
||||
AvatarSource.User =>
|
||||
$"{Emojis.Success} System icon for this server changed to {img.SourceUser?.Username}'s avatar! It will now be used for anything that uses system avatar in this server.\n{Emojis.Warn} If {img.SourceUser?.Username} changes their avatar, the system icon for this server will need to be re-set.",
|
||||
AvatarSource.Url =>
|
||||
$"{Emojis.Success} System icon for this server changed to the image at the given URL. It will now be used for anything that uses system avatar in this server.",
|
||||
AvatarSource.Attachment =>
|
||||
$"{Emojis.Success} System icon for this server changed to attached image. It will now be used for anything that uses system avatar in this server.\n{Emojis.Warn} If you delete the message containing the attachment, the system icon for this server will stop working.",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
// The attachment's already right there, no need to preview it.
|
||||
var hasEmbed = img.Source != AvatarSource.Attachment;
|
||||
await (hasEmbed
|
||||
? ctx.Reply(msg, new EmbedBuilder().Image(new Embed.EmbedImage(img.Url)).Build())
|
||||
: ctx.Reply(msg));
|
||||
}
|
||||
|
||||
async Task ShowIcon()
|
||||
{
|
||||
|
||||
var settings = await ctx.Repository.GetSystemGuild(ctx.Guild.Id, target.Id);
|
||||
|
||||
if ((settings.AvatarUrl?.Trim() ?? "").Length > 0)
|
||||
{
|
||||
var eb = new EmbedBuilder()
|
||||
.Title("System server icon")
|
||||
.Image(new Embed.EmbedImage(settings.AvatarUrl.TryGetCleanCdnUrl()));
|
||||
if (target.Id == ctx.System?.Id)
|
||||
eb.Description("To clear, use `pk;system servericon clear`.");
|
||||
await ctx.Reply(embed: eb.Build());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new PKSyntaxError(
|
||||
"This system does not have a icon specific to this server. Set one by attaching an image to this command, or by passing an image URL or @mention.");
|
||||
}
|
||||
}
|
||||
|
||||
if (target != null && target?.Id != ctx.System?.Id)
|
||||
{
|
||||
await ShowIcon();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx.MatchClear() && await ctx.ConfirmClear("your system's icon for this server"))
|
||||
await ClearIcon();
|
||||
else if (await ctx.MatchImage() is { } img)
|
||||
await SetIcon(img);
|
||||
else
|
||||
await ShowIcon();
|
||||
}
|
||||
|
||||
public async Task BannerImage(Context ctx, PKSystem target)
|
||||
{
|
||||
ctx.CheckSystemPrivacy(target.Id, target.DescriptionPrivacy);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ public class MessageContext
|
|||
public string? SystemGuildTag { get; }
|
||||
public bool TagEnabled { get; }
|
||||
public string? SystemAvatar { get; }
|
||||
public string? SystemGuildAvatar { get; }
|
||||
public bool AllowAutoproxy { get; }
|
||||
public int? LatchTimeout { get; }
|
||||
public bool CaseSensitiveProxyTags { get; }
|
||||
|
|
|
|||
|
|
@ -42,5 +42,5 @@ public class ProxyMember
|
|||
return memberName;
|
||||
}
|
||||
|
||||
public string? ProxyAvatar(MessageContext ctx) => ServerAvatar ?? WebhookAvatar ?? Avatar ?? ctx.SystemAvatar;
|
||||
public string? ProxyAvatar(MessageContext ctx) => ServerAvatar ?? WebhookAvatar ?? Avatar ?? ctx.SystemGuildAvatar ?? ctx.SystemAvatar;
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ create function message_context(account_id bigint, guild_id bigint, channel_id b
|
|||
system_guild_tag text,
|
||||
tag_enabled bool,
|
||||
system_avatar text,
|
||||
system_guild_avatar text,
|
||||
allow_autoproxy bool,
|
||||
latch_timeout integer,
|
||||
case_sensitive_proxy_tags bool,
|
||||
|
|
@ -22,6 +23,7 @@ as $$
|
|||
-- CTEs to query "static" (accessible only through args) data
|
||||
with
|
||||
system as (select systems.*, system_config.latch_timeout, system_guild.tag as guild_tag, system_guild.tag_enabled as tag_enabled,
|
||||
system_guild.avatar_url as guild_avatar,
|
||||
allow_autoproxy as account_autoproxy, system_config.case_sensitive_proxy_tags, system_config.proxy_error_message_enabled from accounts
|
||||
left join systems on systems.id = accounts.system
|
||||
left join system_config on system_config.system = accounts.system
|
||||
|
|
@ -44,6 +46,7 @@ as $$
|
|||
system.guild_tag as system_guild_tag,
|
||||
coalesce(system.tag_enabled, true) as tag_enabled,
|
||||
system.avatar_url as system_avatar,
|
||||
system.guild_avatar as system_guild_avatar,
|
||||
system.account_autoproxy as allow_autoproxy,
|
||||
system.latch_timeout as latch_timeout,
|
||||
system.case_sensitive_proxy_tags as case_sensitive_proxy_tags,
|
||||
|
|
|
|||
7
PluralKit.Core/Database/Migrations/35.sql
Normal file
7
PluralKit.Core/Database/Migrations/35.sql
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
-- database version 35
|
||||
-- add guild avatar and guild name to system guild settings
|
||||
|
||||
alter table system_guild add column avatar_url text;
|
||||
alter table system_guild add column display_name text;
|
||||
|
||||
update info set schema_version = 35;
|
||||
|
|
@ -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 = 34;
|
||||
private const int TargetSchemaVersion = 36;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public DatabaseMigrator(ILogger logger)
|
||||
|
|
|
|||
|
|
@ -11,17 +11,26 @@ public class SystemGuildPatch: PatchObject
|
|||
public Partial<bool> ProxyEnabled { get; set; }
|
||||
public Partial<string?> Tag { get; set; }
|
||||
public Partial<bool?> TagEnabled { get; set; }
|
||||
public Partial<string?> AvatarUrl { get; set; } //TODO API
|
||||
public Partial<string?> DisplayName { get; set; }
|
||||
|
||||
public override Query Apply(Query q) => q.ApplyPatch(wrapper => wrapper
|
||||
.With("proxy_enabled", ProxyEnabled)
|
||||
.With("tag", Tag)
|
||||
.With("tag_enabled", TagEnabled)
|
||||
.With("avatar_url", AvatarUrl)
|
||||
.With("display_name", DisplayName)
|
||||
);
|
||||
|
||||
public new void AssertIsValid()
|
||||
{
|
||||
if (Tag.Value != null)
|
||||
AssertValid(Tag.Value, "tag", Limits.MaxSystemTagLength);
|
||||
if (AvatarUrl.Value != null)
|
||||
AssertValid(AvatarUrl.Value, "avatar_url", Limits.MaxUriLength,
|
||||
s => MiscUtils.TryMatchUri(s, out var avatarUri));
|
||||
if (DisplayName.Value != null)
|
||||
AssertValid(DisplayName.Value, "display_name", Limits.MaxMemberNameLength);
|
||||
}
|
||||
|
||||
#nullable disable
|
||||
|
|
@ -37,6 +46,12 @@ public class SystemGuildPatch: PatchObject
|
|||
|
||||
if (o.ContainsKey("tag_enabled") && o["tag_enabled"].Type != JTokenType.Null)
|
||||
patch.TagEnabled = o.Value<bool>("tag_enabled");
|
||||
|
||||
if (o.ContainsKey("avatar_url"))
|
||||
patch.AvatarUrl = o.Value<string>("avatar_url").NullIfEmpty();
|
||||
|
||||
if (o.ContainsKey("display_name"))
|
||||
patch.DisplayName = o.Value<string>("display_name").NullIfEmpty();
|
||||
|
||||
return patch;
|
||||
}
|
||||
|
|
@ -56,6 +71,12 @@ public class SystemGuildPatch: PatchObject
|
|||
if (TagEnabled.IsPresent)
|
||||
o.Add("tag_enabled", TagEnabled.Value);
|
||||
|
||||
if (AvatarUrl.IsPresent)
|
||||
o.Add("avatar_url", AvatarUrl.Value);
|
||||
|
||||
if (DisplayName.IsPresent)
|
||||
o.Add("display_name", DisplayName.Value);
|
||||
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,8 @@ public class SystemGuildSettings
|
|||
public bool ProxyEnabled { get; } = true;
|
||||
public string? Tag { get; }
|
||||
public bool TagEnabled { get; }
|
||||
public string? AvatarUrl { get; }
|
||||
public string? DisplayName { get; }
|
||||
}
|
||||
|
||||
public static class SystemGuildExt
|
||||
|
|
@ -20,6 +22,8 @@ public static class SystemGuildExt
|
|||
o.Add("proxying_enabled", settings.ProxyEnabled);
|
||||
o.Add("tag", settings.Tag);
|
||||
o.Add("tag_enabled", settings.TagEnabled);
|
||||
o.Add("avatar_url", settings.AvatarUrl);
|
||||
o.Add("display_name", settings.DisplayName);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue