Example #1
0
    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
Example #2
0
    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
Example #3
0
 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
Example #4
0
    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
Example #5
0
 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),
             )
Example #6
0
    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)
Example #7
0
    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)
Example #8
0
    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)