async def check_channel( self, ctx: Context, channel: Optional[discord.TextChannel]) -> discord.TextChannel: def is_correct(m: discord.Message) -> bool: return m.author == ctx.author if channel is None: await ctx.send("What is the channel?") get_channel = await self.bot.wait_for("message", check=is_correct) get_channel.content channel = await commands.TextChannelConverter().convert( ctx, get_channel.content) assert ctx.guild is not None assert ctx.guild.me is not None assert isinstance(ctx.author, discord.Member) perms = channel.permissions_for(ctx.guild.me) sender_perms = channel.permissions_for(ctx.author) if not perms.view_channel: raise errors.InputContentIncorrect( "I do not have the the `View Messages` permission in that channel!" ) elif not (perms.send_messages and perms.embed_links): raise errors.InputContentIncorrect( "I do not have the the `Send Message` and `Embed Links` permission in that channel!" ) elif not sender_perms.view_channel: raise errors.InputContentIncorrect( "You don't have the `View Messages` permissions in that channel!" ) return channel
async def set_logging_logic( self, guild: discord.Guild, channel_input: Optional[str], ) -> Union[discord.Embed, str]: logging_channel = await LoggingChannel.get_or_none(guild_id=guild.id, logger_type="main") embed = discord.Embed( title="Config updated!", timestamp=datetime.now(timezone.utc), colour=discord.Colour(15653155), ) if channel_input is None: if logging_channel is None: embed.description = "Logging channel not updated! It remains None" else: await logging_channel.delete() embed.description = f"Logging channel updated from <#{logging_channel.channel_id}> to None" return embed else: if channel_input[:2] == "<#": channel_input = channel_input[2:-1] try: channel_id = int(channel_input) channel = guild.get_channel(channel_id) if channel is None: raise errors.InputContentIncorrect( "I could not find that channel! Please try again") except ValueError: raise errors.InputContentIncorrect( "I could not find that channel! Please try again") if not isinstance(channel, discord.TextChannel): raise errors.WebhookChannelNotTextChannel( "That channel is not a text channel! " "Try again with a text channel.") db_channel = await Channel.get_or_create(id=channel.id) if logging_channel is None: original_channel = None logging_channel = LoggingChannel(guild_id=guild.id, channel=db_channel[0], logger_type="main") else: original_channel = logging_channel.channel_id logging_channel.channel = db_channel[0] await logging_channel.save() if original_channel is None: embed.description = f"Logging channel updated to {channel.mention}" else: embed.description = f"Logging channel updated from <#{original_channel}> to {channel.mention}" return embed
async def message_or_error( channel: discord.TextChannel, message_id: Union[int, str]) -> discord.Message: try: return await channel.fetch_message(int(message_id)) except Exception as e: if isinstance(e, discord.NotFound): raise errors.InputContentIncorrect( "I can't find that message!") elif isinstance(e, ValueError): raise errors.InputContentIncorrect( "That is not a message id!") else: raise e
async def set_admin_role_logic( self, guild: discord.Guild, new_role_id: Optional[str]) -> discord.Embed: db_guild = await self.bot.guild_cache.get(guild.id) original_role_id = db_guild.management_role_id original_role = (guild.get_role(original_role_id) if original_role_id is not None else None) if new_role_id is None: await self.bot.guild_cache.update_management_role(guild.id, None) embed = discord.Embed( title="Config updated!", timestamp=datetime.now(timezone.utc), colour=discord.Colour(15653155), ) if original_role is None: embed.description = "Management role has not changed! It remains None" else: embed.description = ( f"Management role updated from {original_role.mention} to None" ) return embed else: if new_role_id[:3] == "<@&": new_role_id = new_role_id[3:-1] if isinstance(new_role_id, str): try: new_role_id = int(new_role_id) # type: ignore except ValueError: raise errors.InputContentIncorrect( "I could not find that role! Please try again") assert isinstance(new_role_id, int) new_role = guild.get_role(new_role_id) if new_role is None: raise errors.InputContentIncorrect( "I could not find that role! Please try again") await self.bot.guild_cache.update_management_role( guild.id, new_role_id) embed = discord.Embed( title="Config updated!", timestamp=datetime.now(timezone.utc), colour=discord.Colour(15653155), ) if original_role is None: embed.description = f"Management role updated to {new_role.mention}" else: embed.description = f"Management role updated from {original_role.mention} to {new_role.mention}" return embed
async def set_prefix_logic(self, guild: discord.Guild, new_prefix: Optional[str]) -> discord.Embed: guild_data = await self.bot.guild_cache.get(guild.id) current_prefix = guild_data.prefix if new_prefix is None: await self.bot.guild_cache.update_prefix(guild.id, self.bot.default_prefix) return discord.Embed( title="Config updated!", description= f"Server prefix updated from `{current_prefix}` to `{self.bot.default_prefix}`", timestamp=datetime.now(timezone.utc), colour=discord.Colour(15653155), ) else: if len(new_prefix) > 1: raise errors.InputContentIncorrect( "Prefix's can only be 1 character long!") else: await self.bot.guild_cache.update_prefix(guild.id, new_prefix) return discord.Embed( title="Config updated!", description= f"Server prefix updated from `{current_prefix}` to `{new_prefix}`", timestamp=datetime.now(timezone.utc), colour=discord.Colour(15653155), )
async def json_edit( self, ctx: Context, channel: Optional[discord.TextChannel] = None, message_id: Optional[int] = None, *, json_content: Optional[str] = None, ) -> None: channel = await self.check_channel(ctx, channel) if channel.guild != ctx.guild: raise errors.DifferentServer() msg = await self.check_message_id(ctx, channel, message_id) if msg.author != ctx.guild.me: raise errors.DifferentAuthor() if len(msg.embeds) == 0: raise errors.InputContentIncorrect( f"That message does not have an embed! Try {self.bot.command_with_prefix(ctx, 'edit')} instead" ) elif len(msg.embeds) > 1: raise errors.InputContentIncorrect( "That message has more than one embed! I don't support that right now 😔" ) old_embed = msg.embeds[0].to_dict() new_json_content = await self.check_content( ctx, json_content, ask_message="What is the new JSON content of the embed?") if new_json_content[0:7] == "```json" and new_json_content[ -3:] == "```": new_json_content = new_json_content[7:-3] elif new_json_content[0:3] == "```" and new_json_content[-3:] == "```": new_json_content = new_json_content[3:-3] try: new_dict_content = json.loads(new_json_content) except json.decoder.JSONDecodeError as e: raise errors.JSONFailure( "The json that you specified was not correct, please check and try again.\n" f"Get support from the docs or the support server at {self.bot.command_with_prefix(ctx, 'support')}\n" f"Error message: {e}") log_embed = discord.Embed( title="Edited the embed!", colour=discord.Colour(0xC387C1), description= "The original message and the new message are attached above.", timestamp=datetime.now(timezone.utc), ) log_embed.add_field(name="Editor", value=ctx.author.mention) log_embed.add_field(name="channel", value=channel.mention) final_embed: discord.Embed if "embeds" in new_dict_content: embeds = new_dict_content["embeds"] content = new_dict_content.pop("content", None) if len(embeds) > 1: raise errors.InputContentIncorrect( "You can't edit more than one embed at once!\nTry again with only one embed in the JSON data" ) if content is not None and content != "": await ctx.send( "WARNING!\nPlease update the content separately, the content value has been ignored" ) embed = embeds[0] try: if isinstance(embed["timestamp"], str): embed.pop("timestamp") except KeyError: pass final_embed = discord.Embed.from_dict(embed) else: try: if isinstance(new_dict_content["timestamp"], str): new_dict_content.pop("timestamp") except KeyError: pass final_embed = discord.Embed.from_dict(new_dict_content) content_for_confirm = final_embed.title or "No Title" if not isinstance(content_for_confirm, str): content_for_confirm = "Content too complicated to condense" embeds = self.generate_confirmation_embeds( content=content_for_confirm, original_content=old_embed.get("title", "No Title"), channel=channel, author=ctx.author, action="Editing", message_type="embed", message_link=msg.jump_url, content_name="Embed Title", ) success = await confirm( bot=self.bot, embed=embeds.confirmation_embed, finished_embed=embeds.finish_embed, content=embeds.content, original_content=embeds.original_content, channel_id=ctx.channel.id, author_id=ctx.author.id, initial_message_id=ctx.message.id, content_name="Embed Title", ) if success: await msg.edit(embed=final_embed) old_file_name = f"{ctx.author.id}-{datetime.utcnow()}-old-content.json" with open(old_file_name, "w+") as f: json.dump(old_embed, f) new_file_name = f"{ctx.author.id}-{datetime.utcnow()}-new-content.json" with open(new_file_name, "w+") as f: json.dump(new_dict_content, f) await send_log_once( guild_id=ctx.guild.id, bot=self.bot, logger_type="main", embeds=[log_embed], files=[ discord.File(new_file_name, filename="new-content.json"), discord.File(old_file_name, "old-content.json"), ], ) os.remove(new_file_name) os.remove(old_file_name)
async def edit_embed( self, ctx: Context, channel: Optional[discord.TextChannel] = None, message_id: Optional[int] = None, ) -> None: channel = await self.check_channel(ctx, channel) if channel.guild != ctx.guild: raise errors.DifferentServer() msg = await self.check_message_id(ctx, channel, message_id) if msg.author != ctx.guild.me: raise errors.DifferentAuthor() if len(msg.embeds) == 0: raise errors.InputContentIncorrect( f"That message does not have an embed! Try {self.bot.command_with_prefix(ctx, 'edit')} instead" ) elif len(msg.embeds) > 1: raise errors.InputContentIncorrect( "That message has more than one embed! I don't support that right now 😔" ) title = await self.check_content( ctx, None, ask_message="Enter the new title of the embed:") if title[0:3] == "```" and title[-3:] == "```": title = title[3:-3] description = await self.check_content( ctx, None, ask_message="Enter the new description (main body) of the embed:", ) if description[0:3] == "```" and description[-3:] == "```": description = description[3:-3] old_embed = msg.embeds[0].to_dict() new_embed = msg.embeds[0] new_embed.description = description new_embed.title = title embeds = self.generate_confirmation_embeds( content=title, original_content=old_embed.get("title", "No Title"), channel=channel, author=ctx.author, action="Editing", message_type="embed", message_link=msg.jump_url, content_name="Embed Title", ) success = await confirm( bot=self.bot, embed=embeds.confirmation_embed, finished_embed=embeds.finish_embed, content=embeds.content, original_content=embeds.original_content, channel_id=ctx.channel.id, author_id=ctx.author.id, initial_message_id=ctx.message.id, content_name="Embed Title", ) if success: log_embed = discord.Embed( title="Edited the embed!", colour=discord.Colour(0xC387C1), description= "The original message and the new message are attached above.", timestamp=datetime.now(timezone.utc), ) log_embed.add_field(name="Editor", value=ctx.author.mention) log_embed.add_field(name="Channel", value=channel.mention) old_file_name = f"{ctx.author.id}-{datetime.utcnow()}-old-content.json" with open(old_file_name, "w+") as f: json.dump(old_embed, f) new_file_name = f"{ctx.author.id}-{datetime.utcnow()}-new-content.json" with open(new_file_name, "w+") as f: json.dump(new_embed.to_dict(), f) await send_log_once( guild_id=ctx.guild.id, bot=self.bot, logger_type="main", embeds=[log_embed], files=[ discord.File(new_file_name, filename="new-content.json"), discord.File(old_file_name, "old-content.json"), ], ) os.remove(new_file_name) os.remove(old_file_name) await msg.edit(embed=new_embed)
async def send_json_embed( self, ctx: Context, channel: Optional[discord.TextChannel] = None, *, json_content: Optional[str] = None, ) -> None: log_embed = discord.Embed( title="Sent the embed!", colour=discord.Colour(0xC387C1), description= "The full embed is in the attached text file in JSON format.", timestamp=datetime.now(timezone.utc), ) log_embed.add_field(name="Author", value=ctx.author.mention) channel = await self.check_channel(ctx, channel) # Get the channel. if channel.guild != ctx.guild: raise errors.DifferentServer() log_embed.add_field(name="Channel", value=channel.mention) json_content = await self.check_content( ctx, json_content, ask_message="What is the JSON content of the embed?") if json_content[0:7] == "```json" and json_content[-3:]: json_content = json_content[7:-3] elif json_content[0:3] == "```" and json_content[-3:] == "```": json_content = json_content[3:-3] try: dict_content = json.loads(json_content) except json.decoder.JSONDecodeError as e: raise errors.JSONFailure( "The json that you specified was not correct, please check and try again.\n" f"Get support from the docs or the support server at {self.bot.command_with_prefix(ctx, 'support')}\n" f"Error message: {e}") final_embeds: List[discord.Embed] = [] embed_titles: List[str] = [] content_to_send: Optional[str] = None if "embeds" in dict_content or "content" in dict_content: embeds = dict_content.get("embeds", []) content = dict_content.pop("content", None) if content is not None and content != "": content_to_send = content n = 1 for embed in embeds: try: if isinstance(embed["timestamp"], str): embed.pop("timestamp") except KeyError: pass if "title" in embed: log_embed.add_field(name=f"Embed {n}", value=embed["title"]) embed_titles.append(embed["title"]) final_embeds.append(discord.Embed.from_dict(embed)) n = n + 1 else: try: if isinstance(dict_content["timestamp"], str): dict_content.pop("timestamp") except KeyError: pass final_embeds.append(discord.Embed.from_dict(dict_content)) if "title" in dict_content: log_embed.add_field(name="Embed title", value=dict_content["title"]) embed_titles.append(dict_content["title"]) if content_to_send is None and len(final_embeds) == 0: raise errors.InputContentIncorrect( "You must provide either content or embeds!") if len(final_embeds) > 1: message_type = "embeds" elif len(final_embeds) == 1: message_type = "embed" else: message_type = "message" if len(embed_titles) > 0: if len(final_embeds) > 1: content_name = "First Embed Title" else: content_name = "Embed Title" elif len(embed_titles) == 0 and content_to_send is not None: content_name = "Content" else: content_name = "Content too complicated to condense" content_for_confirm = (embed_titles[0] if len(embed_titles) > 0 else content_to_send) if content_for_confirm is None: content_for_confirm = "Content too complicated to condense" embeds = self.generate_confirmation_embeds( content=content_for_confirm, original_content=None, channel=channel, author=ctx.author, action="Sending", message_type=message_type, message_link=None, content_name=content_name, ) success = await confirm( bot=self.bot, embed=embeds.confirmation_embed, finished_embed=embeds.finish_embed, content=embeds.content, original_content=embeds.original_content, channel_id=ctx.channel.id, author_id=ctx.author.id, initial_message_id=ctx.message.id, content_name="Embed Title", ) if success: file_name = f"{ctx.author.id}-{datetime.utcnow()}-content.json" with open(file_name, "w+") as f: json.dump(dict_content, f) if content_to_send is not None: await channel.send(content_to_send) for embed in final_embeds: await channel.send(embed=embed) await send_log_once( guild_id=ctx.guild.id, bot=self.bot, logger_type="main", embeds=[log_embed], file=discord.File(file_name, filename="content.json"), ) os.remove(file_name)