2018-09-16 19:36:50 +02:00
import pluralkit . bot . embeds
2018-09-02 19:41:14 +02:00
from pluralkit . bot import help
2018-09-09 20:38:57 +02:00
from pluralkit . bot . commands import *
2018-09-16 13:46:22 +02:00
from pluralkit . errors import PluralKitError
2018-07-24 22:47:57 +02:00
2018-12-05 11:44:10 +01:00
async def member_root ( ctx : CommandContext ) :
if ctx . match ( " new " ) or ctx . match ( " create " ) or ctx . match ( " add " ) or ctx . match ( " register " ) :
await new_member ( ctx )
# TODO "pk;member list"
2018-12-10 22:00:34 +01:00
elif not ctx . has_next ( ) :
2018-12-11 20:04:26 +01:00
raise CommandError ( " Must pass a subcommand. For a list of subcommands, type `pk;help member`. " )
2018-12-10 22:00:34 +01:00
else :
await specific_member_root ( ctx )
2018-12-05 11:44:10 +01:00
async def specific_member_root ( ctx : CommandContext ) :
member = await ctx . pop_member ( system_only = False )
if ctx . has_next ( ) :
# Following commands operate on members only in the caller's own system
# error if not, to make sure you can't destructively edit someone else's member
system = await ctx . ensure_system ( )
if not member . system == system . id :
raise CommandError ( " Member must be in your own system. " )
if ctx . match ( " name " ) or ctx . match ( " rename " ) :
await member_name ( ctx , member )
2019-04-11 16:09:29 +09:30
elif ctx . match ( " description " ) or ctx . match ( " desc " ) :
2018-12-05 11:44:10 +01:00
await member_description ( ctx , member )
elif ctx . match ( " avatar " ) or ctx . match ( " icon " ) :
await member_avatar ( ctx , member )
elif ctx . match ( " proxy " ) or ctx . match ( " tags " ) :
await member_proxy ( ctx , member )
elif ctx . match ( " pronouns " ) or ctx . match ( " pronoun " ) :
await member_pronouns ( ctx , member )
elif ctx . match ( " color " ) or ctx . match ( " colour " ) :
await member_color ( ctx , member )
2019-04-11 17:40:56 +09:30
elif ctx . match ( " birthday " ) or ctx . match ( " birthdate " ) or ctx . match ( " bday " ) :
2018-12-05 11:44:10 +01:00
await member_birthdate ( ctx , member )
elif ctx . match ( " delete " ) or ctx . match ( " remove " ) or ctx . match ( " destroy " ) or ctx . match ( " erase " ) :
await member_delete ( ctx , member )
else :
raise CommandError (
2018-12-10 20:09:35 +01:00
" Unknown subcommand {} . For a list of all commands, type `pk;help member` " . format ( ctx . pop_str ( ) ) )
2018-12-05 11:44:10 +01:00
else :
# Basic lookup
await member_info ( ctx , member )
async def member_info ( ctx : CommandContext , member : Member ) :
2019-06-15 16:32:38 +09:30
msg = await ctx . reply ( embed = await pluralkit . bot . embeds . member_card ( ctx . conn , member ) )
if await ctx . delete_by_react ( ctx . message . author , msg ) :
await msg . delete ( )
2019-06-15 16:56:25 +09:30
try :
await ctx . message . delete ( )
except discord . Forbidden :
# This will fail if we don't have Manage messages, just silently fail tbh
# The user can delete their own command if they want
pass
2018-07-24 22:47:57 +02:00
2018-09-07 17:34:38 +02:00
async def new_member ( ctx : CommandContext ) :
system = await ctx . ensure_system ( )
if not ctx . has_next ( ) :
2018-12-05 11:44:10 +01:00
raise CommandError ( " You must pass a name for the new member. " )
2018-09-07 17:34:38 +02:00
2018-09-16 13:46:22 +02:00
new_name = ctx . remaining ( )
2018-07-24 22:47:57 +02:00
2018-11-30 21:51:57 +01:00
existing_member = await Member . get_member_by_name ( ctx . conn , system . id , new_name )
if existing_member :
2018-12-05 11:44:10 +01:00
msg = await ctx . reply_warn (
" There is already a member with this name, with the ID ` {} `. Do you want to create a duplicate member anyway? " . format (
existing_member . hid ) )
2018-11-30 21:51:57 +01:00
if not await ctx . confirm_react ( ctx . message . author , msg ) :
raise CommandError ( " Member creation cancelled. " )
2018-09-16 13:46:22 +02:00
try :
member = await system . create_member ( ctx . conn , new_name )
except PluralKitError as e :
2018-11-15 21:05:13 +01:00
raise CommandError ( e . message )
2018-07-24 22:47:57 +02:00
2018-11-15 21:05:13 +01:00
await ctx . reply_ok (
2018-12-11 20:04:26 +01:00
" Member \" {} \" (` {} `) registered! Type `pk;help member` for a list of commands to edit this member. " . format ( new_name , member . hid ) )
2018-07-24 22:47:57 +02:00
2018-12-05 11:44:10 +01:00
async def member_name ( ctx : CommandContext , member : Member ) :
2018-09-07 17:34:38 +02:00
system = await ctx . ensure_system ( )
2018-12-05 11:44:10 +01:00
new_name = ctx . pop_str ( CommandError ( " You must pass a new member name. " ) )
2018-07-24 22:47:57 +02:00
2018-11-30 21:51:57 +01:00
# Warn if there's a member by the same name already
existing_member = await Member . get_member_by_name ( ctx . conn , system . id , new_name )
2018-12-05 11:44:10 +01:00
if existing_member and existing_member . id != member . id :
msg = await ctx . reply_warn (
" There is already another member with this name, with the ID ` {} `. Do you want to rename this member anyway? This will result in two members with the same name. " . format (
existing_member . hid ) )
2018-11-30 21:51:57 +01:00
if not await ctx . confirm_react ( ctx . message . author , msg ) :
raise CommandError ( " Member renaming cancelled. " )
2018-11-30 21:42:01 +01:00
await member . set_name ( ctx . conn , new_name )
2018-11-23 21:55:47 +01:00
await ctx . reply_ok ( " Member name updated. " )
2018-07-24 22:47:57 +02:00
2018-11-30 21:42:01 +01:00
if len ( new_name ) < 2 and not system . tag :
2018-12-05 11:44:10 +01:00
await ctx . reply_warn (
" This member ' s new name is under 2 characters, and thus cannot be proxied. To prevent this, use a longer member name, or add a system tag. " )
2018-11-30 21:42:01 +01:00
elif len ( new_name ) > 32 :
exceeds_by = len ( new_name ) - 32
2018-12-05 11:44:10 +01:00
await ctx . reply_warn (
" This member ' s new name is longer than 32 characters, and thus cannot be proxied. To prevent this, shorten the member name by {} characters. " . format (
exceeds_by ) )
2018-11-30 21:42:01 +01:00
elif len ( new_name ) > system . get_member_name_limit ( ) :
exceeds_by = len ( new_name ) - system . get_member_name_limit ( )
2018-12-05 11:44:10 +01:00
await ctx . reply_warn (
" This member ' s new name, when combined with the system tag ` {} `, is longer than 32 characters, and thus cannot be proxied. To prevent this, shorten the name or system tag by at least {} characters. " . format (
system . tag , exceeds_by ) )
2018-11-30 21:42:01 +01:00
2018-09-07 17:34:38 +02:00
2018-12-05 11:44:10 +01:00
async def member_description ( ctx : CommandContext , member : Member ) :
2018-11-23 21:55:47 +01:00
new_description = ctx . remaining ( ) or None
await member . set_description ( ctx . conn , new_description )
await ctx . reply_ok ( " Member description {} . " . format ( " updated " if new_description else " cleared " ) )
2018-12-05 11:44:10 +01:00
async def member_avatar ( ctx : CommandContext , member : Member ) :
2018-11-23 21:55:47 +01:00
new_avatar_url = ctx . remaining ( ) or None
if new_avatar_url :
user = await utils . parse_mention ( ctx . client , new_avatar_url )
if user :
new_avatar_url = user . avatar_url_as ( format = " png " )
2019-05-03 08:50:46 -04:00
if not new_avatar_url and ctx . message . attachments [ 0 ] :
new_avatar_url = ctx . message . attachments [ 0 ] . url
2018-11-23 21:55:47 +01:00
await member . set_avatar ( ctx . conn , new_avatar_url )
await ctx . reply_ok ( " Member avatar {} . " . format ( " updated " if new_avatar_url else " cleared " ) )
2018-12-05 11:44:10 +01:00
async def member_color ( ctx : CommandContext , member : Member ) :
2018-11-23 21:55:47 +01:00
new_color = ctx . remaining ( ) or None
await member . set_color ( ctx . conn , new_color )
await ctx . reply_ok ( " Member color {} . " . format ( " updated " if new_color else " cleared " ) )
2018-12-05 11:44:10 +01:00
async def member_pronouns ( ctx : CommandContext , member : Member ) :
2018-11-23 21:55:47 +01:00
new_pronouns = ctx . remaining ( ) or None
await member . set_pronouns ( ctx . conn , new_pronouns )
await ctx . reply_ok ( " Member pronouns {} . " . format ( " updated " if new_pronouns else " cleared " ) )
2018-12-05 11:44:10 +01:00
async def member_birthdate ( ctx : CommandContext , member : Member ) :
2018-11-23 21:55:47 +01:00
new_birthdate = ctx . remaining ( ) or None
await member . set_birthdate ( ctx . conn , new_birthdate )
await ctx . reply_ok ( " Member birthdate {} . " . format ( " updated " if new_birthdate else " cleared " ) )
2018-07-24 22:47:57 +02:00
2018-09-07 17:34:38 +02:00
2018-12-05 11:44:10 +01:00
async def member_proxy ( ctx : CommandContext , member : Member ) :
2018-09-07 17:34:38 +02:00
if not ctx . has_next ( ) :
2018-07-24 22:47:57 +02:00
prefix , suffix = None , None
else :
# Sanity checking
2018-09-07 17:34:38 +02:00
example = ctx . remaining ( )
2018-07-24 22:47:57 +02:00
if " text " not in example :
2018-12-05 11:44:10 +01:00
raise CommandError ( " Example proxy message must contain the string ' text ' . For help, type `pk;help proxy`. " )
2018-07-24 22:47:57 +02:00
if example . count ( " text " ) != 1 :
2018-12-05 11:44:10 +01:00
raise CommandError ( " Example proxy message must contain the string ' text ' exactly once. For help, type `pk;help proxy`. " )
2018-07-24 22:47:57 +02:00
# Extract prefix and suffix
prefix = example [ : example . index ( " text " ) ] . strip ( )
2018-09-07 17:34:38 +02:00
suffix = example [ example . index ( " text " ) + 4 : ] . strip ( )
2018-07-24 22:47:57 +02:00
# DB stores empty strings as None, make that work
if not prefix :
prefix = None
if not suffix :
suffix = None
async with ctx . conn . transaction ( ) :
2018-09-16 13:46:22 +02:00
await member . set_proxy_tags ( ctx . conn , prefix , suffix )
2018-12-05 11:44:10 +01:00
await ctx . reply_ok (
" Proxy settings updated. " if prefix or suffix else " Proxy settings cleared. If you meant to set your proxy tags, type `pk;help proxy` for help. " )
2018-09-07 17:34:38 +02:00
2018-07-24 22:47:57 +02:00
2018-12-05 11:44:10 +01:00
async def member_delete ( ctx : CommandContext , member : Member ) :
2018-11-23 21:55:47 +01:00
delete_confirm_msg = " Are you sure you want to delete {} ? If so, reply to this message with the member ' s ID (` {} `). " . format (
member . name , member . hid )
2018-09-08 13:48:18 +02:00
if not await ctx . confirm_text ( ctx . message . author , ctx . message . channel , member . hid , delete_confirm_msg ) :
2018-11-15 21:05:13 +01:00
raise CommandError ( " Member deletion cancelled. " )
2018-09-08 13:48:18 +02:00
2018-09-16 13:46:22 +02:00
await member . delete ( ctx . conn )
2018-11-15 21:05:13 +01:00
await ctx . reply_ok ( " Member deleted. " )