feat: implement system serveravatar commands

This commit is contained in:
dusk 2025-04-04 04:06:51 +09:00
parent b62340cbb3
commit 6a840f768f
No known key found for this signature in database
3 changed files with 104 additions and 86 deletions

View file

@ -69,6 +69,19 @@ public partial class CommandTree
Commands.SystemShowAvatar(var param, var flags) => ctx.Execute<SystemEdit>(SystemAvatar, m => m.ShowAvatar(ctx, param.target, flags.GetReplyFormat())),
Commands.SystemClearAvatar(var param, var flags) => ctx.Execute<SystemEdit>(SystemAvatar, m => m.ClearAvatar(ctx, ctx.System, flags.yes)),
Commands.SystemChangeAvatar(var param, _) => ctx.Execute<SystemEdit>(SystemAvatar, m => m.ChangeAvatar(ctx, ctx.System, param.avatar)),
Commands.SystemShowServerAvatarSelf(_, var flags) => ((Func<Task>)(() =>
{
// we want to change avatar if an attached image is passed
// we can't have a separate parsed command for this since the parser can't be aware of any attachments
var attachedImage = ctx.ExtractImageFromAttachment();
if (attachedImage is { } image)
return ctx.Execute<SystemEdit>(SystemServerAvatar, m => m.ChangeServerAvatar(ctx, ctx.System, image));
// if no attachment show the avatar like intended
return ctx.Execute<SystemEdit>(SystemServerAvatar, m => m.ShowServerAvatar(ctx, ctx.System, flags.GetReplyFormat()));
}))(),
Commands.SystemShowServerAvatar(var param, var flags) => ctx.Execute<SystemEdit>(SystemServerAvatar, m => m.ShowServerAvatar(ctx, param.target, flags.GetReplyFormat())),
Commands.SystemClearServerAvatar(var param, var flags) => ctx.Execute<SystemEdit>(SystemServerAvatar, m => m.ClearServerAvatar(ctx, ctx.System, flags.yes)),
Commands.SystemChangeServerAvatar(var param, _) => ctx.Execute<SystemEdit>(SystemServerAvatar, m => m.ChangeServerAvatar(ctx, ctx.System, param.avatar)),
_ =>
// this should only ever occur when deving if commands are not implemented...
ctx.Reply(
@ -319,9 +332,6 @@ public partial class CommandTree
{
if (ctx.Match("banner", "splash", "cover"))
await ctx.CheckSystem(target).Execute<SystemEdit>(SystemBannerImage, m => m.BannerImage(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"))

View file

@ -620,96 +620,85 @@ public class SystemEdit
: ctx.Reply(msg));
}
public async Task ServerAvatar(Context ctx, PKSystem target)
public async Task ClearServerAvatar(Context ctx, PKSystem target, bool flagConfirmYes)
{
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);
img = await _avatarHosting.TryRehostImage(img, AvatarHostingService.RehostedImageType.Avatar, ctx.Author.Id, ctx.System);
await _avatarHosting.VerifyAvatarOrThrow(img.Url);
await ctx.Repository.UpdateSystemGuild(target.Id, ctx.Guild.Id, new SystemGuildPatch { AvatarUrl = img.CleanUrl ?? 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.HostedCdn => $"{Emojis.Success} System icon for this server changed to attached image.",
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 && img.Source != AvatarSource.HostedCdn;
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)
{
if (!target.AvatarPrivacy.CanAccess(ctx.DirectLookupContextFor(target.Id)))
throw new PKSyntaxError("This system does not have a icon specific to this server or it is private.");
switch (ctx.MatchFormat())
{
case ReplyFormat.Raw:
await ctx.Reply($"`{settings.AvatarUrl.TryGetCleanCdnUrl()}`");
break;
case ReplyFormat.Plaintext:
var ebP = new EmbedBuilder()
.Description($"Showing icon for system {target.NameFor(ctx)} (`{target.DisplayHid(ctx.Config)}`)");
await ctx.Reply(text: $"<{settings.AvatarUrl.TryGetCleanCdnUrl()}>", embed: ebP.Build());
break;
default:
var ebS = new EmbedBuilder()
.Title("System server icon")
.Image(new Embed.EmbedImage(settings.AvatarUrl.TryGetCleanCdnUrl()));
if (target.Id == ctx.System?.Id)
ebS.Description($"To clear, use `{ctx.DefaultPrefix}system servericon clear`.");
await ctx.Reply(embed: ebS.Build());
break;
}
}
else
{
var isOwner = target.Id == ctx.System?.Id;
throw new PKSyntaxError(
$"This system does not have a icon specific to this server{(isOwner ? "" : " or it is private")}."
+ (isOwner ? " Set one by attaching an image to this command, or by passing an image URL or @mention." : ""));
}
}
ctx.CheckGuildContext();
ctx.CheckSystem().CheckOwnSystem(target);
if (target != null && target?.Id != ctx.System?.Id)
if (await ctx.ConfirmClear("your system's icon for this server", flagConfirmYes))
{
await ShowIcon();
return;
await ctx.Repository.UpdateSystemGuild(target.Id, ctx.Guild.Id, new SystemGuildPatch { AvatarUrl = null });
await ctx.Reply($"{Emojis.Success} System server icon cleared.");
}
}
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);
public async Task ShowServerAvatar(Context ctx, PKSystem target, ReplyFormat format)
{
ctx.CheckGuildContext();
var isOwnSystem = target.Id == ctx.System?.Id;
var settings = await ctx.Repository.GetSystemGuild(ctx.Guild.Id, target.Id);
if ((settings.AvatarUrl?.Trim() ?? "").Length > 0)
{
if (!target.AvatarPrivacy.CanAccess(ctx.DirectLookupContextFor(target.Id)))
throw new PKSyntaxError("This system does not have a icon specific to this server or it is private.");
switch (format)
{
case ReplyFormat.Raw:
await ctx.Reply($"`{settings.AvatarUrl.TryGetCleanCdnUrl()}`");
break;
case ReplyFormat.Plaintext:
var ebP = new EmbedBuilder()
.Description($"Showing icon for system {target.NameFor(ctx)} (`{target.DisplayHid(ctx.Config)}`)");
await ctx.Reply(text: $"<{settings.AvatarUrl.TryGetCleanCdnUrl()}>", embed: ebP.Build());
break;
default:
var ebS = new EmbedBuilder()
.Title("System server icon")
.Image(new Embed.EmbedImage(settings.AvatarUrl.TryGetCleanCdnUrl()));
if (target.Id == ctx.System?.Id)
ebS.Description($"To clear, use `{ctx.DefaultPrefix}system servericon clear`.");
await ctx.Reply(embed: ebS.Build());
break;
}
}
else
await ShowIcon();
{
throw new PKSyntaxError(
$"This system does not have a icon specific to this server{(isOwnSystem ? "" : " or it is private")}."
+ (isOwnSystem ? " Set one by attaching an image to this command, or by passing an image URL or @mention." : ""));
}
}
public async Task ChangeServerAvatar(Context ctx, PKSystem target, ParsedImage img)
{
ctx.CheckGuildContext();
ctx.CheckSystem().CheckOwnSystem(target);
img = await _avatarHosting.TryRehostImage(img, AvatarHostingService.RehostedImageType.Avatar, ctx.Author.Id, ctx.System);
await _avatarHosting.VerifyAvatarOrThrow(img.Url);
await ctx.Repository.UpdateSystemGuild(target.Id, ctx.Guild.Id, new SystemGuildPatch { AvatarUrl = img.CleanUrl ?? 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.HostedCdn => $"{Emojis.Success} System icon for this server changed to attached image.",
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 && img.Source != AvatarSource.HostedCdn;
await (hasEmbed
? ctx.Reply(msg, new EmbedBuilder().Image(new Embed.EmbedImage(img.Url)).Build())
: ctx.Reply(msg));
}
public async Task BannerImage(Context ctx, PKSystem target)

View file

@ -158,6 +158,23 @@ pub fn edit() -> impl Iterator<Item = Command> {
]
.into_iter();
let system_server_avatar = tokens!(system_target, ("serveravatar", ["spfp"]));
let system_server_avatar_cmd = [command!(system_server_avatar => "system_show_server_avatar")
.help("Shows the system's server avatar")]
.into_iter();
let system_server_avatar_self = tokens!(system, ("serveravatar", ["spfp"]));
let system_server_avatar_self_cmd = [
command!(system_server_avatar_self => "system_show_server_avatar_self")
.help("Shows your system's server avatar"),
command!(system_server_avatar_self, ("clear", ["c"]) => "system_clear_server_avatar")
.flag(("yes", ["y"]))
.help("Clears your system's server avatar"),
command!(system_server_avatar_self, ("avatar", Avatar) => "system_change_server_avatar")
.help("Changes your system's server avatar"),
]
.into_iter();
system_new_cmd
.chain(system_name_self_cmd)
.chain(system_server_name_self_cmd)
@ -167,6 +184,7 @@ pub fn edit() -> impl Iterator<Item = Command> {
.chain(system_server_tag_self_cmd)
.chain(system_pronouns_self_cmd)
.chain(system_avatar_self_cmd)
.chain(system_server_avatar_self_cmd)
.chain(system_name_cmd)
.chain(system_server_name_cmd)
.chain(system_description_cmd)
@ -175,5 +193,6 @@ pub fn edit() -> impl Iterator<Item = Command> {
.chain(system_server_tag_cmd)
.chain(system_pronouns_cmd)
.chain(system_avatar_cmd)
.chain(system_server_avatar_cmd)
.chain(system_info_cmd)
}