2020-06-13 14:03:57 +00:00
#nullable enable
2020-12-24 13:52:44 +00:00
using Myriad.Builders ;
2021-11-27 02:10:56 +00:00
using Myriad.Types ;
2020-12-24 13:52:44 +00:00
2020-02-12 14:16:19 +00:00
using PluralKit.Core ;
2020-02-01 12:03:02 +00:00
2021-11-27 02:10:56 +00:00
namespace PluralKit.Bot ;
public class MemberAvatar
2020-02-01 12:03:02 +00:00
{
2021-11-27 02:10:56 +00:00
private readonly HttpClient _client ;
private readonly ModelRepository _repo ;
2021-11-27 03:02:58 +00:00
public MemberAvatar ( ModelRepository repo , HttpClient client )
2020-02-01 12:03:02 +00:00
{
2021-11-27 02:10:56 +00:00
_repo = repo ;
_client = client ;
}
2020-02-01 12:03:02 +00:00
2021-11-27 02:10:56 +00:00
private async Task AvatarClear ( AvatarLocation location , Context ctx , PKMember target , MemberGuildSettings ? mgs )
{
await UpdateAvatar ( location , ctx , target , null ) ;
if ( location = = AvatarLocation . Server )
2020-02-01 12:03:02 +00:00
{
2021-11-27 02:10:56 +00:00
if ( target . AvatarUrl ! = null )
await ctx . Reply (
$"{Emojis.Success} Member server avatar cleared. This member will now use the global avatar in this server (**{ctx.Guild.Name}**)." ) ;
else
await ctx . Reply ( $"{Emojis.Success} Member server avatar cleared. This member now has no avatar." ) ;
2020-02-01 12:03:02 +00:00
}
2021-11-27 02:10:56 +00:00
else
2020-02-01 12:03:02 +00:00
{
2021-11-27 02:10:56 +00:00
if ( mgs ? . AvatarUrl ! = null )
await ctx . Reply (
$"{Emojis.Success} Member avatar cleared. Note that this member has a server-specific avatar set here, type `pk;member {target.Reference()} serveravatar clear` if you wish to clear that too." ) ;
2020-06-13 14:03:57 +00:00
else
2021-11-27 02:10:56 +00:00
await ctx . Reply ( $"{Emojis.Success} Member avatar cleared." ) ;
2020-06-13 14:03:57 +00:00
}
2021-11-27 02:10:56 +00:00
}
2020-06-13 14:03:57 +00:00
2021-11-27 02:10:56 +00:00
private async Task AvatarShow ( AvatarLocation location , Context ctx , PKMember target ,
MemberGuildSettings ? guildData )
{
var currentValue = location = = AvatarLocation . Member ? target . AvatarUrl : guildData ? . AvatarUrl ;
var canAccess = location ! = AvatarLocation . Member | |
2021-12-06 05:32:54 +00:00
target . AvatarPrivacy . CanAccess ( ctx . LookupContextFor ( target . System ) ) ;
2021-11-27 02:10:56 +00:00
if ( string . IsNullOrEmpty ( currentValue ) | | ! canAccess )
2020-06-13 14:03:57 +00:00
{
2021-11-27 02:10:56 +00:00
if ( location = = AvatarLocation . Member )
2020-02-01 12:03:02 +00:00
{
2021-11-27 02:10:56 +00:00
if ( target . System = = ctx . System ? . Id )
throw new PKSyntaxError (
"This member does not have an avatar set. Set one by attaching an image to this command, or by passing an image URL or @mention." ) ;
throw new PKError ( "This member does not have an avatar set." ) ;
2020-02-01 12:03:02 +00:00
}
2021-08-27 15:03:47 +00:00
2021-11-27 02:10:56 +00:00
if ( location = = AvatarLocation . Server )
throw new PKError (
$"This member does not have a server avatar set. Type `pk;member {target.Reference()} avatar` to see their global avatar." ) ;
2020-06-13 14:03:57 +00:00
}
2021-11-27 02:10:56 +00:00
var field = location = = AvatarLocation . Server ? $"server avatar (for {ctx.Guild.Name})" : "avatar" ;
var cmd = location = = AvatarLocation . Server ? "serveravatar" : "avatar" ;
2021-08-27 15:03:47 +00:00
2021-11-27 02:10:56 +00:00
var eb = new EmbedBuilder ( )
. Title ( $"{target.NameFor(ctx)}'s {field}" )
. Image ( new Embed . EmbedImage ( currentValue ? . TryGetCleanCdnUrl ( ) ) ) ;
if ( target . System = = ctx . System ? . Id )
eb . Description ( $"To clear, use `pk;member {target.Reference()} {cmd} clear`." ) ;
await ctx . Reply ( embed : eb . Build ( ) ) ;
}
2020-02-12 16:42:12 +00:00
2021-11-27 02:10:56 +00:00
public async Task ServerAvatar ( Context ctx , PKMember target )
{
ctx . CheckGuildContext ( ) ;
var guildData = await _repo . GetMemberGuild ( ctx . Guild . Id , target . Id ) ;
await AvatarCommandTree ( AvatarLocation . Server , ctx , target , guildData ) ;
}
2020-02-12 16:42:12 +00:00
2021-11-27 02:10:56 +00:00
public async Task Avatar ( Context ctx , PKMember target )
{
var guildData = ctx . Guild ! = null
? await _repo . GetMemberGuild ( ctx . Guild . Id , target . Id )
: null ;
2020-07-07 21:41:51 +00:00
2021-11-27 02:10:56 +00:00
await AvatarCommandTree ( AvatarLocation . Member , ctx , target , guildData ) ;
}
2020-07-07 21:41:51 +00:00
2021-11-27 02:10:56 +00:00
private async Task AvatarCommandTree ( AvatarLocation location , Context ctx , PKMember target ,
MemberGuildSettings ? guildData )
{
// First, see if we need to *clear*
if ( await ctx . MatchClear ( location = = AvatarLocation . Server
? "this member's server avatar"
: "this member's avatar" ) )
{
2020-07-07 21:41:51 +00:00
ctx . CheckSystem ( ) . CheckOwnMember ( target ) ;
2021-11-27 02:10:56 +00:00
await AvatarClear ( location , ctx , target , guildData ) ;
return ;
2020-07-07 21:41:51 +00:00
}
2021-11-27 02:10:56 +00:00
// Then, parse an image from the command (from various sources...)
var avatarArg = await ctx . MatchImage ( ) ;
if ( avatarArg = = null )
2020-07-07 21:41:51 +00:00
{
2021-11-27 02:10:56 +00:00
// If we didn't get any, just show the current avatar
await AvatarShow ( location , ctx , target , guildData ) ;
return ;
}
2021-08-27 15:03:47 +00:00
2021-11-27 02:10:56 +00:00
ctx . CheckSystem ( ) . CheckOwnMember ( target ) ;
await AvatarUtils . VerifyAvatarOrThrow ( _client , avatarArg . Value . Url ) ;
await UpdateAvatar ( location , ctx , target , avatarArg . Value . Url ) ;
await PrintResponse ( location , ctx , target , avatarArg . Value , guildData ) ;
}
2020-07-07 21:41:51 +00:00
2021-11-27 02:10:56 +00:00
private Task PrintResponse ( AvatarLocation location , Context ctx , PKMember target , ParsedImage avatar ,
MemberGuildSettings ? targetGuildData )
{
var typeFrag = location switch
{
AvatarLocation . Server = > "server avatar" ,
AvatarLocation . Member = > "avatar" ,
_ = > throw new ArgumentOutOfRangeException ( nameof ( location ) )
} ;
2020-02-12 16:42:12 +00:00
2021-11-27 02:10:56 +00:00
var serverFrag = location switch
2020-06-29 13:20:28 +00:00
{
2021-11-27 02:10:56 +00:00
AvatarLocation . Server = >
$" This avatar will now be used when proxying in this server (**{ctx.Guild.Name}**)." ,
AvatarLocation . Member when targetGuildData ? . AvatarUrl ! = null = >
$"\n{Emojis.Note} Note that this member *also* has a server-specific avatar set in this server (**{ctx.Guild.Name}**), and thus changing the global avatar will have no effect here." ,
_ = > ""
} ;
var msg = avatar . Source switch
{
AvatarSource . User = >
$"{Emojis.Success} Member {typeFrag} changed to {avatar.SourceUser?.Username}'s avatar!{serverFrag}\n{Emojis.Warn} If {avatar.SourceUser?.Username} changes their avatar, the member's avatar will need to be re-set." ,
AvatarSource . Url = >
$"{Emojis.Success} Member {typeFrag} changed to the image at the given URL.{serverFrag}" ,
AvatarSource . Attachment = >
$"{Emojis.Success} Member {typeFrag} changed to attached image.{serverFrag}\n{Emojis.Warn} If you delete the message containing the attachment, the avatar will stop working." ,
_ = > throw new ArgumentOutOfRangeException ( )
} ;
// The attachment's already right there, no need to preview it.
var hasEmbed = avatar . Source ! = AvatarSource . Attachment ;
return hasEmbed
? ctx . Reply ( msg , new EmbedBuilder ( ) . Image ( new Embed . EmbedImage ( avatar . Url ) ) . Build ( ) )
: ctx . Reply ( msg ) ;
}
2020-02-12 16:42:12 +00:00
2021-11-27 02:10:56 +00:00
private Task UpdateAvatar ( AvatarLocation location , Context ctx , PKMember target , string? url )
{
switch ( location )
2020-06-13 14:03:57 +00:00
{
2021-11-27 02:10:56 +00:00
case AvatarLocation . Server :
return _repo . UpdateMemberGuild ( target . Id , ctx . Guild . Id , new MemberGuildPatch { AvatarUrl = url } ) ;
case AvatarLocation . Member :
return _repo . UpdateMember ( target . Id , new MemberPatch { AvatarUrl = url } ) ;
default :
throw new ArgumentOutOfRangeException ( $"Unknown avatar location {location}" ) ;
2020-02-12 16:42:12 +00:00
}
2020-02-01 12:03:02 +00:00
}
2021-11-27 02:10:56 +00:00
private enum AvatarLocation { Member , Server }
2020-02-01 12:03:02 +00:00
}