Pydis Core

Useful utilities and tools for Discord bot development.

class BotBase(*args, guild_id, allowed_roles, http_session, redis_session=None, api_client=None, statsd_url=None, **kwargs)[source]

Bases: Bot

A sub-class that implements many common features that Python Discord bots use.

guild_id[source]

ID of the guild that the bot belongs to.

Type:

int

http_session[source]

The http session used for sending out HTTP requests.

Type:

aiohttp.ClientSession

api_client[source]

The API client used for communications with the site service.

Type:

pydis_core.site_api.APIClient

statsd_url[source]

The url that statsd sends metrics to.

Type:

str

redis_session[source]

The redis session used to communicate with the Redis instance.

Type:

async_rediscache.RedisSession

stats[source]

The statsd client that sends metrics.

Type:

pydis_core.async_stats.AsyncStatsClient

all_extensions[source]

All extensions that were found within the module passed to self.load_extensions. Use self.extensions to get the loaded extensions.

Type:

frozenset[str]

__init__(*args, guild_id, allowed_roles, http_session, redis_session=None, api_client=None, statsd_url=None, **kwargs)[source]

Initialise the base bot instance.

Parameters:
async add_cog(cog)[source]

Add the given cog to the bot and log the operation.

Return type:

None

add_command(command)[source]

Add command as normal and then add its root aliases to the bot.

Return type:

None

clear()[source]

Not implemented! Re-instantiate the bot instead of attempting to re-use a closed one.

Return type:

None

async close()[source]

Close the Discord connection, and the aiohttp session, connector, statsd client, and resolver.

Return type:

None

async load_extensions(module, *, sync_app_commands=True)[source]

Load all the extensions within the given module and save them to self.all_extensions.

Parameters:

sync_app_commands (bool) – Whether to sync app commands after all extensions are loaded.

Return type:

None

async log_to_dev_log(message)[source]

Log the given message to #dev-log.

Return type:

None

async on_guild_available(guild)[source]

Set the internal guild available event when self.guild_id becomes available.

If the cache appears to still be empty (no members, no channels, or no roles), the event will not be set and guild_available_but_cache_empty event will be emitted.

Return type:

None

async on_guild_unavailable(guild)[source]

Clear the internal guild available event when self.guild_id becomes unavailable.

Return type:

None

async ping_services()[source]

Ping all required services on setup to ensure they are up before starting.

Return type:

None

async process_commands(message)[source]

Overwrite default Discord.py behaviour to process commands only after ensuring extensions are loaded.

This extension check is only relevant for clients that make use of pydis_core.BotBase.load_extensions.

Return type:

None

register_command_error_manager(manager)[source]

Bind an instance of the command error manager to both the bot and the command tree.

The reason this doesn’t happen in the constructor is because error handlers might need an instance of the bot. So registration needs to happen once the bot instance has been created.

Return type:

None

remove_command(name)[source]

Remove a command/alias as normal and then remove its root aliases from the bot.

Individual root aliases cannot be removed by this function. To remove them, either remove the entire command or manually edit bot.all_commands.

Return type:

Command | None

async setup_hook()[source]

An async init to startup generic services.

Connects to statsd, and calls AsyncStatsClient.create_socket and ping_services().

Return type:

None

async wait_until_guild_available()[source]

Wait until the guild that matches the guild_id given at init is available (and the cache is ready).

The on_ready event is inadequate because it only waits 2 seconds for a GUILD_CREATE gateway event before giving up and thus not populating the cache for unavailable guilds.

Return type:

None

exception EmptyPaginatorEmbedError[source]

Bases: Exception

Raised when attempting to paginate with empty contents.

class LinePaginator(prefix='```', suffix='```', max_size=4000, scale_to_size=4000, max_lines=None, linesep='\\n')[source]

Bases: Paginator

A class that aids in paginating code blocks for Discord messages.

Parameters:
  • pagination_emojis (PaginationEmojis) – The emojis used to navigate pages.

  • prefix (str) – The prefix inserted to every page. e.g. three backticks.

  • suffix (str) – The suffix appended at the end of every page. e.g. three backticks.

  • max_size (int) – The maximum amount of codepoints allowed in a page.

  • scale_to_size (int) – The maximum amount of characters a single line can scale up to.

  • max_lines (int) – The maximum amount of lines allowed in a page.

__init__(prefix='```', suffix='```', max_size=4000, scale_to_size=4000, max_lines=None, linesep='\\n')[source]

This function overrides the Paginator.__init__ from inside discord.ext.commands.

It overrides in order to allow us to configure the maximum number of lines per page.

add_line(line='', *, empty=False)[source]

Adds a line to the current page.

If a line on a page exceeds max_size characters, then max_size will go up to scale_to_size for a single line before creating a new page for the overflow words. If it is still exceeded, the excess characters are stored and placed on the next pages unti there are none remaining (by word boundary). The line is truncated if scale_to_size is still exceeded after attempting to continue onto the next page.

In the case that the page already contains one or more lines and the new lines would cause max_size to be exceeded, a new page is created. This is done in order to make a best effort to avoid breaking up single lines across pages, while keeping the total length of the page at a reasonable size.

This function overrides the Paginator.add_line from inside discord.ext.commands.

It overrides in order to allow us to configure the maximum number of lines per page.

Parameters:
  • line (str) – The line to add to the paginated content.

  • empty (bool) – Indicates whether an empty line should be added at the end.

Return type:

None

async classmethod paginate(pagination_emojis, lines, ctx, embed, *, prefix='', suffix='', max_lines=None, max_size=500, scale_to_size=4000, empty=True, restrict_to_user=None, timeout=300, footer_text=None, url=None, exception_on_empty_embed=False, reply=False, allowed_roles=None)[source]

Use a paginator and set of reactions to provide pagination over a set of lines.

The reactions are used to switch page, or to finish with pagination.

When used, this will send a message using ctx.send() and apply a set of reactions to it. These reactions may be used to change page, or to remove pagination from the message.

Pagination will also be removed automatically if no reaction is added for five minutes (300 seconds).

The interaction will be limited to restrict_to_user (ctx.author by default) or to any user with a moderation role.

Parameters:
  • pagination_emojis (PaginationEmojis) – The emojis used to navigate pages.

  • lines (list[str]) – A list of lines to be added to the paginated content.

  • ctx (discord.ext.commands.Context) – The context in which the pagination is needed.

  • embed (discord.Embed) – The embed that holds the content, it serves as the page.

  • prefix (str) – The prefix inserted to every page. e.g. three backticks.

  • suffix (str) – The suffix appended at the end of every page. e.g. three backticks.

  • max_lines (int) – The maximum amount of lines allowed in a page.

  • max_size (int) – The maximum amount of codepoints allowed in a page.

  • scale_to_size (int) – The maximum amount of characters a single line can scale up to.

  • empty (bool) – Indicates whether an empty line should be added to each provided line.

  • restrict_to_user (discord.User) – The user to whom interaction with the pages should be restricted.

  • timeout (int) – The timeout after which users cannot change pages anymore.

  • footer_text (str) – Text to be added as a footer for each page.

  • url (str) – The url to be set for the pagination embed.

  • exception_on_empty_embed (bool) – Indicates whether to raise an exception when no lines are provided.

  • reply (bool) – Indicates whether to send the page as a reply to the context’s message.

  • allowed_roles (Sequence[int]) – A list of role ids that are allowed to change pages.

Return type:

Message | None

Example: >>> embed = discord.Embed() >>> embed.set_author(name=”Some Operation”, url=url, icon_url=icon) >>> await LinePaginator.paginate(pagination_emojis, [line for line in lines], ctx, embed)

class PaginationEmojis(**data)[source]

Bases: BaseModel

The emojis that will be used for pagination.

__class_vars__: ClassVar[set[str]] = {}

The names of the class variables defined on the model.

__private_attributes__: ClassVar[Dict[str, ModelPrivateAttr]] = {}

Metadata about the private attributes of the model.

__pydantic_complete__: ClassVar[bool] = True

Whether model building is completed, or if there are still undefined fields.

__pydantic_core_schema__: ClassVar[CoreSchema] = {'cls': <class 'pydis_core.utils.pagination.PaginationEmojis'>, 'config': {'title': 'PaginationEmojis'}, 'custom_init': False, 'metadata': {'pydantic_js_annotation_functions': [], 'pydantic_js_functions': [functools.partial(<function modify_model_json_schema>, cls=<class 'pydis_core.utils.pagination.PaginationEmojis'>, title=None), <bound method BaseModel.__get_pydantic_json_schema__ of <class 'pydis_core.utils.pagination.PaginationEmojis'>>]}, 'ref': 'pydis_core.utils.pagination.PaginationEmojis:93928774418464', 'root_model': False, 'schema': {'computed_fields': [], 'fields': {'delete': {'metadata': {'pydantic_js_annotation_functions': [<function get_json_schema_update_func.<locals>.json_schema_update_func>], 'pydantic_js_functions': []}, 'schema': {'default': '<:trashcan:637136429717389331>', 'schema': {'type': 'str'}, 'type': 'default'}, 'type': 'model-field'}, 'first': {'metadata': {'pydantic_js_annotation_functions': [<function get_json_schema_update_func.<locals>.json_schema_update_func>], 'pydantic_js_functions': []}, 'schema': {'default': '⏮', 'schema': {'type': 'str'}, 'type': 'default'}, 'type': 'model-field'}, 'last': {'metadata': {'pydantic_js_annotation_functions': [<function get_json_schema_update_func.<locals>.json_schema_update_func>], 'pydantic_js_functions': []}, 'schema': {'default': '⏭', 'schema': {'type': 'str'}, 'type': 'default'}, 'type': 'model-field'}, 'left': {'metadata': {'pydantic_js_annotation_functions': [<function get_json_schema_update_func.<locals>.json_schema_update_func>], 'pydantic_js_functions': []}, 'schema': {'default': '⬅', 'schema': {'type': 'str'}, 'type': 'default'}, 'type': 'model-field'}, 'right': {'metadata': {'pydantic_js_annotation_functions': [<function get_json_schema_update_func.<locals>.json_schema_update_func>], 'pydantic_js_functions': []}, 'schema': {'default': '➡', 'schema': {'type': 'str'}, 'type': 'default'}, 'type': 'model-field'}}, 'model_name': 'PaginationEmojis', 'type': 'model-fields'}, 'type': 'model'}

The core schema of the model.

__pydantic_custom_init__: ClassVar[bool] = False

Whether the model has a custom __init__ method.

__pydantic_decorators__: ClassVar[_decorators.DecoratorInfos] = DecoratorInfos(validators={}, field_validators={}, root_validators={}, field_serializers={}, model_serializers={}, model_validators={}, computed_fields={})

Metadata containing the decorators defined on the model. This replaces Model.__validators__ and Model.__root_validators__ from Pydantic V1.

__pydantic_extra__: dict[str, Any] | None

A dictionary containing extra values, if [extra][pydantic.config.ConfigDict.extra] is set to ‘allow’.

__pydantic_fields_set__: set[str]

The names of fields explicitly set during instantiation.

__pydantic_generic_metadata__: ClassVar[_generics.PydanticGenericMetadata] = {'args': (), 'origin': None, 'parameters': ()}

Metadata for generic models; contains data used for a similar purpose to __args__, __origin__, __parameters__ in typing-module generics. May eventually be replaced by these.

__pydantic_parent_namespace__: ClassVar[Dict[str, Any] | None] = None

Parent namespace of the model, used for automatic rebuilding of models.

__pydantic_post_init__: ClassVar[None | Literal['model_post_init']] = None

The name of the post-init method for the model, if defined.

__pydantic_private__: dict[str, Any] | None

Values of private attributes set on the model instance.

__pydantic_serializer__: ClassVar[SchemaSerializer] = SchemaSerializer(serializer=Model(     ModelSerializer {         class: Py(             0x0000556d7f3bc020,         ),         serializer: Fields(             GeneralFieldsSerializer {                 fields: {                     "first": SerField {                         key_py: Py(                             0x00007fb4cbbf48b0,                         ),                         alias: None,                         alias_py: None,                         serializer: Some(                             WithDefault(                                 WithDefaultSerializer {                                     default: Default(                                         Py(                                             0x00007fb4c62bac40,                                         ),                                     ),                                     serializer: Str(                                         StrSerializer,                                     ),                                 },                             ),                         ),                         required: true,                     },                     "right": SerField {                         key_py: Py(                             0x00007fb4cbb796f0,                         ),                         alias: None,                         alias_py: None,                         serializer: Some(                             WithDefault(                                 WithDefaultSerializer {                                     default: Default(                                         Py(                                             0x00007fb4c62bac90,                                         ),                                     ),                                     serializer: Str(                                         StrSerializer,                                     ),                                 },                             ),                         ),                         required: true,                     },                     "left": SerField {                         key_py: Py(                             0x00007fb4cbb79730,                         ),                         alias: None,                         alias_py: None,                         serializer: Some(                             WithDefault(                                 WithDefaultSerializer {                                     default: Default(                                         Py(                                             0x00007fb4c62babf0,                                         ),                                     ),                                     serializer: Str(                                         StrSerializer,                                     ),                                 },                             ),                         ),                         required: true,                     },                     "last": SerField {                         key_py: Py(                             0x00007fb4cbbd2270,                         ),                         alias: None,                         alias_py: None,                         serializer: Some(                             WithDefault(                                 WithDefaultSerializer {                                     default: Default(                                         Py(                                             0x00007fb4c62bace0,                                         ),                                     ),                                     serializer: Str(                                         StrSerializer,                                     ),                                 },                             ),                         ),                         required: true,                     },                     "delete": SerField {                         key_py: Py(                             0x00007fb4cbf60eb0,                         ),                         alias: None,                         alias_py: None,                         serializer: Some(                             WithDefault(                                 WithDefaultSerializer {                                     default: Default(                                         Py(                                             0x00007fb4c62bad30,                                         ),                                     ),                                     serializer: Str(                                         StrSerializer,                                     ),                                 },                             ),                         ),                         required: true,                     },                 },                 computed_fields: Some(                     ComputedFields(                         [],                     ),                 ),                 mode: SimpleDict,                 extra_serializer: None,                 filter: SchemaFilter {                     include: None,                     exclude: None,                 },                 required_fields: 5,             },         ),         has_extra: false,         root_model: false,         name: "PaginationEmojis",     }, ), definitions=[])

The pydantic-core SchemaSerializer used to dump instances of the model.

__pydantic_validator__: ClassVar[SchemaValidator | PluggableSchemaValidator] = SchemaValidator(title="PaginationEmojis", validator=Model(     ModelValidator {         revalidate: Never,         validator: ModelFields(             ModelFieldsValidator {                 fields: [                     Field {                         name: "first",                         lookup_key: Simple {                             key: "first",                             py_key: Py(                                 0x00007fb4c6119cb0,                             ),                             path: LookupPath(                                 [                                     S(                                         "first",                                         Py(                                             0x00007fb4cb39ec30,                                         ),                                     ),                                 ],                             ),                         },                         name_py: Py(                             0x00007fb4cbbf48b0,                         ),                         validator: WithDefault(                             WithDefaultValidator {                                 default: Default(                                     Py(                                         0x00007fb4c62bac40,                                     ),                                 ),                                 on_error: Raise,                                 validator: Str(                                     StrValidator {                                         strict: false,                                         coerce_numbers_to_str: false,                                     },                                 ),                                 validate_default: false,                                 copy_default: false,                                 name: "default[str]",                                 undefined: Py(                                     0x00007fb4c6b3cb60,                                 ),                             },                         ),                         frozen: false,                     },                     Field {                         name: "left",                         lookup_key: Simple {                             key: "left",                             py_key: Py(                                 0x00007fb4c68b3fb0,                             ),                             path: LookupPath(                                 [                                     S(                                         "left",                                         Py(                                             0x00007fb4c5607fb0,                                         ),                                     ),                                 ],                             ),                         },                         name_py: Py(                             0x00007fb4cbb79730,                         ),                         validator: WithDefault(                             WithDefaultValidator {                                 default: Default(                                     Py(                                         0x00007fb4c62babf0,                                     ),                                 ),                                 on_error: Raise,                                 validator: Str(                                     StrValidator {                                         strict: false,                                         coerce_numbers_to_str: false,                                     },                                 ),                                 validate_default: false,                                 copy_default: false,                                 name: "default[str]",                                 undefined: Py(                                     0x00007fb4c6b3cb60,                                 ),                             },                         ),                         frozen: false,                     },                     Field {                         name: "right",                         lookup_key: Simple {                             key: "right",                             py_key: Py(                                 0x00007fb4c5604430,                             ),                             path: LookupPath(                                 [                                     S(                                         "right",                                         Py(                                             0x00007fb4c5607f30,                                         ),                                     ),                                 ],                             ),                         },                         name_py: Py(                             0x00007fb4cbb796f0,                         ),                         validator: WithDefault(                             WithDefaultValidator {                                 default: Default(                                     Py(                                         0x00007fb4c62bac90,                                     ),                                 ),                                 on_error: Raise,                                 validator: Str(                                     StrValidator {                                         strict: false,                                         coerce_numbers_to_str: false,                                     },                                 ),                                 validate_default: false,                                 copy_default: false,                                 name: "default[str]",                                 undefined: Py(                                     0x00007fb4c6b3cb60,                                 ),                             },                         ),                         frozen: false,                     },                     Field {                         name: "last",                         lookup_key: Simple {                             key: "last",                             py_key: Py(                                 0x00007fb4c5607e70,                             ),                             path: LookupPath(                                 [                                     S(                                         "last",                                         Py(                                             0x00007fb4c56049b0,                                         ),                                     ),                                 ],                             ),                         },                         name_py: Py(                             0x00007fb4cbbd2270,                         ),                         validator: WithDefault(                             WithDefaultValidator {                                 default: Default(                                     Py(                                         0x00007fb4c62bace0,                                     ),                                 ),                                 on_error: Raise,                                 validator: Str(                                     StrValidator {                                         strict: false,                                         coerce_numbers_to_str: false,                                     },                                 ),                                 validate_default: false,                                 copy_default: false,                                 name: "default[str]",                                 undefined: Py(                                     0x00007fb4c6b3cb60,                                 ),                             },                         ),                         frozen: false,                     },                     Field {                         name: "delete",                         lookup_key: Simple {                             key: "delete",                             py_key: Py(                                 0x00007fb4c56046f0,                             ),                             path: LookupPath(                                 [                                     S(                                         "delete",                                         Py(                                             0x00007fb4c5604db0,                                         ),                                     ),                                 ],                             ),                         },                         name_py: Py(                             0x00007fb4cbf60eb0,                         ),                         validator: WithDefault(                             WithDefaultValidator {                                 default: Default(                                     Py(                                         0x00007fb4c62bad30,                                     ),                                 ),                                 on_error: Raise,                                 validator: Str(                                     StrValidator {                                         strict: false,                                         coerce_numbers_to_str: false,                                     },                                 ),                                 validate_default: false,                                 copy_default: false,                                 name: "default[str]",                                 undefined: Py(                                     0x00007fb4c6b3cb60,                                 ),                             },                         ),                         frozen: false,                     },                 ],                 model_name: "PaginationEmojis",                 extra_behavior: Ignore,                 extras_validator: None,                 strict: false,                 from_attributes: false,                 loc_by_alias: true,             },         ),         class: Py(             0x0000556d7f3bc020,         ),         post_init: None,         frozen: false,         custom_init: false,         root_model: false,         undefined: Py(             0x00007fb4c6b3cb60,         ),         name: "PaginationEmojis",     }, ), definitions=[], cache_strings=True)

The pydantic-core SchemaValidator used to validate instances of the model.

__signature__: ClassVar[Signature] = <Signature (*, first: str = '⏮', left: str = '⬅', right: str = '➡', last: str = '⏭', delete: str = '<:trashcan:637136429717389331>') -> None>

The synthesized __init__ [Signature][inspect.Signature] of the model.

model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'delete': FieldInfo(annotation=str, required=False, default='<:trashcan:637136429717389331>'), 'first': FieldInfo(annotation=str, required=False, default='⏮'), 'last': FieldInfo(annotation=str, required=False, default='⏭'), 'left': FieldInfo(annotation=str, required=False, default='⬅'), 'right': FieldInfo(annotation=str, required=False, default='➡')}

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

exception StartupError(base)[source]

Bases: Exception

Exception class for startup errors.

__init__(base)[source]

Subpackages

Submodules