async def start(self, ctx: commands.context, system_member: discord.Member): """ Starts a suspended instance :param ctx: Discord Context :param system_member: System Member """ # TODO: Provide more verbose feedback from command await ctx.message.delete() member = get_member_by_discord_id(system_member.id) if member is not None: if not member["member_enabled"]: c.execute( "UPDATE members SET member_enabled = 1 WHERE member_account_id = ?", [system_member.id], ) instances.append(create_member_instance(member)) await ctx.send( f"{system_member.mention} started by {ctx.message.author.mention}" ) log.info( f"{system_member} has been started by {ctx.message.author}" ) else: await ctx.send(f"{system_member.mention} is already running")
async def disable(self, ctx: commands.context, system_member: discord.Member): """ Disables a system member permanently by deleting it from the database and kicking it from the server. Bot token cannot be reused. :param ctx: Discord Context :param system_member: System Member """ # TODO: Provide more verbose feedback from command instance = get_member_by_discord_id(system_member.id) if instance: log.debug(f"Disabling {system_member}") confirmation = BotConfirmation(ctx, discord.Color.red()) await confirmation.confirm( f"Disable member {system_member} permanently?") if confirmation.confirmed: await confirmation.message.delete() with conn: c.execute( "DELETE FROM members WHERE token = ?", [instance["token"]], ) await self.suspend(ctx, system_member) await ctx.send( f"{system_member.mention} disabled permanently by {ctx.message.author}" ) log.info( f"{system_member} has been disabled permanently by {ctx.message.author}" ) log.debug(f"Disabled {system_member}") else: await confirmation.message.delete() await ctx.send(f"{system_member.mention} was __not__ disabled") log.debug(f"Canceled disable of {system_member}")
async def suspend(self, ctx: commands.context, system_member: discord.Member): """ Pulls the member instance offline. :param ctx: Discord Context :param system_member: System Member """ # TODO: Provide more verbose feedback from command await ctx.message.delete() for i, instance in enumerate(instances): if instance.user.id == system_member.id: await instance.close() with conn: c.execute( "UPDATE members SET member_enabled = 0 WHERE token = ?", [instance.get_token()], ) del instances[i] await ctx.send( f"{system_member.mention} suspended by {ctx.author.mention}" ) log.info( f"{system_member} has been suspended by {ctx.message.author}" )
async def whoarewe(self, ctx: commands.context): """ List members of system belonging to user who executes command :param ctx: Discord Context """ log.debug(f"Listing members for {ctx.author.display_name}...") c.execute( "SELECT * FROM members WHERE discord_account_id == ?", [ctx.author.id], ) member_list = c.fetchall() embed = discord.Embed(title=f"Members of System") embed.set_author(name=f"{ctx.author}", icon_url=ctx.author.avatar_url) if member_list is None: embed.add_field(name="No members where found", value="Ask a mod to add some!") for member in member_list: member_user = ctx.guild.get_member_named( f"p.{member['member_name']}") tags = [] for tag in json.loads(member["pk_proxy_tags"]): tags.append("`" + (tag.get("prefix") or "") + "text" + (tag.get("suffix") or "") + "`") embed.add_field( name=dict(member).get("display_name", member["member_name"]), value= f"""**User:** {member_user.mention}\n**PluralKit Member ID:** `{member['pk_member_id']}`\n**Tags:** {' or '.join(tags)}\n**Enabled:** `{'Yes' if member['member_enabled'] else 'No'}`""", inline=True, ) await ctx.send(embed=embed)
async def tokens(self, ctx: commands.context, *tokens: str): """ Add tokens to queue :param ctx: Discord Context :param tokens: List of tokens """ async def session(self, author: discord.Member): self.token_session.append(author) await asyncio.sleep(300) self.token_session.remove(author) if (ctx.channel.type is discord.ChannelType.private and ctx.message.author in self.token_session): await ctx.send("Adding tokens...") log.debug(tokens) for index, token in enumerate(tokens): logger = LogMessage(ctx, title=f"Adding token #{index+1}...") await logger.init() # Check token await logger.log(f"Checking token #{index+1}...") check_result, client_id = await check_token(token) if not check_result: logger.title = f"Token #{index+1} Invalid" logger.color = discord.Color.red() await logger.log("Bot token is invalid") else: await logger.log("Token valid") if get_token(token) is None: log.info("Adding new token to database") insert_token(token, False) logger.title = f"Bot token #{index+1} added" logger.color = discord.Color.green() c.execute("SELECT * FROM tokens WHERE used = 0") slots = c.fetchall() from polyphony.bot import bot await logger.send( f"[Invite to Server]({discord.utils.oauth_url(client_id, permissions=discord.Permissions(DEFAULT_INSTANCE_PERMS), guild=bot.get_guild(GUILD_ID))})\n\n**Client ID:** {client_id}\nThere are now {len(slots)} slot(s) available" ) else: logger.title = f"Token #{index+1} already in database" logger.color = discord.Color.orange() await logger.log("Bot token already in database") elif ctx.channel.type is not discord.ChannelType.private: await ctx.message.delete() if any(role.name in MODERATOR_ROLES for role in ctx.message.author.roles): await ctx.message.author.send( f"Token mode enabled for 5 minutes. Add tokens with `{self.bot.command_prefix}tokens [token] (more tokens...)` right here.\n\n*Don't paste a bot token in a server*" ) await session(self, ctx.message.author) elif any(role.name in MODERATOR_ROLES for role in ctx.message.author.roles): ctx.message.delete() await ctx.channel.send( f"To add tokens, execute `{self.bot.command_prefix}tokens` as a moderator on a server **WITHOUT A BOT TOKEN**. Then in DMs, use `{self.bot.command_prefix}tokens [token] (more tokens...)`\n\n*Seriously don't paste a bot token in a server*" )
def pk_proxy_tags(self, value: dict): self._pk_proxy_tags = value with conn: log.debug( f"{self.user} ({self.pk_member_id}): Updating proxy tags to {value}" ) c.execute( "UPDATE members SET pk_proxy_tags = ? WHERE token = ?", [json.dumps(value), self._token], )
async def on_ready(self): """Execute on bot initialization with the Discord API.""" log.info( f"Instance started as {self.user} ({self.pk_member_id}). Initializing..." ) state = await self.check_for_invalid_states() if state == 1: log.warning( f"Failed to start {self.user} (`{self.pk_member_id}`) because main user left. Instance has been suspended." ) await self.close() return # Update Member Name self.member_name: str = self.__member_name if self.__display_name: self.display_name: str = self.__display_name else: self.display_name: str = self.__member_name # Update Username await self.user.edit(username=self.member_name) # Update Roles await self.update_default_roles() # Update Avatar self.pk_avatar_url: str = self.__pk_avatar_url # Update Proxy Tags self.pk_proxy_tags = self.__pk_proxy_tags # Update Nickname in Guilds await self.push_nickname_updates() # Update Presence await self.change_presence(activity=discord.Activity( name=f"{self.get_user(self.main_user_account_id)}", type=discord.ActivityType.listening, )) # Update Self ID in Database with conn: log.debug( f"{self.user} ({self.pk_member_id}): Updating Self Account ID: {self.user.id}" ) c.execute( "UPDATE members SET member_account_id = ? WHERE pk_member_id = ?", [self.user.id, self.pk_member_id], ) log.info(f"{self.user} ({self.pk_member_id}): Initialization complete") self.initialized = True
async def system(self, ctx: commands.context, member: discord.Member): log.debug(f"Listing members for {member.display_name}...") c.execute( "SELECT * FROM members WHERE discord_account_id == ?", [member.id], ) member_list = c.fetchall() embed = discord.Embed(title=f"Members of System") embed.set_author(name=f"{member} ({member.id})", icon_url=member.avatar_url) await self.send_member_list(ctx, embed, member_list)
def display_name(self, value: str): """ Requires calling the "update" method to push to Discord """ self._display_name = value with conn: log.debug( f"{self.user} ({self.pk_member_id}): Updating Display Name") c.execute( "UPDATE members SET display_name = ? WHERE token = ?", [value, self._token], )
def pk_avatar_url(self, value: str): """ Requires calling the "update" method to push to Discord """ self._pk_avatar_url = value with conn: log.debug( f"{self.user} ({self.pk_member_id}): Updating avatar URL to {value}" ) c.execute( "UPDATE members SET pk_avatar_url = ? WHERE token = ?", [value, self._token], )
async def list(self, ctx: commands.context): """ list: Shows all active Polyphony members sorted by main account :param ctx: Discord Context """ if ctx.invoked_subcommand is not None: return log.debug("Listing active members...") c.execute("SELECT * FROM members WHERE member_enabled == 1") member_list = c.fetchall() embed = discord.Embed(title="Active Members") await send_member_list(ctx, embed, member_list)
def member_name(self, value: str): log.debug( f"{self.user} ({self.pk_member_id}): Username updating to p.{value}" ) self._member_name = f"p.{value}" self.user.name = f"p.{value}" with conn: log.debug( f"{self.user} ({self.pk_member_id}): Updating Member Name") c.execute( "UPDATE members SET member_name = ? WHERE token = ?", [value, self._token], )
async def whoarewe(self, ctx: commands.context): """ List members of system belonging to user who executes command :param ctx: Discord Context """ log.debug(f"Listing members for {ctx.author.display_name}...") c.execute( "SELECT * FROM members WHERE main_account_id == ?", [ctx.author.id], ) member_list = c.fetchall() embed = discord.Embed(title=f"Members of System") embed.set_author(name=f"{ctx.author}", icon_url=ctx.author.avatar_url) await send_member_list(ctx, embed, member_list, whoarewe=True)
async def edit( self, ctx: commands.context, message: Optional[discord.Message] = None, *, content: str, ): """ edit (message id) [message]: Edits the last message or message with ID :param ctx: Discord Context :param message: (optional) ID of message :param content: Message Content """ await ctx.message.delete() if message is not None: log.debug( f"Editing message {message.id} by {message.author} for {ctx.author}" ) c.execute( "SELECT * FROM members WHERE discord_account_id == ? AND member_account_id == ?", [ctx.author.id, message.author.id], ) if c.fetchone(): for instance in instances: if instance.user.id == message.author.id: message = await instance.get_channel( message.channel.id).fetch_message(message.id) await message.edit(content=content) break else: log.debug(f"Editing last Polyphony message for {ctx.author}") c.execute( "SELECT * FROM members WHERE discord_account_id == ?", [ctx.author.id], ) member_ids = [ member["member_account_id"] for member in c.fetchall() ] async for message in ctx.channel.history(): if message.author.id in member_ids: for instance in instances: if instance.user.id == message.author.id: message = await instance.get_channel( message.channel.id).fetch_message(message.id) await message.edit(content=content) break break
async def delete( self, ctx: commands.context, message: Optional[discord.Message] = None, ): """ del (id): Deletes the last message unless a message ID parameter is provided. Can be run multiple times. n max limited by config. :param ctx: Discord Context :param message: ID of message to delete """ await ctx.message.delete() if message is not None: log.debug( f"Deleting message {message.id} by {message.author} for {ctx.author}" ) c.execute( "SELECT * FROM members WHERE discord_account_id == ? AND member_account_id == ?", [ctx.author.id, message.author.id], ) if c.fetchone(): for instance in instances: if instance.user.id == message.author.id: message = await instance.get_channel( message.channel.id).fetch_message(message.id) await message.delete() break else: log.debug(f"Deleting last Polyphony message for {ctx.author}") c.execute( "SELECT * FROM members WHERE discord_account_id == ?", [ctx.author.id], ) member_ids = [ member["member_account_id"] for member in c.fetchall() ] async for message in ctx.channel.history(): if message.author.id in member_ids: for instance in instances: if instance.user.id == message.author.id: message = await instance.get_channel( message.channel.id).fetch_message(message.id) await message.delete() break break
async def check_for_invalid_states(self) -> int: log.debug( f"{self.user} ({self.pk_member_id}): Checking for invalid states..." ) if await self.check_if_main_account_left(): log.warning( f"{self.user} ({self.pk_member_id}): Main user left. Suspending self." ) embed = discord.Embed( title="Main account left", description= f"Main account left for {self.user.mention}\n\n*Instance has been suspended.*", color=discord.Color.red(), ) embed.set_footer( text=f"Main Account ID: {self.main_user_account_id}") await send_to_log_channel(embed=embed) from polyphony.helpers.instances import instances for i, instance in enumerate(instances): if instance.user.id == self.user.id: await instance.close() with conn: c.execute( "UPDATE members SET member_enabled = 0 WHERE token = ?", [instance.get_token()], ) del instances[i] return 1 elif await self.check_if_not_in_guild(): log.debug(f"{self.user} ({self.pk_member_id}) is not in the guild") from polyphony.bot import bot embed = discord.Embed( title="Member started but is not in server", description= f"[Invite to Server]({discord.utils.oauth_url(self.user.id, permissions=discord.Permissions(DEFAULT_INSTANCE_PERMS), guild=bot.get_guild(GUILD_ID))})", color=discord.Color.red(), ) await send_to_log_channel(embed=embed) return 2 return 0
async def whois(self, ctx: commands.context, system_member: discord.Member): c.execute("SELECT * FROM members WHERE member_account_id == ?", [system_member.id]) member = c.fetchone() embed = discord.Embed( description= f"{system_member.mention} is part of the {self.bot.get_user(member['discord_account_id']).mention} system", ) embed.add_field(name="User ID", value=self.bot.get_user( member["member_account_id"]).id) embed.add_field( name="System Owner ID", value=self.bot.get_user(member["discord_account_id"]).id, ) embed.set_thumbnail( url=self.bot.get_user(member["member_Account_id"]).avatar_url) await ctx.channel.send(embed=embed)
async def whois(self, ctx: commands.context, system_member: discord.Member): c.execute("SELECT * FROM members WHERE id == ?", [system_member.id]) member = c.fetchone() try: embed = discord.Embed( description= f"{system_member.mention} is part of the {self.bot.get_user(member['main_account_id']).mention} system", ) except AttributeError: embed = discord.Embed( description= f":x: It appears the user for {system_member.mention} has left the server.", ) embed.add_field(name="User ID", value=member["id"]) embed.add_field( name="System Owner ID", value=member["main_account_id"], ) embed.set_thumbnail(url=self.bot.get_user(member["id"]).avatar_url) await ctx.channel.send(embed=embed)
async def slots(self, ctx: commands.context): """ Show number of slots available :param ctx: Discord Context """ await ctx.message.delete() c.execute("SELECT * FROM tokens WHERE used = 0") slots = c.fetchall() if 2 > len(slots) >= 1: embed = discord.Embed(title=f"There is 1 slot available.", color=discord.Color.green()) elif len(slots) > 1: embed = discord.Embed( title=f"There are {len(slots)} slots available", color=discord.Color.green(), ) else: embed = discord.Embed( title=f"Sorry, there are currently no slots available", description="Contact a moderator", ) await ctx.channel.send(embed=embed)
async def register( self, ctx: commands.context, pluralkit_member_id: str, account: discord.Member, ): """ Creates a new Polyphony member instance :param ctx: Discord Context :param pluralkit_member_id: PluralKit system or member id :param account: Main Account to be extended from """ log.debug("Registering new member...") logger = LogMessage(ctx, title="Registering...") await logger.init() instance = None async with ctx.channel.typing(): await logger.log("Fetching member from PluralKit...") member = await pk_get_member(pluralkit_member_id) # Member exists if member is not None: system_names = [f"{member['name']} (`{member['id']}`)"] await logger.log( f"Fetched member -> {member['name']} (`{member['id']}`)") tokens = get_unused_tokens() # Fail: No Slots Available if len(tokens) == 0: logger.title = "Error Registering: No Slots Available" logger.color = discord.Color.red() await logger.log( f"No tokens in queue. Run `{self.bot.command_prefix}tokens` for information on how to add more." ) return # Confirm add confirmation = BotConfirmation(ctx, discord.Color.blue()) await confirmation.confirm( f"Create member for {account} with member {', '.join(system_names)}?" ) if confirmation.confirmed: await confirmation.message.delete() await logger.log("Adding to database...") else: await confirmation.message.delete() logger.title = "Extend Cancelled" logger.color = discord.Color.red() await logger.log("Registration cancelled by user") return # Get a token and update as used bot_token = tokens[0] update_token_as_used(bot_token["token"]) # Insert new user into users database if get_user(account.id) is None: await logger.log( f"{account.mention} is a new user! Registering them with Polyphony" ) insert_user(account.id) # Insert member unless already registered if get_member(pluralkit_member_id) is None: insert_member( bot_token["token"], member["id"], account.id, 0, member["name"], member["display_name"], member["avatar_url"], member["proxy_tags"][0], member["keep_proxy"], member_enabled=True, ) # Fail: Member Already Registered else: logger.title = "Member Already Registered with Polyphony" logger.color = discord.Color.light_grey() await logger.log( f"Member ID `{pluralkit_member_id}` was already registered with Polyphony" ) return await logger.log("Creating member instance...") instance = create_member_instance(get_member(member["id"])) # Fail: Invalid ID else: logger.title = "Error Registering: Member ID invalid" logger.color = discord.Color.red() await logger.log( f"Member ID `{pluralkit_member_id}` was not found") return # Success State logger.title = f"Registration of {member['name']} Successful" logger.color = discord.Color.green() c.execute("SELECT * FROM tokens WHERE used = 0") slots = c.fetchall() await logger.log(f"There are now {len(slots)} slots available") await logger.log(f"\nUser is {instance.user.mention}") log.info("New member instance extended and activated")
async def all(self, ctx: commands.context): log.debug("Listing all members...") c.execute("SELECT * FROM members") member_list = c.fetchall() embed = discord.Embed(title="All Members") await self.send_member_list(ctx, embed, member_list)
async def rolesync(self, ctx: commands.context, system_member: discord.Member): """ Sync current roles to system member until typing `done` :param system_member: System member to sync roles with :param ctx: Discord Context """ if any([ role.name in DISABLE_ROLESYNC_ROLES for role in ctx.message.author.roles ]): # Don't execute if has role that disables rolesync return c.execute( "SELECT * FROM members WHERE main_account_id == ? AND id == ?", [ctx.author.id, system_member.id], ) if c.fetchone(): # Get User's Roles user_roles = [] for role in ctx.author.roles[1:]: if role.name not in ALWAYS_SYNC_ROLES and not role.managed: user_roles.append(role) # Get Member's Roles member_roles = [] for role in system_member.roles[1:]: if role.name not in NEVER_SYNC_ROLES: member_roles.append(role) embed = discord.Embed( title=":hourglass: Syncing roles...", description= f"Assign yourself the roles you want for {system_member.mention} and then type `done`", color=discord.Color.orange(), ) saved_roles_str = " ".join( [role.mention for role in ctx.author.roles[1:]]) embed.add_field( name= f":file_folder: __{ctx.author.display_name}__'s Roles *(saved)*", value=saved_roles_str if len(saved_roles_str) < 1024 else ":hushed: Too many to show" or "None", ) embed_member_original_roles = " ".join( [role.mention for role in system_member.roles[1:]]) embed.add_field( name=f"__{system_member.display_name}__'s Original Roles", value=embed_member_original_roles if len(embed_member_original_roles) else ":hushed: Too many to show" or "None", ) embed.set_footer( text= "Will timeout in 5 minutes. Changes may take a moment to update." ) embed.set_author( name=system_member.display_name, icon_url=system_member.avatar_url, ) instructions = await ctx.channel.send(ctx.author.mention, embed=embed) loading_embed = discord.Embed( title=":hourglass: *Hold on while I update your roles...*", color=discord.Color.orange(), ) loading = await ctx.channel.send(embed=loading_embed) # Remove user's roles and give member's roles async with ctx.channel.typing(): await ctx.author.remove_roles(*user_roles) await ctx.author.add_roles(*member_roles) loading_embed = discord.Embed( title="Type `done` to sync your roles.", color=discord.Color.green()) await loading.edit(embed=loading_embed) # Wait for "done" try: await self.bot.wait_for( "message", check=lambda message: message.author == ctx.author and message.content.lower() == "done", timeout=60 * 5, # 5 mins ) loading_embed = discord.Embed( title=":hourglass: *Hold on while I sync and update...*", color=discord.Color.orange(), ) await loading.edit(embed=loading_embed) # On done, add new roles to member, remove new roles from user, and old roles to user async with ctx.channel.typing(): new_roles = [role for role in ctx.author.roles[1:]] roles_to_remove = [] for role in new_roles: if role.name not in ALWAYS_SYNC_ROLES: roles_to_remove.append(role) # Remove all roles from member and main user await asyncio.gather( system_member.remove_roles(*member_roles), ctx.author.remove_roles(*roles_to_remove), ) # Add new roles to member and restore user roles await asyncio.gather( system_member.add_roles(*new_roles), ctx.author.add_roles(*user_roles), ) embed = discord.Embed( title=":white_check_mark: Role Sync Complete", description= f"Finished syncing roles from {ctx.author.mention} to {system_member.mention}\n{ctx.author.mention}'s original roles have been restored", color=discord.Color.green(), ) embed.add_field( name=f"__{system_member.display_name}__'s Old Roles", value=embed_member_original_roles if len(embed_member_original_roles) < 1024 else ":hushed: Too many to show" or "None", ) new_roles_str = " ".join( [role.mention for role in system_member.roles[1:]]) embed.add_field( name=f"__{system_member.display_name}__'s New Roles", value=new_roles_str if len(new_roles_str) < 1024 else ":hushed: Too many to show" or "None", ) embed.set_author( name=system_member.display_name, icon_url=system_member.avatar_url, ) await instructions.edit(content="", embed=embed) await loading.delete() except asyncio.TimeoutError: unsynced_roles = system_member.roles[1:] roles_to_remove = [] for role in system_member.roles[1:]: if role.name not in ALWAYS_SYNC_ROLES: roles_to_remove.append(role) loading_embed = discord.Embed( title="*Timed out. Hold on while I restore your roles...*", color=discord.Color.orange(), ) await loading.edit(embed=loading_embed) async with ctx.channel.typing(): await system_member.add_roles(*member_roles) await ctx.author.remove_roles(*roles_to_remove) await ctx.author.add_roles(*user_roles) embed = discord.Embed( title="Role Sync Timed Out", description= f"Restored original roles for {system_member.mention}", color=discord.Color.dark_orange(), ) embed.add_field( name=f"`{system_member.display_name}`'s Restored Roles", value=embed_member_original_roles if len(embed_member_original_roles) < 1024 else ":hushed: Too many to show" or "None", ) unsynced_roles_str = " ".join( [role.mention for role in unsynced_roles]) embed.add_field( name= f"`{system_member.display_name}`'s Unsaved Roles Due to Timeout", value=unsynced_roles_str if len(unsynced_roles_str) < 1024 else ":hushed: Too many to show" or "None", ) embed.set_footer( text= 'Role sync times out after 5 minutes. Type "done" next time to save changes.' ) embed.set_author( name=system_member.display_name, icon_url=system_member.avatar_url, ) await instructions.edit(content="", embed=embed) await loading.delete()
async def tokens(self, ctx: commands.context, *tokens: str): """ Add tokens to queue :param ctx: Discord Context :param tokens: List of tokens """ async def session(self, author: discord.Member): self.token_session.append(author) await asyncio.sleep(300) self.token_session.remove(author) if (ctx.channel.type is discord.ChannelType.private and ctx.message.author in self.token_session): await ctx.send("Adding tokens...") for index, token in enumerate(tokens): logger = LogMessage(ctx, title=f"Adding token #{index+1}...") await logger.init() # Check token await logger.log(f"Checking token #{index+1}...") all_tokens = conn.execute("SELECT * FROM tokens").fetchall() chk = False token_client = decode_token(token) for chk_token in all_tokens: if decode_token(str(chk_token["token"])) == token_client: chk = True check_result, client_id = await check_token(token) if chk: logger.title = f"Token #{index + 1} Client ID already in database" logger.color = discord.Color.red() await logger.log("Client ID already exists in database") elif not check_result: logger.title = f"Token #{index+1} Invalid" logger.color = discord.Color.red() await logger.log("Bot token is invalid") else: await logger.log("Token valid") if (conn.execute("SELECT * FROM tokens WHERE token = ?", [token]).fetchone() is None): conn.execute("INSERT INTO tokens VALUES(?, ?)", [token, False]) conn.commit() logger.title = f"Bot token #{index+1} added" logger.color = discord.Color.green() c.execute("SELECT * FROM tokens WHERE used = 0") slots = c.fetchall() from polyphony.bot import bot await logger.send( f"[Invite to Server]({discord.utils.oauth_url(client_id, permissions=discord.Permissions(DEFAULT_INSTANCE_PERMS), guild=bot.get_guild(GUILD_ID))})\n\n**Client ID:** {client_id}\nThere are now {len(slots)} slot(s) available" ) log.info( f"New token added by {ctx.author} (There are now {len(slots)} slots)" ) else: logger.title = f"Token #{index+1} already in database" logger.color = discord.Color.orange() await logger.log("Bot token already in database") elif ctx.channel.type is not discord.ChannelType.private: await ctx.message.delete() if any(role.name in MODERATOR_ROLES for role in ctx.message.author.roles) or ctx.bot.is_owner( ctx.author): try: await ctx.message.author.send( f"Token mode enabled for 5 minutes. Add tokens with `{self.bot.command_prefix}tokens [token] (more tokens...)` right here.\n\n*Don't paste a bot token in a server*" ) except discord.errors.Forbidden: await ctx.send("Enable server DMs to use token command", delete_after=10.0) await session(self, ctx.message.author) elif any(role.name in MODERATOR_ROLES for role in ctx.message.author.roles) or ctx.bot.is_owner( ctx.author): await ctx.channel.send( f"To add tokens, execute `{self.bot.command_prefix}tokens` as a moderator on a server **WITHOUT A BOT TOKEN**. Then in DMs, use `{self.bot.command_prefix}tokens [token] (more tokens...)`\n\n*Seriously don't paste a bot token in a server*", delete_after=10.0, )
async def suspended(self, ctx: commands.context): log.debug("Listing suspended members...") c.execute("SELECT * FROM members WHERE member_enabled == 0") member_list = c.fetchall() embed = discord.Embed(title="Suspended Members") await self.send_member_list(ctx, embed, member_list)