2019-04-29 17:43:09 +00:00
using System ;
2019-05-11 21:56:56 +00:00
using System.Text.RegularExpressions ;
2019-04-27 14:30:34 +00:00
using System.Threading.Tasks ;
using Discord.Commands ;
2019-05-13 20:44:49 +00:00
using NodaTime ;
2019-04-27 14:30:34 +00:00
namespace PluralKit.Bot.Commands
{
[Group("member")]
public class MemberCommands : ContextParameterModuleBase < PKMember >
{
2019-05-11 22:44:02 +00:00
public SystemStore Systems { get ; set ; }
2019-04-27 14:30:34 +00:00
public MemberStore Members { get ; set ; }
2019-05-11 22:44:02 +00:00
public EmbedService Embeds { get ; set ; }
2019-04-27 14:30:34 +00:00
public override string Prefix = > "member" ;
public override string ContextNoun = > "member" ;
[Command("new")]
[Remarks("member new <name>")]
2019-04-29 17:43:09 +00:00
[MustHaveSystem]
2019-04-27 14:30:34 +00:00
public async Task NewMember ( [ Remainder ] string memberName ) {
2019-04-29 18:28:53 +00:00
// Hard name length cap
if ( memberName . Length > Limits . MaxMemberNameLength ) throw Errors . MemberNameTooLongError ( memberName . Length ) ;
2019-04-27 14:30:34 +00:00
// Warn if member name will be unproxyable (with/without tag)
2019-04-29 17:43:09 +00:00
if ( memberName . Length > Context . SenderSystem . MaxMemberNameLength ) {
var msg = await Context . Channel . SendMessageAsync ( $"{Emojis.Warn} Member name too long ({memberName.Length} > {Context.SenderSystem.MaxMemberNameLength} characters), this member will be unproxyable. Do you want to create it anyway? (You can change the name later)" ) ;
2019-04-27 14:30:34 +00:00
if ( ! await Context . PromptYesNo ( msg ) ) throw new PKError ( "Member creation cancelled." ) ;
}
// Warn if there's already a member by this name
var existingMember = await Members . GetByName ( Context . SenderSystem , memberName ) ;
if ( existingMember ! = null ) {
2019-04-29 17:43:09 +00:00
var msg = await Context . Channel . SendMessageAsync ( $"{Emojis.Warn} You already have a member in your system with the name \" { existingMember . Name } \ " (with ID `{existingMember.Hid}`). Do you want to create another member with the same name?" ) ;
2019-04-27 14:30:34 +00:00
if ( ! await Context . PromptYesNo ( msg ) ) throw new PKError ( "Member creation cancelled." ) ;
}
// Create the member
var member = await Members . Create ( Context . SenderSystem , memberName ) ;
2019-04-29 17:43:09 +00:00
// Send confirmation and space hint
2019-04-27 14:30:34 +00:00
await Context . Channel . SendMessageAsync ( $"{Emojis.Success} Member \" { memberName } \ " (`{member.Hid}`) registered! Type `pk;help member` for a list of commands to edit this member." ) ;
if ( memberName . Contains ( " " ) ) await Context . Channel . SendMessageAsync ( $"{Emojis.Note} Note that this member's name contains spaces. You will need to surround it with \" double quotes \ " when using commands referring to it." ) ;
}
2019-04-29 17:43:09 +00:00
[Command("rename")]
[Alias("name", "changename", "setname")]
[Remarks("member <member> rename <newname>")]
[MustPassOwnMember]
public async Task RenameMember ( [ Remainder ] string newName ) {
// TODO: this method is pretty much a 1:1 copy/paste of the above creation method, find a way to clean?
2019-04-29 18:28:53 +00:00
// Hard name length cap
if ( newName . Length > Limits . MaxMemberNameLength ) throw Errors . MemberNameTooLongError ( newName . Length ) ;
2019-04-29 17:43:09 +00:00
// Warn if member name will be unproxyable (with/without tag)
if ( newName . Length > Context . SenderSystem . MaxMemberNameLength ) {
var msg = await Context . Channel . SendMessageAsync ( $"{Emojis.Warn} New member name too long ({newName.Length} > {Context.SenderSystem.MaxMemberNameLength} characters), this member will be unproxyable. Do you want to change it anyway?" ) ;
if ( ! await Context . PromptYesNo ( msg ) ) throw new PKError ( "Member renaming cancelled." ) ;
}
// Warn if there's already a member by this name
var existingMember = await Members . GetByName ( Context . SenderSystem , newName ) ;
if ( existingMember ! = null ) {
var msg = await Context . Channel . SendMessageAsync ( $"{Emojis.Warn} You already have a member in your system with the name \" { existingMember . Name } \ " (`{existingMember.Hid}`). Do you want to rename this member to that name too?" ) ;
if ( ! await Context . PromptYesNo ( msg ) ) throw new PKError ( "Member renaming cancelled." ) ;
}
2019-05-11 21:56:56 +00:00
// Rename the member
2019-04-29 17:43:09 +00:00
ContextEntity . Name = newName ;
await Members . Save ( ContextEntity ) ;
await Context . Channel . SendMessageAsync ( $"{Emojis.Success} Member renamed." ) ;
if ( newName . Contains ( " " ) ) await Context . Channel . SendMessageAsync ( $"{Emojis.Note} Note that this member's name now contains spaces. You will need to surround it with \" double quotes \ " when using commands referring to it." ) ;
}
2019-04-29 18:33:21 +00:00
[Command("description")]
[Alias("info", "bio", "text")]
2019-05-11 21:56:56 +00:00
[Remarks("member <member> description <description>")]
2019-04-29 18:33:21 +00:00
[MustPassOwnMember]
public async Task MemberDescription ( [ Remainder ] string description = null ) {
2019-05-11 21:56:56 +00:00
if ( description . IsLongerThan ( Limits . MaxDescriptionLength ) ) throw Errors . DescriptionTooLongError ( description . Length ) ;
2019-04-29 18:33:21 +00:00
ContextEntity . Description = description ;
await Members . Save ( ContextEntity ) ;
await Context . Channel . SendMessageAsync ( $"{Emojis.Success} Member description {(description == null ? " cleared " : " changed ")}." ) ;
}
2019-04-29 18:36:09 +00:00
[Command("pronouns")]
[Alias("pronoun")]
2019-05-11 21:56:56 +00:00
[Remarks("member <member> pronouns <pronouns>")]
2019-04-29 18:36:09 +00:00
[MustPassOwnMember]
public async Task MemberPronouns ( [ Remainder ] string pronouns = null ) {
2019-05-11 21:56:56 +00:00
if ( pronouns . IsLongerThan ( Limits . MaxPronounsLength ) ) throw Errors . MemberPronounsTooLongError ( pronouns . Length ) ;
2019-04-29 18:36:09 +00:00
ContextEntity . Pronouns = pronouns ;
await Members . Save ( ContextEntity ) ;
await Context . Channel . SendMessageAsync ( $"{Emojis.Success} Member pronouns {(pronouns == null ? " cleared " : " changed ")}." ) ;
}
2019-05-11 21:56:56 +00:00
[Command("color")]
[Alias("colour")]
[Remarks("member <member> color <color>")]
[MustPassOwnMember]
public async Task MemberColor ( [ Remainder ] string color = null )
{
if ( color ! = null )
{
if ( color . StartsWith ( "#" ) ) color = color . Substring ( 1 ) ;
if ( ! Regex . IsMatch ( color , "[0-9a-f]{6}" ) ) throw Errors . InvalidColorError ( color ) ;
}
ContextEntity . Color = color ;
await Members . Save ( ContextEntity ) ;
await Context . Channel . SendMessageAsync ( $"{Emojis.Success} Member color {(color == null ? " cleared " : " changed ")}." ) ;
}
2019-05-11 22:44:02 +00:00
2019-05-13 20:44:49 +00:00
[Command("birthday")]
[Alias("birthdate", "bday", "cakeday", "bdate")]
[Remarks("member <member> birthday <birthday>")]
[MustPassOwnMember]
public async Task MemberBirthday ( [ Remainder ] string birthday = null )
{
LocalDate ? date = null ;
if ( birthday ! = null )
{
date = PluralKit . Utils . ParseDate ( birthday , true ) ;
if ( date = = null ) throw Errors . BirthdayParseError ( birthday ) ;
}
ContextEntity . Birthday = date ;
await Members . Save ( ContextEntity ) ;
await Context . Channel . SendMessageAsync ( $"{Emojis.Success} Member birthdate {(date == null ? " cleared " : $" changed to { ContextEntity . BirthdayString } ")}." ) ;
}
2019-05-11 22:44:02 +00:00
[Command]
2019-05-13 20:44:49 +00:00
[Alias("view", "show", "info")]
2019-05-11 22:44:02 +00:00
[Remarks("member")]
public async Task ViewMember ( PKMember member )
{
2019-05-13 20:44:49 +00:00
var system = await Systems . GetById ( member . System ) ;
2019-05-11 22:44:02 +00:00
await Context . Channel . SendMessageAsync ( embed : await Embeds . CreateMemberEmbed ( system , member ) ) ;
}
2019-05-11 21:56:56 +00:00
2019-04-27 14:30:34 +00:00
public override async Task < PKMember > ReadContextParameterAsync ( string value )
{
var res = await new PKMemberTypeReader ( ) . ReadAsync ( Context , value , _services ) ;
return res . IsSuccess ? res . BestMatch as PKMember : null ;
}
}
}