Utilities

General Utility

redbot.core.utils.deduplicate_iterables(*iterables)[source]

Returns a list of all unique items in iterables, in the order they were first encountered.

redbot.core.utils.bounded_gather(*coros_or_futures, loop=None, return_exceptions=False, limit=4, semaphore=None)[source]

A semaphore-bounded wrapper to asyncio.gather().

Parameters:
  • *coros_or_futures – The awaitables to run in a bounded concurrent fashion.
  • loop (asyncio.AbstractEventLoop) – The event loop to use for the semaphore and asyncio.gather().
  • return_exceptions (bool) – If true, gather exceptions in the result list instead of raising.
  • limit (Optional[int]) – The maximum number of concurrent tasks. Used when no semaphore is passed.
  • semaphore (Optional[asyncio.Semaphore]) – The semaphore to use for bounding tasks. If None, create one using loop and limit.
Raises:

TypeError – When invalid parameters are passed

redbot.core.utils.bounded_gather_iter(*coros_or_futures, loop=None, limit=4, semaphore=None)[source]

An iterator that returns tasks as they are ready, but limits the number of tasks running at a time.

Parameters:
  • *coros_or_futures – The awaitables to run in a bounded concurrent fashion.
  • loop (asyncio.AbstractEventLoop) – The event loop to use for the semaphore and asyncio.gather().
  • limit (Optional[int]) – The maximum number of concurrent tasks. Used when no semaphore is passed.
  • semaphore (Optional[asyncio.Semaphore]) – The semaphore to use for bounding tasks. If None, create one using loop and limit.
Raises:

TypeError – When invalid parameters are passed

Chat Formatting

redbot.core.utils.chat_formatting.bold(text)[source]

Get the given text in bold.

Note: This escapes text prior to bolding.

Parameters:text (str) – The text to be marked up.
Returns:The marked up text.
Return type:str
redbot.core.utils.chat_formatting.bordered(*columns, ascii_border=False)[source]

Get two blocks of text in a borders.

Note

This will only work with a monospaced font.

Parameters:
  • *columns (sequence of str) – The columns of text, each being a list of lines in that column.
  • ascii_border (bool) – Whether or not the border should be pure ASCII.
Returns:

The bordered text.

Return type:

str

redbot.core.utils.chat_formatting.box(text, lang='')[source]

Get the given text in a code block.

Parameters:
  • text (str) – The text to be marked up.
  • lang (str, optional) – The syntax highlighting language for the codeblock.
Returns:

The marked up text.

Return type:

str

redbot.core.utils.chat_formatting.error(text)[source]

Get text prefixed with an error emoji.

Returns:The new message.
Return type:str
redbot.core.utils.chat_formatting.escape(text, *, mass_mentions=False, formatting=False)[source]

Get text with all mass mentions or markdown escaped.

Parameters:
  • text (str) – The text to be escaped.
  • mass_mentions (bool, optional) – Set to True to escape mass mentions in the text.
  • formatting (bool, optional) – Set to True to escpae any markdown formatting in the text.
Returns:

The escaped text.

Return type:

str

redbot.core.utils.chat_formatting.format_perms_list(perms)[source]

Format a list of permission names.

This will return a humanized list of the names of all enabled permissions in the provided discord.Permissions object.

Parameters:perms (discord.Permissions) – The permissions object with the requested permissions to list enabled.
Returns:The humanized list.
Return type:str
redbot.core.utils.chat_formatting.humanize_list(items)[source]

Get comma-separted list, with the last element joined with and.

This uses an Oxford comma, because without one, items containing the word and would make the output difficult to interpret.

Parameters:items (Sequence[str]) – The items of the list to join together.
Raises:IndexError – An empty sequence was passed

Examples

>>> humanize_list(['One', 'Two', 'Three'])
'One, Two, and Three'
>>> humanize_list(['One'])
'One'
redbot.core.utils.chat_formatting.humanize_number(val, override_locale=None)[source]

Convert an int or float to a str with digit separators based on bot locale

Parameters:
  • val (Union[int, float]) – The int/float to be formatted.
  • override_locale (Optional[str]) – A value to override the bots locale.
Returns:

locale aware formatted number.

Return type:

str

redbot.core.utils.chat_formatting.humanize_timedelta(*, timedelta=None, seconds=None)[source]

Get a locale aware human timedelta representation.

This works with either a timedelta object or a number of seconds.

Fractional values will be omitted, and values less than 1 second an empty string.

Parameters:
  • timedelta (Optional[datetime.timedelta]) – A timedelta object
  • seconds (Optional[SupportsInt]) – A number of seconds
Returns:

A locale aware representation of the timedelta or seconds.

Return type:

str

Raises:

ValueError – The function was called with neither a number of seconds nor a timedelta object

redbot.core.utils.chat_formatting.info(text)[source]

Get text prefixed with an info emoji.

Returns:The new message.
Return type:str
redbot.core.utils.chat_formatting.inline(text)[source]

Get the given text as inline code.

Parameters:text (str) – The text to be marked up.
Returns:The marked up text.
Return type:str
redbot.core.utils.chat_formatting.italics(text)[source]

Get the given text in italics.

Note: This escapes text prior to italicising

Parameters:text (str) – The text to be marked up.
Returns:The marked up text.
Return type:str
for ... in redbot.core.utils.chat_formatting.pagify(text, delims=['\n'], *, priority=False, escape_mass_mentions=True, shorten_by=8, page_length=2000)[source]

Generate multiple pages from the given text.

Note

This does not respect code blocks or inline code.

Parameters:
  • text (str) – The content to pagify and send.
  • delims (sequence of str, optional) – Characters where page breaks will occur. If no delimiters are found in a page, the page will break after page_length characters. By default this only contains the newline.
Other Parameters:
 
  • priority (bool) – Set to True to choose the page break delimiter based on the order of delims. Otherwise, the page will always break at the last possible delimiter.
  • escape_mass_mentions (bool) – If True, any mass mentions (here or everyone) will be silenced.
  • shorten_by (int) – How much to shorten each page by. Defaults to 8.
  • page_length (int) – The maximum length of each page. Defaults to 2000.
Yields:

str – Pages of the given text.

redbot.core.utils.chat_formatting.question(text)[source]

Get text prefixed with a question emoji.

Returns:The new message.
Return type:str
redbot.core.utils.chat_formatting.strikethrough(text)[source]

Get the given text with a strikethrough.

Note: This escapes text prior to applying a strikethrough

Parameters:text (str) – The text to be marked up.
Returns:The marked up text.
Return type:str
redbot.core.utils.chat_formatting.text_to_file(text, filename='file.txt', *, spoiler=False, encoding='utf-8')[source]

Prepares text to be sent as a file on Discord, without character limit.

This writes text into a bytes object that can be used for the file or files parameters of discord.abc.Messageable.send().

Parameters:
  • text (str) – The text to put in your file.
  • filename (str) – The name of the file sent. Defaults to file.txt.
  • spoiler (bool) – Whether the attachment is a spoiler. Defaults to False.
Returns:

The file containing your text.

Return type:

discord.File

redbot.core.utils.chat_formatting.underline(text)[source]

Get the given text with an underline.

Note: This escapes text prior to underlining

Parameters:text (str) – The text to be marked up.
Returns:The marked up text.
Return type:str
redbot.core.utils.chat_formatting.warning(text)[source]

Get text prefixed with a warning emoji.

Returns:The new message.
Return type:str

Embed Helpers

redbot.core.utils.embed.randomize_colour(embed)[source]

Gives the provided embed a random color. There is an alias for this called randomize_color

Parameters:embed (discord.Embed) – The embed to add a color to
Returns:The embed with the color set to a random color
Return type:discord.Embed

Reaction Menus

This module provides utilities for assisting in sending common types of reaction menus, as well as extending these menus, or creating new ones from scratch.

The ReactionMenu abstract base class and its concrete subclasses were added in version 3.2. Prior to that, the legacy menu() was used, which has been kept for backwards compatibility.

These documents hope to be aimed at cog creators who may use reaction menus in one or two ways:

  1. Sending and managing a common type of reaction menu which is provided with this module, and
  2. Customising the existing reaction menus, or creating new ones from the ReactionMenu ABC.

For those who fit into the 1st category, these are the provided reaction menus:

  • PagedMenu, for a menu where reactions can be used to scroll through a list of pages (text, embed or a combination of both)
  • OptionsMenu, where reactions select an option from a list displayed on the menu, and can pass this onto a provided callback function.
  • PagedOptionsMenu, a combination of the above two menus.

For those who fit into the 2nd category, some protected methods of the reaction menu classes are documented for your interest. Those which are documented are considered part of Red’s public API for cog creators and will be subject to the same care with regards to breaking changes.

Examples

Using Provided Menus

This example shows sending a menu into the context channel, for the command author to scroll through some pages of text and embeds, and waiting for the menu to exit:

import discord
from redbot.core import commands
from redbot.core.utils import menus

@commands.command()
async def sendpages(ctx):
    """Send some useless pages."""
    pages = [
        "This is page 1",
        discord.Embed(title="This is page 2"),
        ("This is page 3", discord.Embed(title="This is also page 3"))
    ]
    await menus.PagedMenu.send_and_wait(ctx, pages=pages)

This example shows sending a menu into a specific channel, for any user to select an option from. This option is then passed onto a callback along with the user who selected it. The menu stays running as a background task and the callback is called multiple times.

import discord
from redbot.core.utils import menus

async def send_reactrole_menu(channel, bot, reactroles) -> menus.OptionsMenu:
    options = [(role.mention, role) for role in reactroles]
    return await menus.OptionsMenu.send_and_return(
        channel=channel,
        bot=bot,
        options=options,
        title="React to add or remove a role",
        embed=True,
        callback=add_or_remove_reactrole
    )

async def add_or_remove_reactrole(member: discord.Member, role: discord.Role):
    if role in member.roles:
        await member.remove_roles(role, reason="Removing reactrole")
    else:
        await member.add_roles(role, reason="Adding reactrole")

Extending Provided Menus

This is an example of a paged menu which lazily fetches batches of pages from some API and caches them, as the user scrolls through it:

from redbot.core.utils import menus
from .api import fetch_preceding_pages, fetch_following_pages

class LazilyPagedMenu(menus.PagedMenu, exit_button=True, initial_emojis=("⬅", "❌", "➡")):

    def __init__(self, **kwargs) -> None:
        # PagedMenu.__init__ requires the pages kwarg.
        # Since we're creating pages ourselves, we allow it to be empty.
        super().__init__(pages=kwargs.pop("pages", []), pagenum_in_footer=False, **kwargs)
        # This attribute is just an example of what might be passed to our API to fetch pages
        self._remote_page_idx = 0

    async def _before_send(self, **kwargs):
        # Fetch the initial pages
        if not self._pages:
            self._pages.extend(await fetch_following_pages(self._remote_page_idx))

    @menus.ReactionMenu.handler("⬅")
    async def prev_page(self, payload: discord.RawReactionActionEvent):
        self._remote_page_idx -= 1
        if self._cur_page == 0:
            # Fetch the previous few pages and add them to the start of the page list
            self._pages[0:0] = new_pages = await fetch_preceding_pages(self._remote_page_idx)
            self._cur_page += len(new_pages)
        # The base method decrements self._cur_page and updates the message
        await super().prev_page(payload)

    @menus.ReactionMenu.handler("➡")
    async def next_page(self, payload: discord.RawReactionActionEvent):
        self._remote_page_idx += 1
        if self._cur_page == len(self._pages) - 1:
            # Fetch the next few pages and add them to the end of the page list
            new_pages = await fetch_following_pages(self._remote_page_idx)
            self._pages.extend(new_pages)
        # The base method increments self._cur_page and updates the message
        await super().next_page(payload)

ReactionMenu

class redbot.core.utils.menus.ReactionMenu(*, ctx=None, channel=None, bot=None, controller_ids=None, initial_emojis=None, timeout=30.0, **kwargs)[source]

Bases: abc.ABC

Abstract base class for reaction menus.

This class does the vast majority of the work when writing reaction menus, and allows for easy customisation of the default behaviour through overriding methods.

It also provides an abstract interface for sending and managing custom menus: most importantly, the classmethods ReactionMenu.send_and_wait() and ReactionMenu.send_and_return(). These methods accept a handful of positional arguments, as well as keyword arguments which can be specific to the menu subclass being used. These keyword arguments should be detailed in the class docstring of the menu subclass being used, just as the built-in ones are detailed below under the Keyword Arguments heading.

New in version 3.2.

Keyword Arguments:
 timeout (Optional[float]) – The timeout for the menu. This timeout is restarted every time a reaction event is handled which passes the event check - which usually means, when a controller adds or removes a reaction to or from the menu. Defaults to 30 seconds. Set to None to disable the timeout.

Important

ReactionMenu subclasses should not be instantiated directly: instead, they should be created through the ReactionMenu.send_and_wait() or ReactionMenu.send_and_return() classmethods.

ctx

The ctx object passed when sending the message, if provided.

Type:Optional[commands.Context]
channel

The messageable where the menu was sent.

Type:discord.abc.Messageable
bot

The bot object.

Type:Red
message

The object for the message which contains the menu. Before the menu is sent, this will be None.

Type:Optional[discord.Message]
INITIAL_EMOJIS

A class variable containing the emojis which should be added to the initial menu message by default.

By default, this will be set to the emojis passed to ReactionMenu.handler() decorators, in the order they appear in the source (with emojis from any inherited handlers appearing first). Alternatively, subclasses may override this behaviour with the initial_emojis argument to ReactionMenu.__init_subclass__().

Type:ClassVar[Optional[Sequence[str]]
staticmethod @handler(*emojis, event = RAW_REACTION_ADD | RAW_REACTION_REMOVE)[source]

A decorator for reaction handlers.

Handlers must be methods of a ReactionMenu subclass, they must be coroutine functions, and they must take the same arguments as listeners to whichever event(s) the handler is responding to.

Parameters:
  • *emojis (str) – The emojis to handle. Leave blank to handle all emojis.
  • event (ReactionEvent) – The event(s) to react to. See the example in that class’s description for how to react to multiple events. Defaults to RAW_REACTION_ADD | RAW_REACTION_REMOVE.
classmethod add_handler(handler, *emojis, event = RAW_REACTION_ADD | RAW_REACTION_REMOVE)[source]

Non-decorator alternative to ReactionMenu.handler.

This classmethod must be called from the actual class which you want the handler to be included in. Calling this method directly from the ReactionMenu class will raise a RuntimeError.

Parameters:
__init__(*, ctx=None, channel=None, bot=None, controller_ids=None, initial_emojis=None, timeout=30.0, **kwargs)[source]

Default constructor for a ReactionMenu.

This method is only documented for the convenience of anyone subclassing ReactionMenu. Menus should not be constructed directly.

Subclasses should always call super().__init__(**kwargs) from their custom constructors.

Constructors are called from the ReactionMenu.send_and_return() and ReactionMenu.send_and_wait() classmethods with the ctx, channel and bot arguments, as well as any other keyword arguments passed. All arguments are passed as keyword arguments. See below for details.

Keyword Arguments:
 
  • ctx (Optional[commands.Context]) – The context object for this menu. This should be the ctx argument to the send classmethods.
  • channel (Optional[discord.abc.Messageable]) – The channel for this menu. This should be the channel argument to the send classmethods.
  • bot (Optional[Red]) – The bot object. This should be the bot argument to the send classmethods.
  • controller_ids (Optional[Set[int]]) – A set of IDs of users given the ability to control this menu. This shouldn’t need to be handled by subclasses.
  • initial_emojis (Optional[Sequence[str]]) – The initial emojis to be reacted to this menu. Defaults to the class attribute ReactionMenu.INITIAL_EMOJIS.
classmethod __init_subclass__(*args, exit_button=False, initial_emojis=None, **kwargs)[source]

Subclass initializer for ReactionMenu.

This method is called whenever ReactionMenu is subclassed, much like a class decorator. Arguments are passed to it through the same parentheses where base classes are specified, like so:

class MyMenu(ReactionMenu, exit_button=True):
    ...

See object.__init_subclass__() for more info on this special method more generally.

Keyword Arguments:
 
  • exit_button (bool) – Set to True to include the default exit button reaction, which uses the ❌ emoji, and is handled by ReactionMenu.exit_menu (or your subclass’s overridden version of that). Note that the exit button handler won’t be inherited from any base classes - it must be explicitly enabled for every subclass.
  • initial_emojis (Optional[Sequence[str]]) – An override for ReactionMenu.INITIAL_EMOJIS. The order of this sequence is preserved when adding reactions.
classmethod await send_and_wait(ctx=None, channel=None, bot=None, controllers=None, **kwargs)[source]

Send the menu and wait for it to be marked as done.

This will usually wait for either a timeout (if the timeout option is enabled for this menu instance), an exit button to be pressed (if the menu class includes it), or some other condition set by the menu subclass.

Note

Subclasses: Do not override this method if you can avoid it. To force this method to return control to the caller, call the set_done() method.

Parameters:
  • ctx (Optional[commands.Context]) – The context object to use for the menu’s context. If provided, the context object provides defaults for the channel, bot, and controllers parameters, where controllers is set to [ctx.author]. If omitted, both channel and bot become required arguments.
  • channel (Optional[discord.abc.Messageable]) – The channel to send the menu in. If ommitted, ctx must be provided instead, and this argument becomes Context.channel.
  • bot (Optional[Red]) – The bot object. If omitted, ctx must be provided instead, and this argument becomes Context.bot.
  • controllers (Optional[Iterable[discord.abc.User]]) – The users who are allowed to control this menu with reactions. To allow anyone to take control of this menu, set to an empty iterable. If omitted, this defaults to [ctx.author], or if ctx is also omitted, this will default to an empty iterable.
  • **kwargs – Other options, specific to the menu subclass being created. See the Keyword Argument section in the class doc for whichever menu subclass you’re using. Some default options can also be passed, as outlined above.
Returns:

The menu object, once it is marked as done.

Return type:

ReactionMenu

classmethod await send_and_return(ctx=None, channel=None, bot=None, controllers=None, **kwargs)[source]

Send this menu, and return straight after sending.

The menu actions will be handled in a background task, and the menu can be force closed externally using the asynchonous ReactionMenu.exit_menu() method, which will wait for the menu to be deleted, or the synchonous, non-blocking set_done() method.

The parameters are the same as in ReactionMenu.send_and_wait().

Note

Subclasses: Do not override this method if you can avoid it.

Returns:The menu object, once the initial message containing the menu has been sent (likely before all reactions are added).
Return type:ReactionMenu
set_done()[source]

Synchonous, non-blocking method to mark the menu as done.

await exit_menu(payload=None)[source]

Delete the menu message and mark the menu as done.

Note

Subclasses: Override this method to implement custom behaviour when the exit menu button (❌) is pressed, and your subclass enables the exit_button option.

_check(reaction, user)[source]

The default check for non-raw reaction add/remove events.

Subclasses may override this method for custom behaviour. By default, it checks that the reaction’s message matches the menu, the user is one of the authorized controllers, and that it wasn’t the bot itself triggerring the event.

_reaction_add_check(reaction, user)[source]

The check for the on_reaction_add() event.

By default, this calls ReactionMenu._check(). Subclasses should override this method if they want different behaviour specifically for the reaction add event.

_reaction_remove_check(reaction, user)[source]

The check for the on_reaction_remove() event.

By default, this calls ReactionMenu._check(). Subclasses should override this method if they want different behaviour specifically for the reaction remove event.

_reaction_clear_check(message, reactions)[source]

The check for the on_reaction_clear() event.

By default, this checks if the reaction’s message matches the menu.

_raw_check(payload)[source]

The default check for raw reaction add/remove events.

Subclasses may override this method for custom behaviour. By default, it checks that the reaction’s message matches the menu, the user is one of the authorized controllers, and that it wasn’t the bot itself triggerring the event.

_raw_reaction_add_check(payload)[source]

The check for the on_raw_reaction_add() event.

By default, this calls ReactionMenu._raw_check(). Subclasses should override this method if they want different behaviour specifically for the raw reaction add event.

_raw_reaction_remove_check(payload)[source]

The check for the on_raw_reaction_remove() event.

By default, this calls ReactionMenu._raw_check(). Subclasses should override this method if they want different behaviour specifically for the raw reaction remove event.

_raw_reaction_clear_check(payload)[source]

The check for the on_raw_reaction_clear() event.

By default, this checks if the reaction’s message matches the menu.

await _before_send(**kwargs)[source]

This method is called before sending the menu.

Subclasses may override this for custom behaviour. By default, it does nothing.

Parameters:**kwargs – The keyword arguments passed to one of the send classethods.
await _send(**kwargs)[source]

This method sends the actual menu.

Overridden methods must return the message object.

Parameters:**kwargs – The keyword arguments passed to one of the send classethods.
Returns:The object for the message that was sent. This will be assigned to the message attribute.
Return type:discord.Message
await _after_send(**kwargs)[source]

This method is called after sending the menu.

Subclasses may override this for custom behaviour. By default, it calls ReactionMenu._start_adding_reactions().

Parameters:**kwargs – The keyword arguments passed to one of the send classethods.
await _after_timeout()[source]

This method is called after the menu times out.

By default, it simply calls ReactionMenu.exit_menu().

await _cleanup()[source]

The cleanup method for the menu.

This method is called when the menu closes, times out, or somehow forcibly exits. It is called within a finally clause, so it shouldn’t be missed.

By default, it does nothing.

_start_adding_reactions(emojis=None)[source]

This method starts the task which adds the initial reactions.

This method simply returns the result of the start_adding_reactions() function.

Parameters:emojis (Optional[Sequence[str]]) – The emojis to use for the reactions. If omitted, it will default to ReactionMenu._initial_emojis.
Returns:The task which is adding the reactions.
Return type:asyncio.Task

PagedMenu

class redbot.core.utils.menus.PagedMenu(*, pages, footer_text=None, first_page=0, arrows_always=False, initial_emojis=None, **kwargs)[source]

Bases: redbot.core.utils.menus.ReactionMenu

A reaction menu for scrolling through pages.

By default, this menu’s intial reactions will be ⬅ ❌ ➡, with the cross being the exit button.

Below are the keyword arguments you must/can pass to the send_and_return() or send_and_wait() classmethods.

New in version 3.2.

Keyword Arguments:
 
  • pages (Iterable[Union[str, discord.Embed, Tuple[str, discord.Embed]]], Required) – An iterable of pages which the menu can scroll through. It can be a combination of strings (for text content), embeds, or 2-tuples containing (text, embed).
  • pagenum_in_footer (bool) – Any embeds which don’t already have non-empty footer text will have the following added to it: Page <k>/<n>, where <k> is the current page number and <n> is the number of pages. Defaults to True.
  • footer_text (Optional[str]) – Text to add to the footer of any embeds which don’t already have non-empty footer text. If pagenum_in_footer is True, this will be added like so: Page <k>/<n> | <footer_text>.
  • first_page (int) – What the initial page index should be. Defaults to zero.
  • arrows_always (bool) – When True, the arrow reactions for previous and next page buttons will be added, even when there is only one page in pages. This is only really useful for subclasses who might only start with one page, but generate the rest dynamically. Defaults to False.
_pages

The list of pages provided. This is documented for the interest of subclasses only.

Type:List[Union[str, discord.Embed, Tuple[str, discord.Embed]]]
_cur_page

The current page number, indexed from zero. This should always be in the range [0, len(_pages)). This is documented for the interest of subclasses only.

Type:int
await prev_page(payload=None)[source]

Handler for the previous page button.

This can be called externally (without arguments) if for some reason the caller wants to manually change pages.

Subclasses may override this method. By default, it decrements PagedMenu._cur_page, wrapping back to the last page if necessary, and then updates the message.

await next_page(payload=None)[source]

Handler for the next page button.

Complements PagedMenu.prev_page().

await _send(**kwargs)[source]

This method sends the actual menu.

Overridden methods must return the message object.

Parameters:**kwargs – The keyword arguments passed to one of the send classethods.
Returns:The object for the message that was sent. This will be assigned to the message attribute.
Return type:discord.Message
await _update_message()[source]

Update the message’s content/embed to the current page.

OptionsMenu

class redbot.core.utils.menus.OptionsMenu(*, options, initial_emojis=None, num_options_per_page=None, exit_on_selection=True, callback=None, **kwargs)[source]

Bases: typing.Generic, redbot.core.utils.menus.ReactionMenu

A reaction menu for picking an option from a list.

This menu allows the caller to provide a list of options in the form of 2-tuples, containing the option description being shown to the user, and some object associated with that option. The selected option’s object will be assigned to the menu’s selection attribute, and can also be passed to some (optionally asynchronous) callback function, along with the user who selected the option.

This menu has a limit of 20 options, due to the limit in the number of reactions which can be added to a Discord message. Providing more than 20 options will raise a ValueError. See the PagedOptionsMenu class if you would like to be able to offer an arbitrarily large number of options.

Below are the keyword arguments you must/can pass to the send_and_return() or send_and_wait() classmethods.

New in version 3.2.

Keyword Arguments:
 
  • options (Sequence[Tuple[str, _T]], Required) – The sequence of options, as described above.
  • emojis (Optional[Sequence[str]]) – The emojis to align with options. If provided, this sequence must be at least as long as options. If omitted, the emojis used depend on the number of options - if 10 or fewer options are provided, number emojis (1, 2, 3 etc.) will be used. If between 11 and 20 options are provided, “regional indicator” letter emojis (A, B, C etc.) will be used.
  • exit_on_selection (bool) – Whether the menu should exit as soon as an option is selected. callback may be called multiple times if this is set to False. Defaults to True.
  • callback (Optional[Callable[[discord.abc.User, _T], Union[Awaitable[None], None]]]) – A callback to pass the user who selected the option, and the selected option’s object to. This must take two arguments: the user and the object, and may be an async function if desired.
  • title (Optional[str]) – A title to display at the top of the menu.
  • embed (Optional[bool]) – Whether or not the menu should be formatted as an embed. If None, it will use the same logic as commands.Context.embed_requested(). Defaults to None.
  • embed_colour (Optional[discord.Colour]) – The colour for the menu embed. If None, it will use the same logic as commands.Context.embed_colour(). Defaults to None. Has no effect if the embed argument is False.
Raises:

ValueError – If emojis is provided but is too small.

PagedOptionsMenu

class redbot.core.utils.menus.PagedOptionsMenu(**kwargs)[source]

Bases: redbot.core.utils.menus.PagedMenu, redbot.core.utils.menus.OptionsMenu

A combination of PagedMenu and OptionsMenu.

This menu supports an arbitrary number of options in total. The number of initial reactions added will be the smallest of either the number of options provided, or the options_per_page argument.

The keyword arguments for this menu include all of those specified by the base classes. However, the pages argument is optional - if omitted, this menu will automatically generate the pages using the formatting keyword arguments specified with OptionsMenu.

New in version 3.2.

Keyword Arguments:
 
  • options_per_page (int) – The number of options to display on each page. Defaults to 5. Must be less than or equal to 20.
  • emojis (Optional[Sequence[str]]) – Same as the emojis keyword argument to OptionsMenu, however its size should be equal to options_per_page. These should not include the page control or exit button emojis - they will be added to the end automatically.
  • **others – See OptionsMenu and PagedMenu, although remember that the pages argument is not required.

ReactionEvent

class redbot.core.utils.menus.ReactionEvent[source]

Bases: enum.Flag

Reaction event enumeration flags.

This enumeration should be used when passing the event kwarg to ReactionMenu.handler and ReactionMenu.add_handler. If a handler accepts multiple events, they should be combined with the bitwise OR operator |, like so:

class MyReactionMenu(ReactionMenu)

    @ReactionMenu.handler(event=ReactionEvent.REACTION_ADD | ReactionEvent.REACTION_REMOVE)
    async def my_handler(self, reaction, user):
        ...
REACTION_ADD

The on_reaction_add() event.

REACTION_REMOVE

The on_reaction_remove() event.

REACTION_CLEAR

The on_reaction_clear() event.

RAW_REACTION_ADD

The on_raw_reaction_add() event.

RAW_REACTION_REMOVE

The on_raw_reaction_remove() event.

RAW_REACTION_CLEAR

The on_raw_reaction_clear() event.

Other Menu Utilities

redbot.core.utils.menus.start_adding_reactions(message, emojis, loop=None)[source]

Start adding reactions to a message.

This is a non-blocking operation - calling this will schedule the reactions being added, but the calling code will continue to execute asynchronously. There is no need to await this function.

This is particularly useful if you wish to start waiting for a reaction whilst the reactions are still being added - in fact, this is exactly what menu uses to do that.

This spawns and returns an asyncio.Task object.

Parameters:
Returns:

The task for the coroutine adding the reactions.

Return type:

asyncio.Task

await redbot.core.utils.menus.menu(ctx, pages, controls, message=None, page=0, timeout=30.0)[source]

Legacy reaction-based menu function.

We recommend using ReactionMenu and/or its subclasses instead of this utility where possible.

Note

All pages should be of the same type

Note

All functions for handling what a particular emoji does should be coroutines (i.e. async def). Additionally, they must take all of the parameters of this function, in addition to a string representing the emoji reacted with. This parameter should be the last one, and none of the parameters in the handling functions are optional

Parameters:
  • ctx (commands.Context) – The command context
  • pages (list of str or discord.Embed) – The pages of the menu.
  • controls (dict) – A mapping of emoji to the function which handles the action for the emoji.
  • message (discord.Message) – The message representing the menu. Usually None when first opening the menu
  • page (int) – The current page number of the menu
  • timeout (float) – The time (in seconds) to wait for a reaction
Raises:

RuntimeError – If either of the notes above are violated

Event Predicates

class redbot.core.utils.predicates.MessagePredicate(predicate)[source]

Bases: collections.abc.Callable, typing.Generic

A simple collection of predicates for message events.

These predicates intend to help simplify checks in message events and reduce boilerplate code.

This class should be created through the provided classmethods. Instances of this class are callable message predicates, i.e. they return True if a message matches the criteria.

All predicates are combined with MessagePredicate.same_context().

Examples

Waiting for a response in the same channel and from the same author:

await bot.wait_for("message", check=MessagePredicate.same_context(ctx))

Waiting for a response to a yes or no question:

pred = MessagePredicate.yes_or_no(ctx)
await bot.wait_for("message", check=pred)
if pred.result is True:
    # User responded "yes"
    ...

Getting a member object from a user’s response:

pred = MessagePredicate.valid_member(ctx)
await bot.wait_for("message", check=pred)
member = pred.result
result

The object which the message content matched with. This is dependent on the predicate used - see each predicate’s documentation for details, not every method will assign this attribute. Defaults to None.

Type:Any
classmethod cancelled(ctx=None, channel=None, user=None)[source]

Match if the message is [p]cancel.

Parameters:
Returns:

The event predicate.

Return type:

MessagePredicate

classmethod contained_in(collection, ctx=None, channel=None, user=None)[source]

Match if the response is contained in the specified collection.

The index of the response in the collection sequence is assigned to the result attribute.

Parameters:
Returns:

The event predicate.

Return type:

MessagePredicate

classmethod equal_to(value, ctx=None, channel=None, user=None)[source]

Match if the response is equal to the specified value.

Parameters:
Returns:

The event predicate.

Return type:

MessagePredicate

classmethod greater(value, ctx=None, channel=None, user=None)[source]

Match if the response is greater than the specified value.

Parameters:
Returns:

The event predicate.

Return type:

MessagePredicate

classmethod has_role(ctx=None, channel=None, user=None)[source]

Match if the response refers to a role which the author has.

Assigns the matching discord.Role object to result.

One of user or ctx must be supplied. This predicate cannot be used in DM.

Parameters:
Returns:

The event predicate.

Return type:

MessagePredicate

classmethod length_greater(length, ctx=None, channel=None, user=None)[source]

Match if the response’s length is greater than the specified length.

Parameters:
Returns:

The event predicate.

Return type:

MessagePredicate

classmethod length_less(length, ctx=None, channel=None, user=None)[source]

Match if the response’s length is less than the specified length.

Parameters:
Returns:

The event predicate.

Return type:

MessagePredicate

classmethod less(value, ctx=None, channel=None, user=None)[source]

Match if the response is less than the specified value.

Parameters:
Returns:

The event predicate.

Return type:

MessagePredicate

classmethod lower_contained_in(collection, ctx=None, channel=None, user=None)[source]

Same as contained_in(), but the response is set to lowercase before matching.

Parameters:
Returns:

The event predicate.

Return type:

MessagePredicate

classmethod lower_equal_to(value, ctx=None, channel=None, user=None)[source]

Match if the response as lowercase is equal to the specified value.

Parameters:
Returns:

The event predicate.

Return type:

MessagePredicate

classmethod positive(ctx=None, channel=None, user=None)[source]

Match if the response is a positive number.

Assigns the response to result as a float.

Parameters:
Returns:

The event predicate.

Return type:

MessagePredicate

classmethod regex(pattern, ctx=None, channel=None, user=None)[source]

Match if the response matches the specified regex pattern.

This predicate will use re.search to find a match. The resulting match object will be assigned to result.

Parameters:
Returns:

The event predicate.

Return type:

MessagePredicate

classmethod same_context(ctx=None, channel=None, user=None)[source]

Match if the reaction fits the described context.

Parameters:
  • ctx (Optional[Context]) – The current invokation context.
  • channel (Optional[discord.TextChannel]) – The channel we expect a message in. If unspecified, defaults to ctx.channel. If ctx is unspecified too, the message’s channel will be ignored.
  • user (Optional[discord.abc.User]) – The user we expect a message from. If unspecified, defaults to ctx.author. If ctx is unspecified too, the message’s author will be ignored.
Returns:

The event predicate.

Return type:

MessagePredicate

classmethod valid_float(ctx=None, channel=None, user=None)[source]

Match if the response is a float.

Assigns the response to result as a float.

Parameters:
Returns:

The event predicate.

Return type:

MessagePredicate

classmethod valid_int(ctx=None, channel=None, user=None)[source]

Match if the response is an integer.

Assigns the response to result as an int.

Parameters:
Returns:

The event predicate.

Return type:

MessagePredicate

classmethod valid_member(ctx=None, channel=None, user=None)[source]

Match if the response refers to a member in the current guild.

Assigns the matching discord.Member object to result.

This predicate cannot be used in DM.

Parameters:
Returns:

The event predicate.

Return type:

MessagePredicate

classmethod valid_role(ctx=None, channel=None, user=None)[source]

Match if the response refers to a role in the current guild.

Assigns the matching discord.Role object to result.

This predicate cannot be used in DM.

Parameters:
Returns:

The event predicate.

Return type:

MessagePredicate

classmethod valid_text_channel(ctx=None, channel=None, user=None)[source]

Match if the response refers to a text channel in the current guild.

Assigns the matching discord.TextChannel object to result.

This predicate cannot be used in DM.

Parameters:
Returns:

The event predicate.

Return type:

MessagePredicate

classmethod yes_or_no(ctx=None, channel=None, user=None)[source]

Match if the message is “yes”/”y” or “no”/”n”.

This will assign True for yes, or False for no to the result attribute.

Parameters:
Returns:

The event predicate.

Return type:

MessagePredicate

class redbot.core.utils.predicates.ReactionPredicate(predicate)[source]

Bases: collections.abc.Callable, typing.Generic

A collection of predicates for reaction events.

All checks are combined with ReactionPredicate.same_context().

Examples

Confirming a yes/no question with a tick/cross reaction:

from redbot.core.utils.predicates import ReactionPredicate
from redbot.core.utils.menus import start_adding_reactions

msg = await ctx.send("Yes or no?")
start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS)

pred = ReactionPredicate.yes_or_no(msg, ctx.author)
await ctx.bot.wait_for("reaction_add", check=pred)
if pred.result is True:
    # User responded with tick
    ...
else:
    # User responded with cross
    ...

Waiting for the first reaction from any user with one of the first 5 letters of the alphabet:

from redbot.core.utils.predicates import ReactionPredicate
from redbot.core.utils.menus import start_adding_reactions

msg = await ctx.send("React to me!")
emojis = ReactionPredicate.ALPHABET_EMOJIS[:5]
start_adding_reactions(msg, emojis)

pred = ReactionPredicate.with_emojis(emojis, msg)
await ctx.bot.wait_for("reaction_add", check=pred)
# pred.result is now the index of the letter in `emojis`
result

The object which the message content matched with. This is dependent on the predicate used - see each predicate’s documentation for details, not every method will assign this attribute. Defaults to None.

Type:Any
ALPHABET_EMOJIS: ClassVar[List[str]] = ['🇦', '🇧', '🇨', '🇩', '🇪', '🇫', '🇬', '🇭', '🇮', '🇯', '🇰', '🇱', '🇲', '🇳', '🇴', '🇵', '🇶', '🇷', '🇸', '🇹', '🇺', '🇻', '🇼', '🇽', '🇾', '🇿']

A list of all 26 alphabetical letter emojis.

Type:List[str]
NUMBER_EMOJIS: ClassVar[List[str]] = ['0⃣', '1⃣', '2⃣', '3⃣', '4⃣', '5⃣', '6⃣', '7⃣', '8⃣', '9⃣']

A list of all single-digit number emojis, 0 through 9.

Type:List[str]
YES_OR_NO_EMOJIS: ClassVar[Tuple[str, str]] = ('✅', '❎')

A tuple containing the tick emoji and cross emoji, in that order.

Type:Tuple[str, str]
classmethod same_context(message=None, user=None)[source]

Match if a reaction fits the described context.

This will ignore reactions added by the bot user, regardless of whether or not user is supplied.

Parameters:
  • message (Optional[discord.Message]) – The message which we expect a reaction to. If unspecified, the reaction’s message will be ignored.
  • user (Optional[discord.abc.User]) – The user we expect to react. If unspecified, the user who added the reaction will be ignored.
Returns:

The event predicate.

Return type:

ReactionPredicate

classmethod with_emojis(emojis, message=None, user=None)[source]

Match if the reaction is one of the specified emojis.

Parameters:
Returns:

The event predicate.

Return type:

ReactionPredicate

classmethod yes_or_no(message=None, user=None)[source]

Match if the reaction is a tick or cross emoji.

The emojis used can are in ReactionPredicate.YES_OR_NO_EMOJIS.

This will assign True for yes, or False for no to the result attribute.

Parameters:
Returns:

The event predicate.

Return type:

ReactionPredicate

Mod Helpers

await redbot.core.utils.mod.check_permissions(ctx, perms)[source]

Check if the author has required permissions.

This will always return True if the author is a bot owner, or has the administrator permission. If perms is empty, this will only check if the user is a bot owner.

Parameters:
  • ctx (Context) – The command invokation context to check.
  • perms (Dict[str, bool]) – A dictionary mapping permissions to their required states. Valid permission names are those listed as properties of the discord.Permissions class.
Returns:

True if the author has the required permissions.

Return type:

bool

redbot.core.utils.mod.get_audit_reason(author, reason=None)[source]

Construct a reason to appear in the audit log.

Parameters:
  • author (discord.Member) – The author behind the audit log action.
  • reason (str) – The reason behind the audit log action.
Returns:

The formatted audit log reason.

Return type:

str

await redbot.core.utils.mod.is_admin_or_superior(bot, obj)[source]

Same as is_mod_or_superior except for admin permissions.

If a message is passed, its author’s permissions are checked. If a role is passed, it simply checks if it is the admin role.

Parameters:
Returns:

True if the object has admin permissions.

Return type:

bool

Raises:

TypeError – If the wrong type of obj was passed.

await redbot.core.utils.mod.is_mod_or_superior(bot, obj)[source]

Check if an object has mod or superior permissions.

If a message is passed, its author’s permissions are checked. If a role is passed, it simply checks if it is one of either the admin or mod roles.

Parameters:
Returns:

True if the object has mod permissions.

Return type:

bool

Raises:

TypeError – If the wrong type of obj was passed.

await redbot.core.utils.mod.mass_purge(messages, channel)[source]

Bulk delete messages from a channel.

If more than 100 messages are supplied, the bot will delete 100 messages at a time, sleeping between each action.

Note

Messages must not be older than 14 days, and the bot must not be a user account.

Parameters:
Raises:
await redbot.core.utils.mod.slow_deletion(messages)[source]

Delete a list of messages one at a time.

Any exceptions raised when trying to delete the message will be silenced.

Parameters:messages (iterable of discord.Message) – The messages to delete.
redbot.core.utils.mod.strfdelta(delta)[source]

Format a timedelta object to a message with time units.

Parameters:delta (datetime.timedelta) – The duration to parse.
Returns:A message representing the timedelta with units.
Return type:str

Tunnel

class redbot.core.utils.tunnel.Tunnel(*, sender, origin, recipient)[source]

Bases: object

A tunnel interface for messages

This will return None on init if the destination or source + origin pair is already in use, or the existing tunnel object if one exists for the designated parameters

sender

The person who opened the tunnel

Type:discord.Member
origin

The channel in which it was opened

Type:discord.TextChannel
recipient

The user on the other end of the tunnel

Type:discord.User
await communicate(*, message, topic=None, skip_message_content=False)[source]

Forwards a message.

Parameters:
  • message (discord.Message) – The message to forward
  • topic (str) – A string to prepend
  • skip_message_content (bool) – If this flag is set, only the topic will be sent
Returns:

a pair of ints matching the ids of the message which was forwarded and the last message the bot sent to do that. useful if waiting for reactions.

Return type:

int, int

Raises:

discord.Forbidden – This should only happen if the user’s DMs are disabled the bot can’t upload at the origin channel or can’t add reactions there.

staticmethod await files_from_attach(m, *, use_cached=False, images_only=False)[source]

makes a list of file objects from a message returns an empty list if none, or if the sum of file sizes is too large for the bot to send

Parameters:
  • m (discord.Message) – A message to get attachments from
  • use_cached (bool) – Whether to use proxy_url rather than url when downloading the attachment
  • images_only (bool) – Whether only image attachments should be added to returned list
Returns:

A list of discord.File objects

Return type:

list of discord.File

staticmethod await files_from_attatch(m, *, use_cached=False, images_only=False)

makes a list of file objects from a message returns an empty list if none, or if the sum of file sizes is too large for the bot to send

Parameters:
  • m (discord.Message) – A message to get attachments from
  • use_cached (bool) – Whether to use proxy_url rather than url when downloading the attachment
  • images_only (bool) – Whether only image attachments should be added to returned list
Returns:

A list of discord.File objects

Return type:

list of discord.File

staticmethod await message_forwarder(*, destination, content=None, embed=None, files=None)[source]

This does the actual sending, use this instead of a full tunnel if you are using command initiated reactions instead of persistent event based ones

Parameters:
Returns:

The messages sent as a result.

Return type:

List[discord.Message]

Raises:

Common Filters

redbot.core.utils.common_filters.filter_urls(to_filter)[source]

Get a string with URLs sanitized.

This will match any URLs starting with these protocols:

  • http://
  • https://
  • ftp://
  • sftp://
Parameters:to_filter (str) – The string to filter.
Returns:The sanitized string.
Return type:str
redbot.core.utils.common_filters.filter_invites(to_filter)[source]

Get a string with discord invites sanitized.

Will match any discord.gg, discordapp.com/invite, or discord.me invite URL.

Parameters:to_filter (str) – The string to filter.
Returns:The sanitized string.
Return type:str
redbot.core.utils.common_filters.filter_mass_mentions(to_filter)[source]

Get a string with mass mentions sanitized.

Will match any here and/or everyone mentions.

Parameters:to_filter (str) – The string to filter.
Returns:The sanitized string.
Return type:str
redbot.core.utils.common_filters.filter_various_mentions(to_filter)[source]

Get a string with role, user, and channel mentions sanitized.

This is mainly for use on user display names, not message content, and should be applied sparingly.

Parameters:to_filter (str) – The string to filter.
Returns:The sanitized string.
Return type:str
redbot.core.utils.common_filters.normalize_smartquotes(to_normalize)[source]

Get a string with smart quotes replaced with normal ones

Parameters:to_normalize (str) – The string to normalize.
Returns:The normalized string.
Return type:str
redbot.core.utils.common_filters.escape_spoilers(content)[source]

Get a string with spoiler syntax escaped.

Parameters:content (str) – The string to escape.
Returns:The escaped string.
Return type:str
redbot.core.utils.common_filters.escape_spoilers_and_mass_mentions(content)[source]

Get a string with spoiler syntax and mass mentions escaped

Parameters:content (str) – The string to escape.
Returns:The escaped string.
Return type:str