2020-02-12 14:16:19 +00:00
using System.Linq ;
2020-02-01 12:03:02 +00:00
using System.Threading.Tasks ;
2020-02-12 14:16:19 +00:00
using PluralKit.Core ;
2020-02-01 12:03:02 +00:00
2020-02-12 14:16:19 +00:00
namespace PluralKit.Bot
2020-02-01 12:03:02 +00:00
{
public class MemberProxy
{
private IDataStore _data ;
2020-02-01 13:40:57 +00:00
public MemberProxy ( IDataStore data )
2020-02-01 12:03:02 +00:00
{
_data = data ;
}
public async Task Proxy ( Context ctx , PKMember target )
{
if ( ctx . System = = null ) throw Errors . NoSystemError ;
if ( target . System ! = ctx . System . Id ) throw Errors . NotOwnMemberError ;
ProxyTag ParseProxyTags ( string exampleProxy )
{
// // Make sure there's one and only one instance of "text" in the example proxy given
var prefixAndSuffix = exampleProxy . Split ( "text" ) ;
if ( prefixAndSuffix . Length < 2 ) throw Errors . ProxyMustHaveText ;
if ( prefixAndSuffix . Length > 2 ) throw Errors . ProxyMultipleText ;
return new ProxyTag ( prefixAndSuffix [ 0 ] , prefixAndSuffix [ 1 ] ) ;
}
async Task < bool > WarnOnConflict ( ProxyTag newTag )
{
var conflicts = ( await _data . GetConflictingProxies ( ctx . System , newTag ) )
. Where ( m = > m . Id ! = target . Id )
. ToList ( ) ;
if ( conflicts . Count < = 0 ) return true ;
2020-06-18 15:08:36 +00:00
var conflictList = conflicts . Select ( m = > $"- **{m.NameFor(ctx)}**" ) ;
2020-02-01 12:03:02 +00:00
var msg = await ctx . Reply (
$"{Emojis.Warn} The following members have conflicting proxy tags:\n{string.Join('\n', conflictList)}\nDo you want to proceed anyway?" ) ;
return await ctx . PromptYesNo ( msg ) ;
}
2020-03-04 17:13:36 +00:00
// "Sub"command: clear flag
2020-03-04 23:07:42 +00:00
if ( ctx . Match ( "clear" , "purge" , "clean" , "removeall" ) | | ctx . MatchFlag ( "c" , "clear" ) )
2020-02-01 12:03:02 +00:00
{
// If we already have multiple tags, this would clear everything, so prompt that
if ( target . ProxyTags . Count > 1 )
{
var msg = await ctx . Reply (
$"{Emojis.Warn} You already have multiple proxy tags set: {target.ProxyTagsString()}\nDo you want to clear them all?" ) ;
if ( ! await ctx . PromptYesNo ( msg ) )
throw Errors . GenericCancelled ( ) ;
}
target . ProxyTags = new ProxyTag [ ] { } ;
await _data . SaveMember ( target ) ;
await ctx . Reply ( $"{Emojis.Success} Proxy tags cleared." ) ;
}
2020-03-04 17:13:36 +00:00
// "Sub"command: no arguments; will print proxy tags
else if ( ! ctx . HasNext ( skipFlags : false ) )
{
if ( target . ProxyTags . Count = = 0 )
await ctx . Reply ( "This member does not have any proxy tags." ) ;
else
{
var tags = string . Join ( "\n" , target . ProxyTags . Select ( t = > $"`{t.ProxyString}`" . SanitizeMentions ( ) ) ) ;
await ctx . Reply ( $"This member's proxy tags are:\n{tags}" ) ;
}
}
2020-02-01 12:03:02 +00:00
// Subcommand: "add"
2020-02-04 17:16:45 +00:00
else if ( ctx . Match ( "add" , "append" ) )
2020-02-01 12:03:02 +00:00
{
2020-02-22 14:21:48 +00:00
if ( ! ctx . HasNext ( skipFlags : false ) ) throw new PKSyntaxError ( "You must pass an example proxy to add (eg. `[text]` or `J:text`)." ) ;
2020-02-01 12:03:02 +00:00
2020-02-20 22:53:05 +00:00
var tagToAdd = ParseProxyTags ( ctx . RemainderOrNull ( skipFlags : false ) ) ;
2020-02-03 14:11:35 +00:00
if ( tagToAdd . IsEmpty ) throw Errors . EmptyProxyTags ( target ) ;
2020-02-01 12:03:02 +00:00
if ( target . ProxyTags . Contains ( tagToAdd ) )
throw Errors . ProxyTagAlreadyExists ( tagToAdd , target ) ;
if ( ! await WarnOnConflict ( tagToAdd ) )
throw Errors . GenericCancelled ( ) ;
// It's not guaranteed the list's mutable, so we force it to be
target . ProxyTags = target . ProxyTags . ToList ( ) ;
target . ProxyTags . Add ( tagToAdd ) ;
await _data . SaveMember ( target ) ;
await ctx . Reply ( $"{Emojis.Success} Added proxy tags `{tagToAdd.ProxyString.SanitizeMentions()}`." ) ;
}
// Subcommand: "remove"
2020-02-04 17:16:45 +00:00
else if ( ctx . Match ( "remove" , "delete" ) )
2020-02-01 12:03:02 +00:00
{
2020-02-22 14:21:48 +00:00
if ( ! ctx . HasNext ( skipFlags : false ) ) throw new PKSyntaxError ( "You must pass a proxy tag to remove (eg. `[text]` or `J:text`)." ) ;
2020-02-01 12:03:02 +00:00
2020-02-20 22:53:05 +00:00
var tagToRemove = ParseProxyTags ( ctx . RemainderOrNull ( skipFlags : false ) ) ;
2020-02-03 14:11:35 +00:00
if ( tagToRemove . IsEmpty ) throw Errors . EmptyProxyTags ( target ) ;
2020-02-01 12:03:02 +00:00
if ( ! target . ProxyTags . Contains ( tagToRemove ) )
throw Errors . ProxyTagDoesNotExist ( tagToRemove , target ) ;
// It's not guaranteed the list's mutable, so we force it to be
target . ProxyTags = target . ProxyTags . ToList ( ) ;
target . ProxyTags . Remove ( tagToRemove ) ;
await _data . SaveMember ( target ) ;
await ctx . Reply ( $"{Emojis.Success} Removed proxy tags `{tagToRemove.ProxyString.SanitizeMentions()}`." ) ;
}
// Subcommand: bare proxy tag given
else
{
2020-02-20 22:53:05 +00:00
var requestedTag = ParseProxyTags ( ctx . RemainderOrNull ( skipFlags : false ) ) ;
2020-02-03 14:11:35 +00:00
if ( requestedTag . IsEmpty ) throw Errors . EmptyProxyTags ( target ) ;
2020-02-05 22:44:03 +00:00
// This is mostly a legacy command, so it's gonna warn if there's
2020-02-01 12:03:02 +00:00
// already more than one proxy tag.
if ( target . ProxyTags . Count > 1 )
2020-02-05 22:44:03 +00:00
{
var msg = await ctx . Reply ( $"This member already has more than one proxy tag set: {target.ProxyTagsString().SanitizeMentions()}\nDo you want to replace them?" ) ;
if ( ! await ctx . PromptYesNo ( msg ) )
throw Errors . GenericCancelled ( ) ;
}
2020-02-01 12:03:02 +00:00
if ( ! await WarnOnConflict ( requestedTag ) )
throw Errors . GenericCancelled ( ) ;
target . ProxyTags = new [ ] { requestedTag } ;
await _data . SaveMember ( target ) ;
await ctx . Reply ( $"{Emojis.Success} Member proxy tags set to `{requestedTag.ProxyString.SanitizeMentions()}`." ) ;
}
}
}
}