async def start_embed(bot: commands.Bot, channel: discord.TextChannel, user: discord.User, delete_message: bool = False) -> \ typing.Optional[typing.Tuple[discord.CategoryChannel, discord.Guild]]: try: categories = await bot.db_conn.fetch( "SELECT category_name, emote_id \ FROM modmail.categories \ WHERE \ active=true") embed = common_embed( "Category Selector", "Please react with the corresponding emote for your desired category" ) embed.add_field(name="Available categories: ", value="\n".join([ f"{row[0].capitalize()} = {row[1]}" for row in categories ])) msg = await channel.send(embed=embed) for row in categories: await msg.add_reaction(row[1]) reaction, _ = await bot.wait_for( "reaction_add", check=lambda react, react_user: react.message.id == msg.id and react_user == user, timeout=120) db_category = await bot.db_conn.fetchrow( "SELECT category_id, guild_id \ FROM modmail.categories \ WHERE \ emote_id=$1 AND \ active=true", reaction.emoji) if not db_category: await msg.edit(embed=common_embed( "Invalid Reaction", "What the heck, you should be using the existing emotes not new " "ones. Please restart the process and try again")) return except asyncio.TimeoutError: await channel.send( "You didn't answer in time, please restart the process by sending your message " "again") return else: category = bot.get_channel(db_category[0]) guild = bot.get_guild(db_category[1]) if delete_message: await asyncio.sleep(2) await msg.delete() return category, guild
async def is_muted(self, ctx, user: typing.Union[discord.Member, str]) -> None: if isinstance(user, str): try: user = await self.bot.fetch_user(int(user)) except (commands.CommandInvokeError, ValueError): await ctx.send(embed=common_embed("Is muted", "Unable to locate user, please check if the id is correct")) return result = await self.db_conn.fetchrow("SELECT active, muted_by, muted_at, muted_until \ FROM modmail.muted \ WHERE \ user_id = $1", user.id) if result: muted_by = await self.bot.fetch_user(result[1]) await ctx.send( embed=discord.Embed( color=discord.Color.red(), description=f"```{user}({user.id})\n\n" f"Muted: {'✓' if is_muted else '✗'}\n" f"Muted by: {muted_by}({result[1]})\n" f"Muted at: {result[2].strftime('%d/%m/%Y, %H:%M')}\n" f"Muted until: {result[3].strftime('%d/%m/%Y, %H:%M')}\n```")) else: await ctx.send(embed=common_embed("Is muted", "User is not muted and is not in database"))
async def ping(self, ctx): embed = common_embed( "", f"Pong! :ping_pong:\n*Bot latency:* {round(self.bot.latency * 1000, 3)}ms" ) t1 = time.perf_counter() msg = await ctx.send(embed=embed) t2 = time.perf_counter() embed = common_embed( "", f"Pong! :ping_pong:\n*Bot latency:* {round(self.bot.latency * 1000, 3)}ms\n" f"*Actual response time:* {round((t2 - t1) * 1000, 3)}ms") await msg.edit(embed=embed)
async def mute(self, ctx, user: typing.Union[discord.Member, str], end_time: typing.Optional[str] = None) -> None: if isinstance(user, str): try: user = await self.bot.fetch_user(int(user)) except (discord.ext.commands.CommandInvokeError, ValueError): await ctx.send(embed=common_embed("Mute", "Unable to locate user, please check if the id is correct")) return if await is_muted(user.id, self.db_conn): await ctx.send(embed=common_embed("Mute", 'User already muted')) return try: msg = await ctx.send(embed=common_embed("Mute", f"Muting user {user.name}...")) db_user = await self.db_conn.fetch("SELECT * \ FROM modmail.muted \ WHERE \ user_id = $1", user.id) if end_time: time_class = Time() time = time_class.add_text_to_time(end_time, datetime.datetime.now(pytz.utc)) if db_user: await self.db_conn.execute("UPDATE modmail.muted \ SET active = true, muted_by = $1, muted_until = $2 \ WHERE \ user_id = $3", ctx.author.id, time, user.id) else: await self.db_conn.execute("INSERT INTO modmail.muted (user_id, muted_by, muted_until, active) \ VALUES ($1, $2, $3, true)", user.id, ctx.author.id, time) else: if db_user: await self.db_conn.execute("UPDATE modmail.muted \ SET active = true, muted_by = $1 \ WHERE \ user_id = $2", ctx.author.id, user.id) else: await self.db_conn.execute("INSERT INTO modmail.muted (user_id, muted_by, active) \ VALUES ($1, $2, true)", user.id, ctx.author.id) finally: await msg.edit(embed=common_embed("Mute", f"Muted user {user}({user.id})")) await user.send(embed=common_embed("Muted", f"Due to misuse of our modmail bot, you were muted " f"for {end_time}. Any messages you send here will not be " f"received by the moderator team."))
async def query(self, ctx, fetch: str, *, arg: str) -> None: if fetch == "all": i = await self.db_conn.fetch(arg) description = "" for ret in i: description += str(ret) + "\n" if len(description) > 850: await ctx.send(description) description = "" await ctx.send(description) elif fetch == "one": i = await self.db_conn.fetchrow(arg) value = str(i[0]) await ctx.send(str(value)) elif fetch == "commit": await self.db_conn.execute(arg) await ctx.send( embed=common_embed("Query", f"`{arg}` Committed the query."))
async def notes( self, ctx, user: typing.Optional[typing.Union[discord.Member, str]]) -> None: if user is None: result = await self.db_conn.fetchrow( "SELECT user_id \ FROM modmail.conversations \ WHERE \ channel_id = $1", ctx.channel.id) if not result: await ctx.send(embed=common_embed( title="Not Found", description= "Unable to locate modmail thread, please specify the id")) return user = await self.bot.fetch_user(result[0]) elif isinstance(user, str): try: user = await self.bot.fetch_user(int(user)) except (commands.CommandInvokeError, ValueError, discord.NotFound): await ctx.send( embed=common_embed(title="Not Found", description="Unable to locate user, " "please check if the id is correct")) return db_notes = await self.db_conn.fetch( "SELECT note_id, user_id, made_by_id, note \ FROM modmail.notes \ WHERE \ user_id = $1 \ ORDER BY note_id", user.id) embeds = list() for row in db_notes: user = await self.bot.fetch_user(row[1]) created_by = await self.bot.fetch_user(row[2]) embeds.append( common_embed( f"ID: {row[0]}\n\n", f"```User: {user}\n" f"Created By: {created_by}\n" f"Note: '{str(row[3])}'\n```")) await disputils.BotEmbedPaginator(ctx, embeds).run()
async def unmute(self, ctx, user: typing.Union[discord.Member, str]) -> None: if isinstance(user, str): try: user = await self.bot.fetch_user(int(user)) except (discord.ext.commands.CommandInvokeError, ValueError): await ctx.send(embed=common_embed("Unmute", "Unable to locate user, please check if the id is correct")) return if not await is_muted(user.id, self.db_conn): await ctx.send(embed=common_embed("Unmute", 'User is not muted')) return else: msg = await ctx.send(embed=common_embed("Unmute", f"Unmuting user {user}...")) await self.db_conn.execute("UPDATE modmail.muted \ SET active = false \ WHERE \ user_id = $1", user.id) await msg.edit(embed=common_embed("Unmute", f'Unmuted user {user.id}'))
async def dm_delete_listener(self, message: discord.Message) -> None: if message.guild is None: conv = await self.db_conn.fetchrow("SELECT conversation_id, channel_id, message_id \ FROM modmail.conversations \ WHERE \ user_id=$1 AND \ active=true", message.author.id) if conv: db_msg = await self.db_conn.fetchrow("SELECT other_side_message_id, message \ FROM modmail.messages \ WHERE \ message_id=$1 AND \ conversation_id=$2", message.id, conv[0]) thread_channel = await self.bot.fetch_channel(conv[1]) thread_msg = await thread_channel.fetch_message(db_msg[0]) thread_embed = common_embed("", db_msg[1], color=self.red) thread_embed.set_author(name=message.author, icon_url=message.author.avatar_url) thread_embed.set_footer(text=f"Message ID: {message.id} (deleted)") await thread_msg.edit(embed=thread_embed) usr_msg = await message.author.dm_channel.fetch_message(conv[2]) usr_embed = common_embed("Message deleted", f"> {message.content}", color=self.red) usr_embed.set_author(name=message.author, icon_url=message.author.avatar_url) usr_embed.set_footer(text=f"Message ID: {message.id}") await usr_msg.edit(embed=usr_embed) await self.db_conn.execute("UPDATE modmail.messages \ SET deleted=true \ WHERE \ message_id=$1", message.id) await self.db_conn.execute("UPDATE modmail.all_messages_attachments \ SET deleted=true \ WHERE \ message_id=$1", message.id)
async def deletenote(self, ctx, note_id: int): results = await self.db_conn.fetchrow( "SELECT made_by_id \ FROM modmail.notes \ WHERE \ note_id = $1", note_id) if results[0] != ctx.author.id: await ctx.send(embed=common_embed( title="Not found", description= "You do not have access to delete this note, or the note " "doesn't exist")) return await self.db_conn.execute( "DELETE FROM modmail.notes \ WHERE \ note_id = $1", note_id) await ctx.send(embed=common_embed( title="Success", description=f'Successfully deleted note with id: `{note_id}`'))
async def member_leave_listener(self, member: discord.Member) -> None: channel_id = await self.member_has_conversation(member=member) if (channel_id != []) and (channel_id is not None) and (len(channel_id) > 0): if (channel_id[0] is not None) and (channel_id[0] is not "") and (len(channel_id[0]) > 0): if (channel_id[0][0] is not "") and (channel_id[0][0] is not None): ch = await self.bot.fetch_channel(channel_id[0][0]) await ch.send(embed=common_embed("User left the server.", "User left the server."))
async def reply(bot: commands.Bot, ctx: commands.Context, db_conn: asyncpg.pool.Pool, user_id: int, message: str, conv_id: int, anon: bool = False, attachments: list = {}) -> None: user = bot.get_user(user_id) usr_embed = common_embed("", message, color=yellow) if anon: usr_embed.set_author(name="Moderator") else: usr_embed.set_author(name=ctx.author, icon_url=ctx.author.avatar_url) usr_embed.set_footer(text=ctx.author.roles[-1].name) if attachments: usr_embed.add_field(name=f"File upload ({len(attachments)})", value='\n'.join( [f"[{attachment.filename}]({attachment.url})" for attachment in attachments])) usr_msg = await user.send(embed=usr_embed) thread_embed = common_embed("", message, color=green) thread_embed.set_author(name=ctx.author, icon_url=ctx.author.avatar_url) thread_embed.set_footer(text=ctx.author.roles[-1].name if not anon else "anonymous reply") if attachments: thread_embed.add_field(name=f"File upload ({len(attachments)})", value='\n'.join( [f"[{attachment.filename}]({attachment.url})" for attachment in attachments])) mod_msg = await ctx.send(embed=thread_embed) await db_conn.execute("INSERT INTO modmail.messages \ (message_id, message, author_id, conversation_id, other_side_message_id, made_by_mod) \ VALUES ($1, $2, $3, $4, $5, true)", mod_msg.id, message, ctx.author.id, conv_id, usr_msg.id) await db_conn.execute("INSERT INTO modmail.all_messages_attachments \ (message_id, message, author_id, conversation_id, made_by_mod, internal) \ VALUES ($1, $2, $3, $4, true, true)", mod_msg.id, message, ctx.author.id, conv_id) await ctx.message.delete()
async def confirmation(bot, ctx, title: str, confirmation_msg_input: str, command: str) -> bool: confirmation_msg = await ctx.send( embed=common_embed(title, confirmation_msg_input)) await confirmation_msg.add_reaction("✅") await confirmation_msg.add_reaction("❌") try: def is_category_emoji(react, user): return react.message.id == confirmation_msg.id and user == ctx.message.author reaction, _ = await bot.wait_for('reaction_add', check=is_category_emoji, timeout=30) await confirmation_msg.add_reaction(reaction.emoji) if reaction.emoji not in ["✅", "❌"]: await confirmation_msg.edit(embed=common_embed( title, "Shaking my f*****g head. Please start over and don't " "be a fool.")) return False elif reaction.emoji == "❌": await confirmation_msg.edit(embed=common_embed( title, "The request is cancelled. " f"Type `!help {command}` to start over.")) return False elif reaction.emoji == "✅": await confirmation_msg.edit(embed=common_embed( title, f"The {title.lower()} request is confirmed.")) return True except asyncio.TimeoutError: await confirmation_msg.edit(embed=common_embed( title, "Looks like you waited too long. Please restart the process.")) return False
async def editnote(self, ctx, note_id: int, *, new_text: str) -> None: results = await self.db_conn.fetchrow( "SELECT made_by_id \ FROM modmail.notes \ WHERE \ note_id = $1", note_id) if results[0] != ctx.author.id: await ctx.send( common_embed( title="Missing Permissions", description= "You do not have access to edit this note, or the note doesn't " "exist")) return await self.db_conn.execute( "UPDATE modmail.notes \ SET note = $1 \ WHERE \ note_id = $2", new_text, note_id) await ctx.send(embed=common_embed( title='Success', description=f"Updated `{note_id}` to \"{new_text}\""))
async def addnote(self, ctx, *, note: str) -> None: conv = await self.db_conn.fetchrow( "SELECT conversation_id, user_id \ FROM modmail.conversations \ WHERE \ channel_id = $1", ctx.channel.id) if not conv: await ctx.send(embed=common_embed( title="Missing Permissions", description="You aren't in a valid modmail channel, if this is " "incorrect please contact my makers")) return await self.db_conn.execute( "INSERT INTO modmail.notes \ (conversation_id, user_id, made_by_id, note) \ VALUES ($1, $2, $3, $4)", conv[0], conv[1], ctx.author.id, note) await ctx.send(embed=common_embed( title="Success", description=f"Inserted the note for user id: {conv[1]}"))
async def deny(self, ctx, *, arg: str) -> None: for user_id in arg.split(" "): user_id = user_id[:-1] if user_id[:3] == "<@!": user_id = user_id[3:] else: user_id = user_id[2:] await ctx.channel.set_permissions(self.bot.get_user(int(user_id)), read_messages=False, send_messages=False, read_message_history=False) deny_msg = "Removed " + self.bot.get_user( int(user_id)).mention + " from " + ctx.channel.mention await ctx.send(embed=common_embed("Deny", deny_msg))
async def verify_categories(self) -> None: results = await self.db_conn.fetch( "SELECT category_id, category_name, guild_id \ FROM modmail.categories \ WHERE \ active=true") owners = [ await self.bot.fetch_user(owner) for owner in json.loads(self.conf.get('global', 'owners')) ] for row in results: guild = await self.bot.fetch_guild(row[2]) admin_role = guild.get_role( self.conf.get('global', 'admin_role_id')) chnl = self.bot.get_channel(self.chnl_id) category = self.bot.get_channel(row[0]) if category is None: unsync_msg = f"Category ID: `{row[0]}` is not correctly synced.\n\n **Category '{row[1]}' does " \ f"not exist or isn't accessible by the bot.\n\n** " set_inactive = await self.set_category_inactive(row=row) if set_inactive: unsync_msg += f"I set category with category ID: {row[0]} to inactive. Please fix this issue " \ f"and set the category to active. " elif category.name.lower() != row[1].lower(): unsync_msg = f"Category ID: `{row[0]}` is not correctly synced.\n\n **Category is named '{row[1]}'" \ f" in database but is actually called '{category.name}'\n\n** " set_inactive = await self.set_category_inactive(row=row) if set_inactive: unsync_msg += f"I set category with category ID: {row[0]} to inactive. Please fix this issue " \ f"and set the category to active. " else: continue embed = common_embed("Categories not correctly synced!", unsync_msg) embed.set_image(url="https://i.imgur.com/b8y71CJ.gif") await chnl.send(embed=embed) await chnl.send(" ".join([owner.mention for owner in owners]) + admin_role.mention)
async def allow(self, ctx, *, arg: str) -> None: for user_id in arg.split(" "): if user_id[:2] == "<#": pass else: user_id = user_id[:-1] if user_id[:3] == "<@!" or user_id[:2] == "<@": if user_id[:3] == "<@!": user_id = user_id[3:] elif user_id[:2] == "<@": user_id = user_id[2:] await ctx.channel.set_permissions( self.bot.get_user(int(user_id)), read_messages=True, send_messages=True, read_message_history=True) allow_msg = "Added " + self.bot.get_user( int(user_id)).mention + " to " + ctx.channel.mention await ctx.send(embed=common_embed("Allow", allow_msg))
async def note(self, ctx, note_id: int) -> None: results = await self.db_conn.fetchrow( "SELECT note_id, user_id, made_by_id, note \ FROM modmail.notes \ WHERE \ note_id = $1", note_id) if not results: await ctx.send(embed=common_embed( title="Not Found", description= "Unable to locate note, please check the id and try again")) user = await self.bot.fetch_user(results[1]) created_by = await self.bot.fetch_user(results[2]) embed = discord.Embed( color=discord.Color.red(), description= f"```ID: {results[0]}\n\nUser: {user}\nCreated By: {created_by}\n" f"Note: '{str(results[3])}'\n```") await ctx.send(embed=embed)
async def all(self, ctx): msg = await ctx.send(embed=common_embed("Muted all", "Getting all users...")) results = await self.db_conn.fetch("SELECT user_id, muted_by, muted_at, muted_until, active \ FROM modmail.muted") paginator = commands.Paginator() for row in results: user = await self.bot.fetch_user(row[0]) muted_by = await self.bot.fetch_user(row[1]) paginator.add_line(f"{user}({user.id})\n\n" f"Muted: {'✓' if bool(row[4]) else '✗'}\n" f"Muted by: {muted_by}({row[1]})\n" f"Muted at: {row[2].strftime('%d/%m/%Y, %H:%M')}\n" f"Muted until: {row[3].strftime('%d/%m/%Y, %H:%M')}\n" f"--------------------------------\n") await msg.delete() for page in paginator.pages: await ctx.send(embed=discord.Embed(color=discord.Color.red(), description=page))
async def reloadcogs(self, ctx) -> None: for cog in os.listdir('./cogs'): if cog.endswith('.py') and not cog.startswith('_'): try: self.bot.reload_extension(f"cogs.{cog.replace('.py', '')}") except Exception as err: print(f"{cog} can't be loaded") raise err for task in os.listdir('./tasks'): if task.endswith('.py') and not task.startswith('_'): try: self.bot.reload_extension( f"tasks.{task.replace('.py', '')}") except Exception as err: print(f"{task} can't be loaded") raise err await ctx.send(embed=common_embed( "Reload cogs", f"{ctx.author.mention}, all cogs have been reloaded."))
async def muted(self, ctx) -> None: msg = await ctx.send(embed=common_embed("Muted", "Getting all active users...")) results = await self.db_conn.fetch("SELECT user_id, muted_by, muted_at, muted_until \ FROM modmail.muted \ WHERE \ active = true") paginator = discord.ext.commands.Paginator() try: for row in results: user = await self.bot.fetch_user(row[0]) muted_by = await self.bot.fetch_user(row[1]) paginator.add_line(f"{user}({user.id})\n\n" f"Muted by: {muted_by}({row[1]})\n" f"Muted at: {row[2].strftime('%d/%m/%Y, %H:%M')}\n" f"Muted until: {row[3].strftime('%d/%m/%Y, %H:%M')}\n" f"--------------------------------\n") finally: await msg.delete() for page in paginator.pages: await ctx.send(embed=discord.Embed(color=discord.Color.red(), description=page))
async def dm_message_listener(self, message: discord.Message) -> None: if (message.content.startswith(self.bot.command_prefix)) or (message.author == self.bot.user): return if message.guild is not None: active_channels = await self.db_conn.fetch("SELECT channel_id \ FROM modmail.conversations \ WHERE \ active=true") active_channel_list = [channel[0] for channel in active_channels] if message.channel.id in active_channel_list: conv_id = await self.db_conn.fetchrow("SELECT conversation_id \ FROM modmail.conversations \ WHERE \ channel_id=$1 AND \ active=true", message.channel.id) try: await self.db_conn.execute("INSERT INTO modmail.all_messages_attachments \ (message_id, message, author_id, conversation_id, made_by_mod) \ VALUES ($1, $2, $3, $4, false)", message.id, message.content, message.author.id, conv_id[0]) if message.attachments: attachment_object = await message.attachments[0].read() await self.db_conn.execute("UPDATE modmail.all_messages_attachments \ SET attachment=$1 \ WHERE \ message_id=$2", attachment_object, message.id) except: return return check_muted = await self.db_conn.fetchrow("SELECT active \ FROM modmail.muted \ WHERE \ user_id=$1 AND \ active=true", message.author.id) if check_muted: return conv = await self.db_conn.fetchrow("SELECT conversation_id, channel_id \ FROM modmail.conversations \ WHERE \ user_id=$1 AND \ active=true", message.author.id) if not conv: category, guild = await category_selector.start_embed(self.bot, message.channel, message.author) or ( None, None) if category is None: return channel = await guild.create_text_channel(f"{message.author.name}-{message.author.discriminator}", category=category) await channel.edit(topic=f"{message.author.id}") past_threads = await self.db_conn.fetch("SELECT * \ FROM modmail.conversations \ WHERE \ user_id=$1 AND \ active=false", message.author.id) check = False if int(guild.id) == int(self.bot.conf.get('global', 'main_server_id')): check = True if check: try: user = guild.get_member(message.author.id) created_ago = datetime.datetime.now() - user.created_at joined_ago = datetime.datetime.now() - user.joined_at chnl_embed_msg = f"{user.mention} was created {created_ago.days} days ago, " \ f"joined {joined_ago.days} days ago" except AttributeError: check = False if not check: user = message.author created_ago = datetime.datetime.now() - user.created_at chnl_embed_msg = f"{user.mention} was created {created_ago.days} days ago, " chnl_embed_msg += f" with **{'no' if len(past_threads) == 0 else len(past_threads)}** past threads" chnl_embed = common_embed(f"{message.author.id}", chnl_embed_msg, color=0x7289da) chnl_embed.set_author(name=str(user), icon_url=user.avatar_url) if check: roles = " ".join([role.mention for role in user.roles if not role.is_default()]) else: roles = "" chnl_embed.add_field(name="Roles", value=roles if roles else "No Roles") await channel.send(embed=chnl_embed) thread_embed = common_embed("", message.content, color=self.yellow) thread_embed.set_author(name=message.author, icon_url=message.author.avatar_url) for attachment in message.attachments: thread_embed.add_field(name=f"File upload ({len(message.attachments)})", value=f"[{attachment.filename}]({attachment.url})") thread_embed.set_footer(text=f"Message ID: {message.id}") thread_msg = await channel.send(embed=thread_embed) await self.db_conn.execute("INSERT INTO modmail.conversations \ (creation_date, user_id, active, channel_id, category_id) \ VALUES (now(), $1, true, $2, $3)", message.author.id, channel.id, category.id) conv_id = await self.db_conn.fetchrow("SELECT conversation_id \ FROM modmail.conversations \ WHERE \ channel_id=$1", channel.id) await self.db_conn.execute("INSERT INTO modmail.messages \ (message_id, message, author_id, conversation_id, other_side_message_id, \ made_by_mod) \ VALUES ($1, $2, $3, $4, $5, false)", message.id, message.content, message.author.id, conv_id[0], thread_msg.id) await self.db_conn.execute("INSERT INTO modmail.all_messages_attachments \ (message_id, message, author_id, conversation_id, made_by_mod, internal) \ VALUES ($1, $2, $3, $4, false, true)", message.id, message.content, message.author.id, conv_id[0]) usr_embed = common_embed("Message sent", f"> {message.content} \n\n *if this isn't correct you can change it with " f"{self.bot.command_prefix}edit*", color=self.green) usr_embed.set_author(name=message.author, icon_url=message.author.avatar_url) for attachment in message.attachments: usr_embed.add_field(name=f"File upload ({len(message.attachments)})", value=f"[{attachment.filename}]({attachment.url})") usr_embed.set_footer(text=f"Message ID: {message.id}") await message.channel.send(embed=usr_embed) else: channel = await self.bot.fetch_channel(conv[1]) thread_embed = common_embed("", message.content, color=self.yellow) thread_embed.set_author(name=message.author, icon_url=message.author.avatar_url) for attachment in message.attachments: thread_embed.add_field(name=f"File upload ({len(message.attachments)})", value=f"[{attachment.filename}]({attachment.url})") thread_embed.set_footer(text=f"Message ID: {message.id}") thread_msg = await channel.send(embed=thread_embed) usr_embed = common_embed("Message sent", f"> {message.content}\n\n *if this isn't correct you can change it with " f"{self.bot.command_prefix}edit*", color=self.green) usr_embed.set_author(name=message.author, icon_url=message.author.avatar_url) for attachment in message.attachments: usr_embed.add_field(name=f"File upload ({len(message.attachments)})", value=f"[{attachment.filename}]({attachment.url})") usr_embed.set_footer(text=f"Message ID: {message.id}") await message.channel.send(embed=usr_embed) await self.db_conn.execute("INSERT INTO modmail.messages \ (message_id, message, author_id, conversation_id, other_side_message_id, \ made_by_mod) \ VALUES ($1, $2, $3, $4, $5, false)", message.id, message.content, message.author.id, conv[0], thread_msg.id) await self.db_conn.execute("INSERT INTO modmail.all_messages_attachments \ (message_id, message, author_id, conversation_id, made_by_mod, internal) \ VALUES ($1, $2, $3, $4, false, true)", message.id, message.content, message.author.id, conv[0]) if message.attachments: attachment_object = await message.attachments[0].read() await self.db_conn.execute("UPDATE modmail.all_messages_attachments \ SET attachment=$1 \ WHERE \ message_id=$2", attachment_object, message.id)
async def unloadcog(self, ctx, cog) -> None: self.bot.unload_extension(cog) await ctx.send(embed=common_embed( "Unload cog", f"{ctx.author.mention}, `{cog}` has been unloaded."))
async def columns(self, ctx, table) -> None: result = dict(await self.db_conn.fetchrow(f'SELECT * FROM {table} LIMIT 1')) colnames = str([key for key, value in result.items()]) await ctx.send(embed=common_embed("Columns", str(colnames)))
async def purge(self, ctx, n: typing.Optional[int] = 100) -> None: deleted = await ctx.channel.purge(limit=n) await ctx.send( embed=common_embed("Purge", f"Deleted {len(deleted)} message(s)."))