Source code for cyberjake.discord_common

"""Common code for discord bots"""

import random
import typing
from ._utils import _check_required_modules, _INSTALLED_MODULES

try:
    import discord
    from discord.ext import commands

    _INSTALLED_MODULES["discord.py"] = True
except ModuleNotFoundError:
    pass


[docs]@_check_required_modules("discord.py") async def error_embed( ctx: typing.Union["commands.Context", "discord.Interaction"], message: str, title: str = "Error:", **kwargs, ): """ Makes and send an error embed **Requires discord.py** **Asynchronous Function** :raises ModuleNotFoundError: Will raise a ModuleNotFoundError if discord.py module \ is not installed :param ctx: Command context :type ctx: discord.ext.commands.Context :param message: Message description :type message: str :param title: Error message title :type title: str """ await make_embed( ctx, color="FF0000", send=isinstance(ctx, commands.Context), description=message, title=title, **kwargs, )
[docs]@_check_required_modules("discord.py") async def make_embed( ctx: typing.Union["discord.commands.Context", "discord.Interaction"], color: typing.Union[str, int, "discord.Color"] = None, send: typing.Union[bool, str] = True, as_reply: bool = False, **kwargs, ) -> typing.Optional["discord.Embed"]: """ Makes and defaults to sending a discord.Embed **Asynchronous Function** :raises ModuleNotFoundError: Will raise a ModuleNotFoundError if discord.py module \ is not installed :param ctx: Discord context or interaction :type ctx: discord.ext.commands.Context | discord.Interaction :param color: Color of the embed :type color: [str, int, discord.Color] :param send: Send the message instead of returning :type send: bool :param as_reply: Reply to the message instead of sending :type as_reply: bool :param kwargs: Keyword arguments to pass to embed :return: Filled out embed if send is False """ if send and isinstance(ctx, discord.Interaction): raise NotImplementedError("Can not have send with an interaction context") if not color: kwargs["color"] = random.randint(0, 16777215) # nosec elif isinstance(color, str): kwargs["color"] = discord.Color(int(color, 16)) footer = kwargs.pop("footer", None) embed = discord.Embed(timestamp=ctx.message.created_at, **kwargs) if footer: embed.set_footer(text=footer) if send: if as_reply: await ctx.reply(embed=embed) else: await ctx.send(embed=embed) else: return embed
[docs]@_check_required_modules("discord.py") async def error_message( ctx: typing.Union["commands.Context", "discord.Interaction"], message: str, title: str = "Error:", **kwargs, ) -> None: """Error Message Generate an error embed **Requires discord.py** **Asynchronous Function** :param ctx: Discord Context :type ctx: discord.ext.commands.Context :param message: Message of the error :param title: Title of error embed :param kwargs: Keyword arguments to pass to Embed """ await make_embed(ctx, "FF0000", description=message, title=title, **kwargs)
[docs]@_check_required_modules("discord.py") async def list_message( ctx: typing.Union["commands.Context", "discord.Interaction"], message: list, title: str, **kwargs, ) -> typing.Optional[typing.List["discord.Embed"]]: """List Message Breaks up messages that contain a list and sends the parts of them. Shared function between multiple commands. **Requires discord.py** **Asynchronous Function** I'm sorry for everyone dealing with this function. It is not clean and I have commented to the best that I can. :param ctx: Context of command. :type ctx: discord.ext.commands.Context :param message: list of items to send. :type message: list :param title: Title of the message to send. :type title: str :param kwargs: keyword arguments :type kwargs: dict :return: All embeds are sent ":rtype: None """ joined_message = len("".join(message)) list_of_embeds: typing.List["discord.Embed"] = [] part = 1 item = 0 amount_of_embeds = len(range(0, joined_message, 1500)) for _ in range(amount_of_embeds): # Each embed can only be 6000 characters so if the length is over that more are created embed = await make_embed(ctx, title=title, send=False, **kwargs) for _ in range(2): temp_msg = "" while len(temp_msg) < 1024: # Each field can only be 1024 characters try: if len(temp_msg + f"- {message[item]}\n") > 1024: # If the new item is going to make it over the 1024 limit then skip it. break temp_msg += f"- {message[item]}\n" item += 1 except IndexError: # Error happens when there the length of temp_msg is still under 1000 but # no items left. break if len(temp_msg) > 0: # Blank messages can occur and this filters them out embed.add_field(name=f"Part: {part}", value=temp_msg, inline=True) part += 1 list_of_embeds.append(embed) if isinstance(ctx, commands.Context): for item in list_of_embeds: if len(item.fields) > 0: await ctx.send(embed=item) else: return list_of_embeds