2022-05-07 21:15:41 +00:00
using System.Text ;
2021-03-28 10:02:41 +00:00
using System.Text.RegularExpressions ;
2020-02-01 12:03:02 +00:00
2020-12-24 13:52:44 +00:00
using Myriad.Builders ;
2022-05-07 21:15:41 +00:00
using Myriad.Rest.Exceptions ;
using Myriad.Rest.Types ;
using Myriad.Rest.Types.Requests ;
2021-11-27 02:10:56 +00:00
using Myriad.Types ;
2020-12-24 13:52:44 +00:00
2022-05-07 21:15:41 +00:00
using Newtonsoft.Json ;
2019-07-09 22:19:18 +00:00
using PluralKit.Core ;
2019-04-19 18:48:37 +00:00
2021-11-27 02:10:56 +00:00
namespace PluralKit.Bot ;
public class SystemEdit
2019-04-19 18:48:37 +00:00
{
2021-11-27 02:10:56 +00:00
private readonly HttpClient _client ;
2022-05-07 21:15:41 +00:00
private readonly DataFileService _dataFiles ;
private readonly PrivateChannelService _dmCache ;
2021-11-27 02:10:56 +00:00
2022-05-07 21:15:41 +00:00
public SystemEdit ( DataFileService dataFiles , HttpClient client , PrivateChannelService dmCache )
2021-11-27 02:10:56 +00:00
{
2022-05-07 21:15:41 +00:00
_dataFiles = dataFiles ;
2021-11-27 02:10:56 +00:00
_client = client ;
2022-05-07 21:15:41 +00:00
_dmCache = dmCache ;
2021-11-27 02:10:56 +00:00
}
2021-12-05 22:21:31 +00:00
public async Task Name ( Context ctx , PKSystem target )
2019-04-19 18:48:37 +00:00
{
2021-12-05 22:21:31 +00:00
var isOwnSystem = target . Id = = ctx . System ? . Id ;
2019-04-21 13:33:22 +00:00
2021-12-05 22:21:31 +00:00
var noNameSetMessage = $"{(isOwnSystem ? " Your " : " This ")} system does not have a name set." ;
if ( isOwnSystem )
noNameSetMessage + = " Type `pk;system name <name>` to set one." ;
2021-11-27 02:10:56 +00:00
if ( ctx . MatchRaw ( ) )
2019-10-05 05:41:00 +00:00
{
2021-12-05 22:21:31 +00:00
if ( target . Name ! = null )
await ctx . Reply ( $"```\n{target.Name}\n```" ) ;
2021-11-27 02:10:56 +00:00
else
await ctx . Reply ( noNameSetMessage ) ;
return ;
2019-04-21 13:33:22 +00:00
}
2021-11-27 02:10:56 +00:00
if ( ! ctx . HasNext ( false ) )
2019-10-05 05:41:00 +00:00
{
2021-12-05 22:21:31 +00:00
if ( target . Name ! = null )
2021-11-27 02:10:56 +00:00
await ctx . Reply (
2021-12-05 22:21:31 +00:00
$"{(isOwnSystem ? " Your " : " This ")} system's name is currently **{target.Name}**."
+ ( isOwnSystem ? " Type `pk;system name -clear` to clear it." : "" ) ) ;
2021-11-27 02:10:56 +00:00
else
await ctx . Reply ( noNameSetMessage ) ;
return ;
}
2021-08-27 15:03:47 +00:00
2021-12-05 22:21:31 +00:00
ctx . CheckSystem ( ) . CheckOwnSystem ( target ) ;
2021-11-27 02:10:56 +00:00
if ( await ctx . MatchClear ( "your system's name" ) )
{
2022-01-22 08:05:01 +00:00
await ctx . Repository . UpdateSystem ( target . Id , new SystemPatch { Name = null } ) ;
2021-08-27 15:03:47 +00:00
2021-11-27 02:10:56 +00:00
await ctx . Reply ( $"{Emojis.Success} System name cleared." ) ;
}
else
{
var newSystemName = ctx . RemainderOrNull ( false ) . NormalizeLineEndSpacing ( ) ;
2021-08-27 23:20:14 +00:00
2021-11-27 02:10:56 +00:00
if ( newSystemName . Length > Limits . MaxSystemNameLength )
throw Errors . StringTooLongError ( "System name" , newSystemName . Length , Limits . MaxSystemNameLength ) ;
2021-08-27 23:20:14 +00:00
2022-01-22 08:05:01 +00:00
await ctx . Repository . UpdateSystem ( target . Id , new SystemPatch { Name = newSystemName } ) ;
2021-08-27 15:03:47 +00:00
2021-11-27 02:10:56 +00:00
await ctx . Reply ( $"{Emojis.Success} System name changed." ) ;
2019-04-19 18:48:37 +00:00
}
2021-11-27 02:10:56 +00:00
}
2021-08-27 15:03:47 +00:00
2021-12-05 22:21:31 +00:00
public async Task Description ( Context ctx , PKSystem target )
2021-11-27 02:10:56 +00:00
{
2021-12-24 03:50:16 +00:00
ctx . CheckSystemPrivacy ( target . Id , target . DescriptionPrivacy ) ;
2021-12-05 22:21:31 +00:00
var isOwnSystem = target . Id = = ctx . System ? . Id ;
var noDescriptionSetMessage = "This system does not have a description set." ;
if ( isOwnSystem )
noDescriptionSetMessage + = " To set one, type `pk;s description <description>`." ;
2021-08-27 15:03:47 +00:00
2021-11-27 02:10:56 +00:00
if ( ctx . MatchRaw ( ) )
{
2021-12-05 22:21:31 +00:00
if ( target . Description = = null )
2021-11-27 02:10:56 +00:00
await ctx . Reply ( noDescriptionSetMessage ) ;
else
2021-12-24 04:02:21 +00:00
await ctx . Reply ( $"```\n{target.Description}\n```" ) ;
2021-11-27 02:10:56 +00:00
return ;
}
2021-08-27 23:20:14 +00:00
2021-11-27 02:10:56 +00:00
if ( ! ctx . HasNext ( false ) )
{
2021-12-05 22:21:31 +00:00
if ( target . Description = = null )
2021-11-27 02:10:56 +00:00
await ctx . Reply ( noDescriptionSetMessage ) ;
2020-02-23 11:45:05 +00:00
else
2021-11-27 02:10:56 +00:00
await ctx . Reply ( embed : new EmbedBuilder ( )
. Title ( "System description" )
2021-12-05 22:21:31 +00:00
. Description ( target . Description )
2021-11-27 02:10:56 +00:00
. Footer ( new Embed . EmbedFooter (
2021-12-05 22:21:31 +00:00
"To print the description with formatting, type `pk;s description -raw`."
+ ( isOwnSystem ? "To clear it, type `pk;s description -clear`. To change it, type `pk;s description <new description>`." : "" ) ) )
2021-11-27 02:10:56 +00:00
. Build ( ) ) ;
return ;
}
2021-08-27 15:03:47 +00:00
2021-12-05 22:21:31 +00:00
ctx . CheckSystem ( ) . CheckOwnSystem ( target ) ;
2021-11-27 02:10:56 +00:00
if ( await ctx . MatchClear ( "your system's description" ) )
{
2022-01-22 08:05:01 +00:00
await ctx . Repository . UpdateSystem ( target . Id , new SystemPatch { Description = null } ) ;
2021-08-27 15:03:47 +00:00
2021-11-27 02:10:56 +00:00
await ctx . Reply ( $"{Emojis.Success} System description cleared." ) ;
2019-04-19 18:48:37 +00:00
}
2021-11-27 02:10:56 +00:00
else
2021-08-27 15:03:47 +00:00
{
2021-11-27 02:10:56 +00:00
var newDescription = ctx . RemainderOrNull ( false ) . NormalizeLineEndSpacing ( ) ;
if ( newDescription . Length > Limits . MaxDescriptionLength )
throw Errors . StringTooLongError ( "Description" , newDescription . Length , Limits . MaxDescriptionLength ) ;
2021-03-28 10:02:41 +00:00
2022-01-22 08:05:01 +00:00
await ctx . Repository . UpdateSystem ( target . Id , new SystemPatch { Description = newDescription } ) ;
2021-03-28 10:02:41 +00:00
2021-11-27 02:10:56 +00:00
await ctx . Reply ( $"{Emojis.Success} System description changed." ) ;
}
}
2021-03-28 10:02:41 +00:00
2021-12-05 22:21:31 +00:00
public async Task Color ( Context ctx , PKSystem target )
2021-11-27 02:10:56 +00:00
{
2021-12-05 22:21:31 +00:00
var isOwnSystem = ctx . System ? . Id = = target . Id ;
2021-03-28 10:02:41 +00:00
2022-05-02 19:54:49 +00:00
if ( ! isOwnSystem | | ! ctx . HasNext ( false ) )
2021-11-27 02:10:56 +00:00
{
2021-12-05 22:21:31 +00:00
if ( target . Color = = null )
2021-11-27 02:10:56 +00:00
await ctx . Reply (
2021-12-05 22:21:31 +00:00
"This system does not have a color set." + ( isOwnSystem ? " To set one, type `pk;system color <color>`." : "" ) ) ;
2021-11-27 02:10:56 +00:00
else
2021-03-28 10:02:41 +00:00
await ctx . Reply ( embed : new EmbedBuilder ( )
2021-11-27 02:10:56 +00:00
. Title ( "System color" )
2021-12-05 22:21:31 +00:00
. Color ( target . Color . ToDiscordColor ( ) )
2021-12-24 04:02:21 +00:00
. Thumbnail ( new Embed . EmbedThumbnail ( $"https://fakeimg.pl/256x256/{target.Color}/?text=%20" ) )
2021-11-27 02:10:56 +00:00
. Description (
2021-12-24 04:02:21 +00:00
$"This system's color is **#{target.Color}**." + ( isOwnSystem ? " To clear it, type `pk;s color -clear`." : "" ) )
2021-03-28 10:02:41 +00:00
. Build ( ) ) ;
2021-12-24 04:17:25 +00:00
return ;
2021-03-28 10:02:41 +00:00
}
2021-12-05 22:21:31 +00:00
ctx . CheckSystem ( ) . CheckOwnSystem ( target ) ;
if ( await ctx . MatchClear ( ) )
{
2022-01-22 08:05:01 +00:00
await ctx . Repository . UpdateSystem ( target . Id , new SystemPatch { Color = Partial < string > . Null ( ) } ) ;
2021-12-05 22:21:31 +00:00
await ctx . Reply ( $"{Emojis.Success} System color cleared." ) ;
}
2021-11-27 02:10:56 +00:00
else
2019-10-05 05:41:00 +00:00
{
2021-11-27 02:10:56 +00:00
var color = ctx . RemainderOrNull ( ) ;
2021-08-27 23:20:14 +00:00
2021-11-27 02:10:56 +00:00
if ( color . StartsWith ( "#" ) ) color = color . Substring ( 1 ) ;
if ( ! Regex . IsMatch ( color , "^[0-9a-fA-F]{6}$" ) ) throw Errors . InvalidColorError ( color ) ;
2019-04-19 18:48:37 +00:00
2022-01-22 08:05:01 +00:00
await ctx . Repository . UpdateSystem ( target . Id ,
2021-11-27 02:10:56 +00:00
new SystemPatch { Color = Partial < string > . Present ( color . ToLowerInvariant ( ) ) } ) ;
2021-08-27 23:20:14 +00:00
2021-11-27 02:10:56 +00:00
await ctx . Reply ( embed : new EmbedBuilder ( )
. Title ( $"{Emojis.Success} System color changed." )
. Color ( color . ToDiscordColor ( ) )
. Thumbnail ( new Embed . EmbedThumbnail ( $"https://fakeimg.pl/256x256/{color}/?text=%20" ) )
. Build ( ) ) ;
}
}
2021-08-27 15:03:47 +00:00
2021-12-05 22:21:31 +00:00
public async Task Tag ( Context ctx , PKSystem target )
2021-11-27 02:10:56 +00:00
{
2021-12-05 22:21:31 +00:00
var isOwnSystem = ctx . System ? . Id = = target . Id ;
2021-08-27 15:03:47 +00:00
2021-12-05 22:21:31 +00:00
var noTagSetMessage = isOwnSystem
? "You currently have no system tag set. To set one, type `pk;s tag <tag>`."
: "This system currently has no system tag set." ;
2021-08-27 15:03:47 +00:00
2021-11-27 02:10:56 +00:00
if ( ctx . MatchRaw ( ) )
{
2021-12-05 22:21:31 +00:00
if ( target . Tag = = null )
2021-11-27 02:10:56 +00:00
await ctx . Reply ( noTagSetMessage ) ;
else
2021-12-05 22:21:31 +00:00
await ctx . Reply ( $"```\n{target.Tag}\n```" ) ;
2021-11-27 02:10:56 +00:00
return ;
2019-04-19 18:48:37 +00:00
}
2021-08-02 21:22:06 +00:00
2021-11-27 02:10:56 +00:00
if ( ! ctx . HasNext ( false ) )
2021-08-02 21:22:06 +00:00
{
2021-12-05 22:21:31 +00:00
if ( target . Tag = = null )
2021-11-27 02:10:56 +00:00
await ctx . Reply ( noTagSetMessage ) ;
else
2021-12-24 04:02:21 +00:00
await ctx . Reply ( $"{(isOwnSystem ? " Your " : " This system ' s ")} current system tag is {target.Tag.AsCode()}."
2021-12-05 22:21:31 +00:00
+ ( isOwnSystem ? "To change it, type `pk;s tag <tag>`. To clear it, type `pk;s tag -clear`." : "" ) ) ;
2021-11-27 02:10:56 +00:00
return ;
}
2021-09-30 01:51:38 +00:00
2021-12-05 22:21:31 +00:00
ctx . CheckSystem ( ) . CheckOwnSystem ( target ) ;
2021-11-27 02:10:56 +00:00
if ( await ctx . MatchClear ( "your system's tag" ) )
{
2022-01-22 08:05:01 +00:00
await ctx . Repository . UpdateSystem ( target . Id , new SystemPatch { Tag = null } ) ;
2021-08-02 21:22:06 +00:00
2021-11-27 02:10:56 +00:00
await ctx . Reply ( $"{Emojis.Success} System tag cleared." ) ;
}
else
{
var newTag = ctx . RemainderOrNull ( false ) . NormalizeLineEndSpacing ( ) ;
if ( newTag ! = null )
if ( newTag . Length > Limits . MaxSystemTagLength )
throw Errors . StringTooLongError ( "System tag" , newTag . Length , Limits . MaxSystemTagLength ) ;
2021-08-02 21:22:06 +00:00
2022-01-22 08:05:01 +00:00
await ctx . Repository . UpdateSystem ( target . Id , new SystemPatch { Tag = newTag } ) ;
2021-08-02 21:22:06 +00:00
2021-11-27 02:10:56 +00:00
await ctx . Reply (
$"{Emojis.Success} System tag changed. Member names will now end with {newTag.AsCode()} when proxied." ) ;
}
}
2021-08-02 21:22:06 +00:00
2021-12-05 22:21:31 +00:00
public async Task ServerTag ( Context ctx , PKSystem target )
2021-11-27 02:10:56 +00:00
{
2021-12-05 22:21:31 +00:00
ctx . CheckSystem ( ) . CheckOwnSystem ( target ) . CheckGuildContext ( ) ;
2021-08-02 21:22:06 +00:00
2021-11-27 02:10:56 +00:00
var setDisabledWarning =
$"{Emojis.Warn} Your system tag is currently **disabled** in this server. No tag will be applied when proxying.\nTo re-enable the system tag in the current server, type `pk;s servertag -enable`." ;
2021-08-02 21:22:06 +00:00
2022-01-22 08:05:01 +00:00
var settings = await ctx . Repository . GetSystemGuild ( ctx . Guild . Id , target . Id ) ;
2021-08-02 21:22:06 +00:00
2021-11-27 02:10:56 +00:00
async Task Show ( bool raw = false )
{
if ( settings . Tag ! = null )
2021-08-02 21:22:06 +00:00
{
2021-11-27 02:10:56 +00:00
if ( raw )
{
await ctx . Reply ( $"```{settings.Tag}```" ) ;
return ;
}
2021-08-02 21:22:06 +00:00
2021-11-27 02:10:56 +00:00
var msg = $"Your current system tag in '{ctx.Guild.Name}' is {settings.Tag.AsCode()}" ;
if ( ! settings . TagEnabled )
msg + = ", but it is currently **disabled**. To re-enable it, type `pk;s servertag -enable`." ;
else
msg + =
". To change it, type `pk;s servertag <tag>`. To clear it, type `pk;s servertag -clear`." ;
2021-08-02 21:22:06 +00:00
2021-11-27 02:10:56 +00:00
await ctx . Reply ( msg ) ;
return ;
2021-08-02 21:22:06 +00:00
}
2021-11-27 02:10:56 +00:00
if ( ! settings . TagEnabled )
await ctx . Reply (
2021-12-24 04:02:21 +00:00
$"Your global system tag is {target.Tag}, but it is **disabled** in this server. To re-enable it, type `pk;s servertag -enable`" ) ;
2021-11-27 02:10:56 +00:00
else
await ctx . Reply (
$"You currently have no system tag specific to the server '{ctx.Guild.Name}'. To set one, type `pk;s servertag <tag>`. To disable the system tag in the current server, type `pk;s servertag -disable`." ) ;
}
2021-08-02 21:22:06 +00:00
2021-11-27 02:10:56 +00:00
async Task Set ( )
{
var newTag = ctx . RemainderOrNull ( false ) ;
if ( newTag ! = null & & newTag . Length > Limits . MaxSystemTagLength )
throw Errors . StringTooLongError ( "System server tag" , newTag . Length , Limits . MaxSystemTagLength ) ;
2021-08-02 21:22:06 +00:00
2022-01-22 08:05:01 +00:00
await ctx . Repository . UpdateSystemGuild ( target . Id , ctx . Guild . Id , new SystemGuildPatch { Tag = newTag } ) ;
2021-08-02 21:22:06 +00:00
2021-11-27 02:10:56 +00:00
await ctx . Reply (
$"{Emojis.Success} System server tag changed. Member names will now end with {newTag.AsCode()} when proxied in the current server '{ctx.Guild.Name}'." ) ;
2021-08-02 21:22:06 +00:00
2021-11-27 02:10:56 +00:00
if ( ! ctx . MessageContext . TagEnabled )
await ctx . Reply ( setDisabledWarning ) ;
}
2021-08-27 15:03:47 +00:00
2021-11-27 02:10:56 +00:00
async Task Clear ( )
{
2022-01-22 08:05:01 +00:00
await ctx . Repository . UpdateSystemGuild ( target . Id , ctx . Guild . Id , new SystemGuildPatch { Tag = null } ) ;
2021-08-02 21:22:06 +00:00
2021-11-27 02:10:56 +00:00
await ctx . Reply (
$"{Emojis.Success} System server tag cleared. Member names will now end with the global system tag, if there is one set." ) ;
if ( ! ctx . MessageContext . TagEnabled )
await ctx . Reply ( setDisabledWarning ) ;
2021-08-02 21:22:06 +00:00
}
2021-08-27 15:03:47 +00:00
2021-11-27 02:10:56 +00:00
async Task EnableDisable ( bool newValue )
2019-07-19 12:21:16 +00:00
{
2022-01-22 08:05:01 +00:00
await ctx . Repository . UpdateSystemGuild ( target . Id , ctx . Guild . Id ,
2021-11-27 02:10:56 +00:00
new SystemGuildPatch { TagEnabled = newValue } ) ;
2020-07-07 21:41:51 +00:00
2021-11-27 02:10:56 +00:00
await ctx . Reply ( PrintEnableDisableResult ( newValue , newValue ! = ctx . MessageContext . TagEnabled ) ) ;
}
2020-07-07 21:41:51 +00:00
2021-11-27 02:10:56 +00:00
string PrintEnableDisableResult ( bool newValue , bool changedValue )
{
var opStr = newValue ? "enabled" : "disabled" ;
var str = "" ;
2021-08-27 15:03:47 +00:00
2021-11-27 02:10:56 +00:00
if ( ! changedValue )
str = $"{Emojis.Note} The system tag is already {opStr} in this server." ;
else
str = $"{Emojis.Success} System tag {opStr} in this server." ;
2020-07-07 21:41:51 +00:00
2021-11-27 02:10:56 +00:00
if ( newValue )
2019-12-28 11:47:31 +00:00
{
2021-11-27 02:10:56 +00:00
if ( ctx . MessageContext . TagEnabled )
2019-12-28 11:47:31 +00:00
{
2021-11-27 02:10:56 +00:00
if ( ctx . MessageContext . SystemGuildTag = = null )
str + =
" However, you do not have a system tag specific to this server. Messages will be proxied using your global system tag, if there is one set." ;
else
str + =
$" Your current system tag in '{ctx.Guild.Name}' is {ctx.MessageContext.SystemGuildTag.AsCode()}." ;
2019-12-28 11:47:31 +00:00
}
else
2021-11-27 02:10:56 +00:00
{
if ( ctx . MessageContext . SystemGuildTag ! = null )
str + =
$" Member names will now end with the server-specific tag {ctx.MessageContext.SystemGuildTag.AsCode()} when proxied in the current server '{ctx.Guild.Name}'." ;
else
str + =
" Member names will now end with the global system tag when proxied in the current server, if there is one set." ;
}
2019-12-28 11:47:31 +00:00
}
2019-10-05 05:41:00 +00:00
2021-11-27 02:10:56 +00:00
return str ;
}
2021-10-30 23:02:21 +00:00
2021-11-27 02:10:56 +00:00
if ( await ctx . MatchClear ( "your system's server tag" ) )
await Clear ( ) ;
else if ( ctx . Match ( "disable" ) | | ctx . MatchFlag ( "disable" ) )
await EnableDisable ( false ) ;
else if ( ctx . Match ( "enable" ) | | ctx . MatchFlag ( "enable" ) )
await EnableDisable ( true ) ;
else if ( ctx . MatchRaw ( ) )
await Show ( true ) ;
else if ( ! ctx . HasNext ( false ) )
await Show ( ) ;
else
await Set ( ) ;
}
2022-03-23 18:20:16 +00:00
public async Task Pronouns ( Context ctx , PKSystem target )
{
ctx . CheckSystemPrivacy ( target . Id , target . PronounPrivacy ) ;
var isOwnSystem = ctx . System . Id = = target . Id ;
var noPronounsSetMessage = "This system does not have pronouns set." ;
2022-03-30 06:36:39 +00:00
if ( isOwnSystem )
2022-03-23 18:20:16 +00:00
noPronounsSetMessage + = " To set some, type `pk;system pronouns <pronouns>`" ;
if ( ctx . MatchRaw ( ) )
{
if ( target . Pronouns = = null )
await ctx . Reply ( noPronounsSetMessage ) ;
else
await ctx . Reply ( $"```\n{target.Pronouns}\n```" ) ;
return ;
}
if ( ! ctx . HasNext ( false ) )
{
if ( target . Pronouns = = null )
await ctx . Reply ( noPronounsSetMessage ) ;
else
await ctx . Reply ( $"{(isOwnSystem ? " Your " : " This system ' s ")} current pronouns are **{target.Pronouns}**.\nTo print the pronouns with formatting, type `pk;system pronouns -raw`."
2022-03-30 06:36:39 +00:00
+ ( isOwnSystem ? " To clear them, type `pk;system pronouns -clear`."
: "" ) ) ;
2022-03-23 18:20:16 +00:00
return ;
}
ctx . CheckSystem ( ) . CheckOwnSystem ( target ) ;
if ( await ctx . MatchClear ( "your system's pronouns" ) )
{
await ctx . Repository . UpdateSystem ( target . Id , new SystemPatch { Pronouns = null } ) ;
await ctx . Reply ( $"{Emojis.Success} System pronouns cleared." ) ;
}
else
{
var newPronouns = ctx . RemainderOrNull ( false ) . NormalizeLineEndSpacing ( ) ;
if ( newPronouns ! = null )
if ( newPronouns . Length > Limits . MaxPronounsLength )
throw Errors . StringTooLongError ( "Pronouns" , newPronouns . Length , Limits . MaxPronounsLength ) ;
await ctx . Repository . UpdateSystem ( target . Id , new SystemPatch { Pronouns = newPronouns } ) ;
await ctx . Reply (
$"{Emojis.Success} System pronouns changed." ) ;
}
}
2021-12-24 04:02:21 +00:00
public async Task Avatar ( Context ctx , PKSystem target )
2021-11-27 02:10:56 +00:00
{
async Task ClearIcon ( )
{
2021-12-25 00:19:50 +00:00
ctx . CheckOwnSystem ( target ) ;
2022-01-22 08:05:01 +00:00
await ctx . Repository . UpdateSystem ( target . Id , new SystemPatch { AvatarUrl = null } ) ;
2021-11-27 02:10:56 +00:00
await ctx . Reply ( $"{Emojis.Success} System icon cleared." ) ;
2019-07-19 12:21:16 +00:00
}
2021-08-02 17:46:12 +00:00
2021-11-27 02:10:56 +00:00
async Task SetIcon ( ParsedImage img )
2021-08-02 17:46:12 +00:00
{
2021-12-25 00:28:46 +00:00
ctx . CheckOwnSystem ( target ) ;
2021-11-27 02:10:56 +00:00
await AvatarUtils . VerifyAvatarOrThrow ( _client , img . Url ) ;
2021-08-02 17:46:12 +00:00
2022-01-22 08:05:01 +00:00
await ctx . Repository . UpdateSystem ( target . Id , new SystemPatch { AvatarUrl = img . Url } ) ;
2021-08-02 17:46:12 +00:00
2021-11-27 02:10:56 +00:00
var msg = img . Source switch
2021-08-02 17:46:12 +00:00
{
2021-11-27 02:10:56 +00:00
AvatarSource . User = >
$"{Emojis.Success} System icon changed to {img.SourceUser?.Username}'s avatar!\n{Emojis.Warn} If {img.SourceUser?.Username} changes their avatar, the system icon will need to be re-set." ,
AvatarSource . Url = > $"{Emojis.Success} System icon changed to the image at the given URL." ,
AvatarSource . Attachment = >
$"{Emojis.Success} System icon changed to attached image.\n{Emojis.Warn} If you delete the message containing the attachment, the system icon will stop working." ,
_ = > throw new ArgumentOutOfRangeException ( )
} ;
2021-08-02 17:46:12 +00:00
2021-11-27 02:10:56 +00:00
// 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 ) ) ;
}
2021-08-02 17:46:12 +00:00
2021-11-27 02:10:56 +00:00
async Task ShowIcon ( )
{
2021-12-24 04:02:21 +00:00
if ( ( target . AvatarUrl ? . Trim ( ) ? ? "" ) . Length > 0 )
2021-08-02 17:46:12 +00:00
{
2021-11-27 02:10:56 +00:00
var eb = new EmbedBuilder ( )
. Title ( "System icon" )
2021-12-24 04:02:21 +00:00
. Image ( new Embed . EmbedImage ( target . AvatarUrl . TryGetCleanCdnUrl ( ) ) ) ;
if ( target . Id = = ctx . System ? . Id )
2021-11-27 02:10:56 +00:00
eb . Description ( "To clear, use `pk;system icon clear`." ) ;
await ctx . Reply ( embed : eb . Build ( ) ) ;
2021-08-02 17:46:12 +00:00
}
else
2021-11-27 02:10:56 +00:00
{
throw new PKSyntaxError (
"This system does not have an icon set. Set one by attaching an image to this command, or by passing an image URL or @mention." ) ;
}
2021-08-02 17:46:12 +00:00
}
2021-11-27 02:10:56 +00:00
if ( target ! = null & & target ? . Id ! = ctx . System ? . Id )
2021-08-27 15:03:47 +00:00
{
2021-11-27 02:10:56 +00:00
await ShowIcon ( ) ;
return ;
}
2019-07-15 21:50:32 +00:00
2021-11-27 02:10:56 +00:00
if ( await ctx . MatchClear ( "your system's icon" ) )
await ClearIcon ( ) ;
else if ( await ctx . MatchImage ( ) is { } img )
await SetIcon ( img ) ;
else
await ShowIcon ( ) ;
}
2019-07-15 21:50:32 +00:00
2021-12-05 22:21:31 +00:00
public async Task BannerImage ( Context ctx , PKSystem target )
2021-11-27 02:10:56 +00:00
{
2021-12-24 03:50:16 +00:00
ctx . CheckSystemPrivacy ( target . Id , target . DescriptionPrivacy ) ;
2021-12-05 22:21:31 +00:00
var isOwnSystem = target . Id = = ctx . System ? . Id ;
2021-12-24 03:49:15 +00:00
if ( ! ctx . HasNext ( ) & & ctx . Message . Attachments . Length = = 0 )
2021-12-05 22:21:31 +00:00
{
if ( ( target . BannerImage ? . Trim ( ) ? ? "" ) . Length > 0 )
{
var eb = new EmbedBuilder ( )
. Title ( "System banner image" )
. Image ( new Embed . EmbedImage ( target . BannerImage ) ) ;
if ( isOwnSystem )
eb . Description ( "To clear, use `pk;system banner clear`." ) ;
await ctx . Reply ( embed : eb . Build ( ) ) ;
}
else
{
2022-03-30 08:36:22 +00:00
throw new PKSyntaxError ( "This system does not have a banner image set."
+ ( isOwnSystem ? "Set one by attaching an image to this command, or by passing an image URL or @mention." : "" ) ) ;
2021-12-05 22:21:31 +00:00
}
2022-03-30 08:36:22 +00:00
2021-12-05 22:21:31 +00:00
return ;
}
ctx . CheckSystem ( ) . CheckOwnSystem ( target ) ;
2021-08-27 15:03:47 +00:00
2021-12-05 22:21:31 +00:00
if ( await ctx . MatchClear ( "your system's banner image" ) )
2021-11-27 02:10:56 +00:00
{
2022-01-22 08:05:01 +00:00
await ctx . Repository . UpdateSystem ( target . Id , new SystemPatch { BannerImage = null } ) ;
2021-11-27 02:10:56 +00:00
await ctx . Reply ( $"{Emojis.Success} System banner image cleared." ) ;
2019-07-15 21:50:32 +00:00
}
2021-08-27 15:03:47 +00:00
2021-12-05 22:21:31 +00:00
else if ( await ctx . MatchImage ( ) is { } img )
2019-12-22 13:15:56 +00:00
{
2021-11-27 02:10:56 +00:00
await AvatarUtils . VerifyAvatarOrThrow ( _client , img . Url , true ) ;
2021-04-06 04:25:13 +00:00
2022-01-22 08:05:01 +00:00
await ctx . Repository . UpdateSystem ( target . Id , new SystemPatch { BannerImage = img . Url } ) ;
2021-04-06 04:25:13 +00:00
2021-11-27 02:10:56 +00:00
var msg = img . Source switch
{
AvatarSource . Url = > $"{Emojis.Success} System banner image changed to the image at the given URL." ,
AvatarSource . Attachment = >
$"{Emojis.Success} System banner image changed to attached image.\n{Emojis.Warn} If you delete the message containing the attachment, the banner image will stop working." ,
AvatarSource . User = > throw new PKError ( "Cannot set a banner image to an user's avatar." ) ,
_ = > throw new ArgumentOutOfRangeException ( )
} ;
2021-04-06 04:25:13 +00:00
2021-11-27 02:10:56 +00:00
// 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 ) ) ;
}
}
2019-12-22 13:15:56 +00:00
2021-12-05 22:21:31 +00:00
public async Task Delete ( Context ctx , PKSystem target )
2021-11-27 02:10:56 +00:00
{
2021-12-05 22:21:31 +00:00
ctx . CheckSystem ( ) . CheckOwnSystem ( target ) ;
2021-11-27 02:10:56 +00:00
await ctx . Reply (
2022-05-07 21:27:12 +00:00
$"{Emojis.Warn} Are you sure you want to delete your system? If so, reply to this message with your system's ID (`{target.Hid}`).\n"
+ $"**Note: this action is permanent,** but you will get a copy of your system's data that can be re-imported into PluralKit at a later date sent to you in DMs."
+ " If you don't want this to happen, use `pk;s delete -no-export` instead." ) ;
2021-12-24 04:02:21 +00:00
if ( ! await ctx . ConfirmWithReply ( target . Hid ) )
2021-11-27 02:10:56 +00:00
throw new PKError (
2021-12-24 04:02:21 +00:00
$"System deletion cancelled. Note that you must reply with your system ID (`{target.Hid}`) *verbatim*." ) ;
2021-11-27 02:10:56 +00:00
2022-05-07 21:15:41 +00:00
// If the user confirms the deletion, export their system and send them the export file before actually
// deleting their system, unless they specifically tell us not to do an export.
var noExport = ctx . MatchFlag ( "ne" , "no-export" ) ;
if ( ! noExport )
{
var json = await ctx . BusyIndicator ( async ( ) = >
{
// Make the actual data file
var data = await _dataFiles . ExportSystem ( ctx . System ) ;
return JsonConvert . SerializeObject ( data , Formatting . None ) ;
} ) ;
var stream = new MemoryStream ( Encoding . UTF8 . GetBytes ( json ) ) ;
2021-11-27 02:10:56 +00:00
2022-05-07 21:15:41 +00:00
try
{
var dm = await _dmCache . GetOrCreateDmChannel ( ctx . Author . Id ) ;
var msg = await ctx . Rest . CreateMessage ( dm ,
new MessageRequest { Content = $"{Emojis.Success} System deleted. If you want to set up your PluralKit system again, you can import the file below with `pk;import`." } ,
new [ ] { new MultipartFile ( "system.json" , stream , null ) } ) ;
await ctx . Rest . CreateMessage ( dm , new MessageRequest { Content = $"<{msg.Attachments[0].Url}>" } ) ;
// If the original message wasn't posted in DMs, send a public reminder
if ( ctx . Channel . Type ! = Channel . ChannelType . Dm )
await ctx . Reply ( $"{Emojis.Success} System deleted. Check your DMs for a copy of your system's data!" ) ;
}
catch ( ForbiddenException )
{
// If user has DMs closed, tell 'em to open them
throw new PKError (
$"I couldn't send you a DM with your system's data before deleting your system. Either make sure your DMs are open, or use `pk;s delete -no-export` to delete your system without exporting first." ) ;
}
2022-05-07 21:27:12 +00:00
}
else
2022-05-07 21:15:41 +00:00
{
await ctx . Reply ( $"{Emojis.Success} System deleted." ) ;
}
// Now that we've sent the export data (or been told not to), we can safely delete the system
await ctx . Repository . DeleteSystem ( target . Id ) ;
2021-11-27 02:10:56 +00:00
}
public async Task SystemProxy ( Context ctx )
{
ctx . CheckSystem ( ) ;
var guild = await ctx . MatchGuild ( ) ? ? ctx . Guild ? ?
throw new PKError ( "You must run this command in a server or pass a server ID." ) ;
2022-01-22 08:05:01 +00:00
var gs = await ctx . Repository . GetSystemGuild ( guild . Id , ctx . System . Id ) ;
2021-11-27 02:10:56 +00:00
string serverText ;
if ( guild . Id = = ctx . Guild ? . Id )
serverText = $"this server ({guild.Name.EscapeMarkdown()})" ;
else
serverText = $"the server {guild.Name.EscapeMarkdown()}" ;
2022-01-21 05:00:54 +00:00
if ( ! ctx . HasNext ( ) )
2021-11-27 02:10:56 +00:00
{
if ( gs . ProxyEnabled )
await ctx . Reply (
$"Proxying in {serverText} is currently **enabled** for your system. To disable it, type `pk;system proxy off`." ) ;
2019-12-22 13:15:56 +00:00
else
2021-11-27 02:10:56 +00:00
await ctx . Reply (
$"Proxying in {serverText} is currently **disabled** for your system. To enable it, type `pk;system proxy on`." ) ;
return ;
2019-12-22 13:15:56 +00:00
}
2021-08-27 15:03:47 +00:00
2022-01-21 05:00:54 +00:00
var newValue = ctx . MatchToggle ( ) ;
2022-01-22 08:05:01 +00:00
await ctx . Repository . UpdateSystemGuild ( ctx . System . Id , guild . Id , new SystemGuildPatch { ProxyEnabled = newValue } ) ;
2021-11-27 02:10:56 +00:00
if ( newValue )
await ctx . Reply ( $"Message proxying in {serverText} is now **enabled** for your system." ) ;
else
await ctx . Reply ( $"Message proxying in {serverText} is now **disabled** for your system." ) ;
}
2021-12-05 22:21:31 +00:00
public async Task SystemPrivacy ( Context ctx , PKSystem target )
2021-11-27 02:10:56 +00:00
{
2021-12-05 22:21:31 +00:00
ctx . CheckSystem ( ) . CheckOwnSystem ( target ) ;
2021-11-27 02:10:56 +00:00
Task PrintEmbed ( )
{
var eb = new EmbedBuilder ( )
. Title ( "Current privacy settings for your system" )
2021-12-24 04:02:21 +00:00
. Field ( new Embed . Field ( "Description" , target . DescriptionPrivacy . Explanation ( ) ) )
2022-03-23 18:20:16 +00:00
. Field ( new Embed . Field ( "Pronouns" , target . PronounPrivacy . Explanation ( ) ) )
2021-12-24 04:02:21 +00:00
. Field ( new Embed . Field ( "Member list" , target . MemberListPrivacy . Explanation ( ) ) )
. Field ( new Embed . Field ( "Group list" , target . GroupListPrivacy . Explanation ( ) ) )
. Field ( new Embed . Field ( "Current fronter(s)" , target . FrontPrivacy . Explanation ( ) ) )
. Field ( new Embed . Field ( "Front/switch history" , target . FrontHistoryPrivacy . Explanation ( ) ) )
2021-11-27 02:10:56 +00:00
. Description (
"To edit privacy settings, use the command:\n`pk;system privacy <subject> <level>`\n\n- `subject` is one of `description`, `list`, `front`, `fronthistory`, `groups`, or `all` \n- `level` is either `public` or `private`." ) ;
return ctx . Reply ( embed : eb . Build ( ) ) ;
2019-06-13 18:33:17 +00:00
}
2021-11-27 02:10:56 +00:00
async Task SetLevel ( SystemPrivacySubject subject , PrivacyLevel level )
2020-01-11 15:49:20 +00:00
{
2022-01-22 08:05:01 +00:00
await ctx . Repository . UpdateSystem ( target . Id , new SystemPatch ( ) . WithPrivacy ( subject , level ) ) ;
2020-01-11 15:49:20 +00:00
2021-11-27 02:10:56 +00:00
var levelExplanation = level switch
2020-01-11 15:49:20 +00:00
{
2021-11-27 02:10:56 +00:00
PrivacyLevel . Public = > "be able to query" ,
PrivacyLevel . Private = > "*not* be able to query" ,
_ = > ""
} ;
2020-07-07 22:46:58 +00:00
2021-11-27 02:10:56 +00:00
var subjectStr = subject switch
2020-01-11 15:49:20 +00:00
{
2021-11-27 02:10:56 +00:00
SystemPrivacySubject . Description = > "description" ,
2022-03-23 18:20:16 +00:00
SystemPrivacySubject . Pronouns = > "pronouns" ,
2021-11-27 02:10:56 +00:00
SystemPrivacySubject . Front = > "front" ,
SystemPrivacySubject . FrontHistory = > "front history" ,
SystemPrivacySubject . MemberList = > "member list" ,
SystemPrivacySubject . GroupList = > "group list" ,
_ = > ""
} ;
2020-07-07 22:46:58 +00:00
2021-11-27 02:10:56 +00:00
var msg =
$"System {subjectStr} privacy has been set to **{level.LevelName()}**. Other accounts will now {levelExplanation} your system {subjectStr}." ;
await ctx . Reply ( $"{Emojis.Success} {msg}" ) ;
}
2020-01-11 15:49:20 +00:00
2021-11-27 02:10:56 +00:00
async Task SetAll ( PrivacyLevel level )
{
2022-01-22 08:05:01 +00:00
await ctx . Repository . UpdateSystem ( target . Id , new SystemPatch ( ) . WithAllPrivacy ( level ) ) ;
2020-01-11 15:49:20 +00:00
2021-11-27 02:10:56 +00:00
var msg = level switch
2020-01-11 15:49:20 +00:00
{
2021-11-27 02:10:56 +00:00
PrivacyLevel . Private = >
$"All system privacy settings have been set to **{level.LevelName()}**. Other accounts will now not be able to view your member list, group list, front history, or system description." ,
PrivacyLevel . Public = >
$"All system privacy settings have been set to **{level.LevelName()}**. Other accounts will now be able to view everything." ,
_ = > ""
} ;
2020-06-17 19:31:39 +00:00
2021-11-27 02:10:56 +00:00
await ctx . Reply ( $"{Emojis.Success} {msg}" ) ;
}
2020-07-07 22:46:58 +00:00
2021-11-27 02:10:56 +00:00
if ( ! ctx . HasNext ( ) )
await PrintEmbed ( ) ;
else if ( ctx . Match ( "all" ) )
await SetAll ( ctx . PopPrivacyLevel ( ) ) ;
else
await SetLevel ( ctx . PopSystemPrivacySubject ( ) , ctx . PopPrivacyLevel ( ) ) ;
}
2021-08-27 15:03:47 +00:00
}