async def getprofilemeta(self, ctx: Context, profile: Profile, target_user: Member): """Gets a profile for a given member""" # See if there's a set profile user_profile = profile.get_profile_for_member(target_user or ctx.author) if user_profile is None: if target_user: await ctx.send( f"{target_user.mention} doesn't have a profile for `{profile.name}`." ) else: await ctx.send( f"You don't have a profile for `{profile.name}`.") return # See if verified if user_profile.verified or member_is_moderator(ctx.bot, ctx.author): await ctx.send(embed=user_profile.build_embed()) return # Not verified if target_user: await ctx.send( f"{target_user.mention}'s profile hasn't been verified yet.") else: await ctx.send(f"Your profile hasn't been verified yet.") return
async def deleteprofilemeta(self, ctx: Context, profile: Profile, target_user: Member): """Handles deleting a profile""" # Handle permissions if ctx.author != target_user and not member_is_moderator( self.bot, ctx.author): await ctx.send( f"You're missing the `manage_roles` permission required to do this." ) return # Check it exists if profile.get_profile_for_member(target_user or ctx.author) is None: if target_user: await ctx.send( f"{target_user.mention} doesn't have a profile set for `{profile.name}`." ) else: await ctx.send( f"You don't have a profile set for `{profile.name}`.") return # Database it babey async with self.bot.database() as db: await db( 'DELETE FROM filled_field WHERE user_id=$1 AND field_id in (SELECT field_id FROM field WHERE profile_id=$2)', target_user.id, profile.profile_id) await db( 'DELETE FROM created_profile WHERE user_id=$1 AND profile_id=$2', target_user.id, profile.profile_id) del UserProfile.all_profiles[(target_user.id, ctx.guild.id, profile.name)] await ctx.send("Profile deleted.")
async def verification_emoji_check(self, payload: RawReactionActionEvent): '''Triggered when a reaction is added or removed, check for profile verification''' # Firstly we wanna check the message being reacted to, make sure its ours channel_id = payload.channel_id channel: TextChannel = self.bot.get_channel(channel_id) if channel is None: channel: TextChannel = await self.bot.fetch_channel(channel_id) # Get the message from the channel message: Message = await channel.fetch_message(payload.message_id) # Check if we're the author if message.author.id != self.bot.user.id: return # Check if there's an embed if not message.embeds: return # Make sure it's the right kind of embed embed: Embed = message.embeds[0] if 'Verification Check' not in embed.footer.text: return # profile_name = embed.footer.text.split('//')[0].strip().lower() profile_name = embed.title.split(' ')[0].strip().lower() # It's a verification message! Now we wanna check the author to make sure they're approved # Get guild guild_id = payload.guild_id guild: Guild = self.bot.get_guild(guild_id) if guild is None: guild: Guild = await self.bot.fetch_guild(guild_id) # Get the member from the guild member: Member = guild.get_member(payload.user_id) # Make sure they aren't a bot if member.bot: return # Check their permissions if not member_is_moderator(self.bot, member): return # And FINALLY we can check their emoji if payload.emoji.id and payload.emoji.id not in [ self.TICK_EMOJI_ID, self.CROSS_EMOJI_ID ]: return # Check what they reacted with verify = payload.emoji.id == self.TICK_EMOJI_ID # Check whom and what we're updating profile_user_id, profile_id = message.content.split('\n')[-1].split( '/') profile_user_id = int(profile_user_id) # Decide whether to verify or to delete async with self.bot.database() as db: if verify: await db( 'UPDATE created_profile SET verified=true WHERE user_id=$1 AND profile_id=$2', profile_user_id, profile_id) else: await db( 'DELETE FROM filled_field WHERE user_id=$1 AND field_id IN (SELECT field_id FROM field WHERE profile_id=$2)', profile_user_id, profile_id) await db( 'DELETE FROM created_profile WHERE user_id=$1 AND profile_id=$2', profile_user_id, profile_id) # Delete the verify message await message.delete() # Get the profile profile = UserProfile.all_profiles.get( (profile_user_id, guild.id, profile_name)) if profile is None: # Silently fail I guess return # Remove them if necessary if verify is False: del UserProfile.all_profiles[(profile_user_id, guild.id, profile_name)] else: profile.verified = verify # Tell the user about the decision user: User = self.bot.get_user(profile_user_id) if user is None: user: User = await self.bot.fetch_user(profile_user_id) try: if verify: await user.send( f"Your profile for `{profile.profile.name}` on `{guild.name}` has been verified.", embed=profile.build_embed()) else: await user.send( f"Your profile for `{profile.profile.name}` on `{guild.name}` has been denied.", embed=profile.build_embed()) except Exception: # Issues sending info to the user, just fail silently # raise e pass
async def setprofilemeta(self, ctx: Context, profile: Profile, target_user: Member): """Talks a user through setting up a profile on a given server""" # Set up some variaballlales user = ctx.author target_user = target_user or user fields = profile.fields # Check if they're setting someone else's profile and they're not a mod if target_user != ctx.author and not member_is_moderator( ctx.bot, ctx.author): await ctx.send( f"You're missing the `manage_roles` permission required to do this." ) return # Check if they already have a profile set user_profile = profile.get_profile_for_member(target_user) if user_profile is not None: await ctx.send( f"{'You' if target_user == user else target_user.mention} already {'have' if target_user == user else 'has'} a profile set for `{profile.name}`." ) return # See if you we can send them the PM try: await user.send( f"Now talking you through setting up a `{profile.name}` profile{' for ' + target_user.mention if target_user != user else ''}." ) await ctx.send("Sent you a PM!") except Exception: await ctx.send( "I'm unable to send you PMs to set up the profile :/") return # Talk the user through each field filled_fields = [] for field in fields: await user.send(field.prompt) # User text input if isinstance(field.field_type, (TextField, NumberField)): check = lambda m: m.author == user and isinstance( m.channel, DMChannel) while True: try: m = await self.bot.wait_for('message', check=check, timeout=field.timeout) except AsyncTimeoutError: await user.send( f"Your input for this field has timed out. Please try running `set{profile.name}` on your server again." ) return try: field.field_type.check(m.content) field_content = m.content break except FieldCheckFailure as e: await user.send(e.message) # Image input elif isinstance(field.field_type, ImageField): check = lambda m: m.author == user and isinstance( m.channel, DMChannel) while True: try: m = await self.bot.wait_for('message', check=check, timeout=field.timeout) except AsyncTimeoutError: await user.send( f"Your input for this field has timed out. Please try running `set{profile.name}` on your server again." ) return try: if m.attachments: content = m.attachments[0].url else: content = m.content field.field_type.check(content) field_content = content break except FieldCheckFailure as e: await user.send(e.message) # Invalid field type apparently else: raise Exception( f"Field type {field.field_type} is not catered for") # Add field to list filled_fields.append( FilledField(target_user.id, field.field_id, field_content)) # Make the UserProfile object up = UserProfile(target_user.id, profile.profile_id, profile.verification_channel_id == None) # Make sure the bot can send the embed at all try: await user.send(embed=up.build_embed()) except Exception as e: await user.send( f"Your profile couldn't be sent to you - `{e}`.\nPlease try again later." ) return # Make sure the bot can send the embed to the channel if profile.verification_channel_id: try: channel = await self.bot.fetch_channel( profile.verification_channel_id) embed = up.build_embed() embed.set_footer( text=f'{profile.name.upper()} // Verification Check') v = await channel.send( f"New **{profile.name}** submission from {target_user.mention}\n{target_user.id}/{profile.profile_id}", embed=embed) await v.add_reaction(self.TICK_EMOJI) await v.add_reaction(self.CROSS_EMOJI) except Exception as e: await user.send( f"Your profile couldn't be send to the verification channel? - `{e}`." ) return # Database me up daddy async with self.bot.database() as db: try: await db( 'INSERT INTO created_profile (user_id, profile_id, verified) VALUES ($1, $2, $3)', up.user_id, up.profile.profile_id, up.verified) except UniqueViolationError: await db( 'UPDATE created_profile SET verified=$3 WHERE user_id=$1 AND profile_id=$2', up.user_id, up.profile.profile_id, up.verified) await db( 'DELETE FROM filled_field WHERE user_id=$1 AND field_id in (SELECT field_id FROM field WHERE profile_id=$2)', up.user_id, up.profile.profile_id) self.log_handler.warn( f"Deleted profile for {up.user_id} on UniqueViolationError" ) for field in filled_fields: await db( 'INSERT INTO filled_field (user_id, field_id, value) VALUES ($1, $2, $3)', field.user_id, field.field_id, field.value) # Respond to user await user.send("Your profile has been created and saved.")