Changelog#

+
+

Next 10.x feature release

+

10.6.0 30th January 2024

  • [Feature] #199: Port common discord.commands checks from other bots to pydis_core.utils.checks.

  • diff --git a/main/genindex.html b/main/genindex.html index b8c63e89..b5269ff4 100644 --- a/main/genindex.html +++ b/main/genindex.html @@ -1023,6 +1023,8 @@
diff --git a/main/objects.inv b/main/objects.inv index b1b9755e..d99c7f40 100644 Binary files a/main/objects.inv and b/main/objects.inv differ diff --git a/main/output/pydis_core.async_stats.html b/main/output/pydis_core.async_stats.html index 3c522f64..e5f08484 100644 --- a/main/output/pydis_core.async_stats.html +++ b/main/output/pydis_core.async_stats.html @@ -450,12 +450,12 @@

An async transport method for statsd communication.

-class AsyncStatsClient(loop, host='localhost', port=8125, prefix=None)[source]#
+class AsyncStatsClient(loop, host='localhost', port=8125, prefix=None)[source]#

Bases: StatsClientBase

An async implementation of statsd.client.base.StatsClientBase that supports async stat communication.

-__init__(loop, host='localhost', port=8125, prefix=None)[source]#
+__init__(loop, host='localhost', port=8125, prefix=None)[source]#

Create a new AsyncStatsClient.

Parameters:
@@ -472,7 +472,7 @@
-async create_socket()[source]#
+async create_socket()[source]#

Use asyncio.loop.create_datagram_endpoint from the loop given on init to create a socket.

Return type:
diff --git a/main/output/pydis_core.html b/main/output/pydis_core.html index 77f4abeb..8312a81d 100644 --- a/main/output/pydis_core.html +++ b/main/output/pydis_core.html @@ -450,12 +450,12 @@

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]#
+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.

-__init__(*args, guild_id, allowed_roles, http_session, redis_session=None, api_client=None, statsd_url=None, **kwargs)[source]#
+__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:
@@ -474,7 +474,7 @@ a dummy statsd client will be created.

-async add_cog(cog)[source]#
+async add_cog(cog)[source]#

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

Return type:
@@ -485,7 +485,7 @@ a dummy statsd client will be created.

-add_command(command)[source]#
+add_command(command)[source]#

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

Return type:
@@ -496,7 +496,7 @@ a dummy statsd client will be created.

-clear()[source]#
+clear()[source]#

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

Return type:
@@ -507,7 +507,7 @@ a dummy statsd client will be created.

-async close()[source]#
+async close()[source]#

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

Return type:
@@ -518,7 +518,7 @@ a dummy statsd client will be created.

-async load_extensions(module, sync_app_commands=True)[source]#
+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:
@@ -532,7 +532,7 @@ a dummy statsd client will be created.

-async log_to_dev_log(message)[source]#
+async log_to_dev_log(message)[source]#

Log the given message to #dev-log.

Return type:
@@ -543,7 +543,7 @@ a dummy statsd client will be created.

-async on_guild_available(guild)[source]#
+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.

@@ -556,7 +556,7 @@ will not be set and guild_available_but_cache_empty event will be e
-async on_guild_unavailable(guild)[source]#
+async on_guild_unavailable(guild)[source]#

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

Return type:
@@ -567,7 +567,7 @@ will not be set and guild_available_but_cache_empty event will be e
-async ping_services()[source]#
+async ping_services()[source]#

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

Return type:
@@ -578,7 +578,7 @@ will not be set and guild_available_but_cache_empty event will be e
-async process_commands(message)[source]#
+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.

@@ -590,7 +590,7 @@ will not be set and guild_available_but_cache_empty event will be e
-remove_command(name)[source]#
+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.

@@ -603,7 +603,7 @@ To remove them, either remove the entire command or manually edit bot.all_
-async setup_hook()[source]#
+async setup_hook()[source]#

An async init to startup generic services.

Connects to statsd, and calls AsyncStatsClient.create_socket @@ -617,7 +617,7 @@ and

-async wait_until_guild_available()[source]#
+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.

@@ -632,14 +632,14 @@ gateway event before giving up and thus not populating the cache for unavailable
-exception EmptyPaginatorEmbedError[source]#
+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]#
+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.

@@ -656,14 +656,14 @@ gateway event before giving up and thus not populating the cache for unavailable
-__init__(prefix='```', suffix='```', max_size=4000, scale_to_size=4000, max_lines=None, linesep='\\n')[source]#
+__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]#
+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 @@ -691,7 +691,7 @@ page at a reasonable size.

-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]#
+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 @@ -735,7 +735,7 @@ to any user with a moderation role.

-class PaginationEmojis(**data)[source]#
+class PaginationEmojis(**data)[source]#

Bases: BaseModel

The emojis that will be used for pagination.

@@ -756,12 +756,12 @@ mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].
-exception StartupError(base)[source]#
+exception StartupError(base)[source]#

Bases: Exception

Exception class for startup errors.

-__init__(base)[source]#
+__init__(base)[source]#
@@ -817,6 +817,7 @@ mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].interactions
  • logging
      diff --git a/main/output/pydis_core.site_api.html b/main/output/pydis_core.site_api.html index 844f5189..c622e8d9 100644 --- a/main/output/pydis_core.site_api.html +++ b/main/output/pydis_core.site_api.html @@ -450,12 +450,12 @@

      An API wrapper around the Site API.

      -class APIClient(site_api_url, site_api_token, **session_kwargs)[source]#
      +class APIClient(site_api_url, site_api_token, **session_kwargs)[source]#

      Bases: object

      A wrapper for the Django Site API.

      -__init__(site_api_url, site_api_token, **session_kwargs)[source]#
      +__init__(site_api_url, site_api_token, **session_kwargs)[source]#

      Initialize a new APIClient instance.

      Parameters:
      @@ -470,7 +470,7 @@
      -async close()[source]#
      +async close()[source]#

      Close the aiohttp session.

      Return type:
      @@ -481,7 +481,7 @@
      -async delete(endpoint, *, raise_for_status=True, **kwargs)[source]#
      +async delete(endpoint, *, raise_for_status=True, **kwargs)[source]#

      Equivalent to APIClient.request() with DELETE passed as the method.

      Return type:
      @@ -492,7 +492,7 @@
      -async get(endpoint, *, raise_for_status=True, **kwargs)[source]#
      +async get(endpoint, *, raise_for_status=True, **kwargs)[source]#

      Equivalent to APIClient.request() with GET passed as the method.

      Return type:
      @@ -503,7 +503,7 @@
      -async static maybe_raise_for_status(response, should_raise)[source]#
      +async static maybe_raise_for_status(response, should_raise)[source]#

      Raise ResponseCodeError for non-OK response if an exception should be raised.

      Parameters:
      @@ -523,7 +523,7 @@
      -async patch(endpoint, *, raise_for_status=True, **kwargs)[source]#
      +async patch(endpoint, *, raise_for_status=True, **kwargs)[source]#

      Equivalent to APIClient.request() with PATCH passed as the method.

      Return type:
      @@ -534,7 +534,7 @@
      -async post(endpoint, *, raise_for_status=True, **kwargs)[source]#
      +async post(endpoint, *, raise_for_status=True, **kwargs)[source]#

      Equivalent to APIClient.request() with POST passed as the method.

      Return type:
      @@ -545,7 +545,7 @@
      -async put(endpoint, *, raise_for_status=True, **kwargs)[source]#
      +async put(endpoint, *, raise_for_status=True, **kwargs)[source]#

      Equivalent to APIClient.request() with PUT passed as the method.

      Return type:
      @@ -556,7 +556,7 @@
      -async request(method, endpoint, *, raise_for_status=True, **kwargs)[source]#
      +async request(method, endpoint, *, raise_for_status=True, **kwargs)[source]#

      Send an HTTP request to the site API and return the JSON response.

      Parameters:
      @@ -583,12 +583,12 @@
      -exception ResponseCodeError(response, response_json=None, response_text=None)[source]#
      +exception ResponseCodeError(response, response_json=None, response_text=None)[source]#

      Bases: ValueError

      Raised in APIClient.request() when a non-OK HTTP response is received.

      -__init__(response, response_json=None, response_text=None)[source]#
      +__init__(response, response_json=None, response_text=None)[source]#

      Initialize a new ResponseCodeError instance.

      Parameters:
      @@ -603,7 +603,7 @@
      -__str__()[source]#
      +__str__()[source]#

      Return a string representation of the error.

      diff --git a/main/output/pydis_core.utils.caching.html b/main/output/pydis_core.utils.caching.html index 684c7a05..94861e3e 100644 --- a/main/output/pydis_core.utils.caching.html +++ b/main/output/pydis_core.utils.caching.html @@ -450,14 +450,14 @@

      Utilities related to custom caches.

      -class AsyncCache(max_size=128)[source]#
      +class AsyncCache(max_size=128)[source]#

      Bases: object

      LRU cache implementation for coroutines.

      Once the cache exceeds the maximum size, keys are deleted in FIFO order.

      An offset may be optionally provided to be applied to the coroutine’s arguments when creating the cache key.

      -__call__(arg_offset=0)[source]#
      +__call__(arg_offset=0)[source]#

      Decorator for async cache.

      Parameters:
      @@ -474,7 +474,7 @@
      -__init__(max_size=128)[source]#
      +__init__(max_size=128)[source]#

      Initialise a new AsyncCache instance.

      Parameters:
      @@ -485,7 +485,7 @@
      -clear()[source]#
      +clear()[source]#

      Clear cache instance.

      Return type:
      diff --git a/main/output/pydis_core.utils.channel.html b/main/output/pydis_core.utils.channel.html index d260df53..2f151810 100644 --- a/main/output/pydis_core.utils.channel.html +++ b/main/output/pydis_core.utils.channel.html @@ -450,7 +450,7 @@

      Useful helper functions for interacting with various discord channel objects.

      -async get_or_fetch_channel(bot, channel_id)[source]#
      +async get_or_fetch_channel(bot, channel_id)[source]#

      Attempt to get or fetch the given channel_id from the bots cache, and return it.

      Parameters:
      @@ -478,7 +478,7 @@
      -is_in_category(channel, category_id)[source]#
      +is_in_category(channel, category_id)[source]#

      Return whether the given channel in the the category with the id category_id.

      Parameters:
      diff --git a/main/output/pydis_core.utils.checks.html b/main/output/pydis_core.utils.checks.html index 7b97beef..5f174cdd 100644 --- a/main/output/pydis_core.utils.checks.html +++ b/main/output/pydis_core.utils.checks.html @@ -449,26 +449,26 @@

      checks#

      -exception ContextCheckFailure(redirect_channel)[source]#
      +exception ContextCheckFailure(redirect_channel)[source]#

      Bases: CheckFailure

      Raised when a context-specific check fails.

      -__init__(redirect_channel)[source]#
      +__init__(redirect_channel)[source]#
      -exception InWhitelistCheckFailure(redirect_channel)[source]#
      +exception InWhitelistCheckFailure(redirect_channel)[source]#

      Bases: ContextCheckFailure

      Raised when the in_whitelist check fails.

      -cooldown_with_role_bypass(rate, per, type=('default', 0), *, bypass_roles)[source]#
      +cooldown_with_role_bypass(rate, per, type=('default', 0), *, bypass_roles)[source]#

      Decorate a command to have a cooldown, which can be bypassed by users with specified roles.

      Note: This replaces the Command.before_invoke callback, which might introduce problems in the future.

      @@ -494,7 +494,7 @@
      -async has_any_role_check(ctx, *roles)[source]#
      +async has_any_role_check(ctx, *roles)[source]#

      Verify if the context’s author has any of the specified roles.

      This check will always fail if the context is a DM, since DMs don’t have roles.

      @@ -515,7 +515,7 @@
      -async has_no_roles_check(ctx, *roles)[source]#
      +async has_no_roles_check(ctx, *roles)[source]#

      Verify if the context’s author doesn’t have any of the specified roles.

      This check will always fail if the context is a DM, since DMs don’t have roles.

      @@ -536,7 +536,7 @@
      -in_whitelist_check(ctx, redirect, channels=(), categories=(), roles=(), fail_silently=False)[source]#
      +in_whitelist_check(ctx, redirect, channels=(), categories=(), roles=(), fail_silently=False)[source]#

      Check if a command was issued in a context that is whitelisted by channel, category, or roles.

      Parameters:
      diff --git a/main/output/pydis_core.utils.commands.html b/main/output/pydis_core.utils.commands.html index 628546f5..d9abc2f8 100644 --- a/main/output/pydis_core.utils.commands.html +++ b/main/output/pydis_core.utils.commands.html @@ -449,7 +449,7 @@

      commands#

      -async clean_text_or_reply(ctx, text=None)[source]#
      +async clean_text_or_reply(ctx, text=None)[source]#

      Cleans a text argument or replied message’s content.

      Parameters:
      diff --git a/main/output/pydis_core.utils.cooldown.html b/main/output/pydis_core.utils.cooldown.html index 4518a644..ae0b62fb 100644 --- a/main/output/pydis_core.utils.cooldown.html +++ b/main/output/pydis_core.utils.cooldown.html @@ -450,17 +450,17 @@

      Helpers for setting a cooldown on commands.

      -exception CommandOnCooldown(message, function, /, *args, **kwargs)[source]#
      +exception CommandOnCooldown(message, function, /, *args, **kwargs)[source]#

      Bases: CommandError, Generic[P, R]

      Raised when a command is invoked while on cooldown.

      -__init__(message, function, /, *args, **kwargs)[source]#
      +__init__(message, function, /, *args, **kwargs)[source]#
      -async call_without_cooldown()[source]#
      +async call_without_cooldown()[source]#

      Run the command this cooldown blocked.

      Return type:
      @@ -476,20 +476,20 @@
      -P = ~P[source]#
      +P = ~P[source]#

      The command’s signature.

      -class R[source]#
      +class R[source]#

      The command’s return value.

      alias of TypeVar(‘R’)

      -block_duplicate_invocations(*, cooldown_duration=5, send_notice=False, args_preprocessor=None)[source]#
      +block_duplicate_invocations(*, cooldown_duration=5, send_notice=False, args_preprocessor=None)[source]#

      Prevent duplicate invocations of a command with the same arguments in a channel for cooldown_duration seconds.

      Parameters:
      diff --git a/main/output/pydis_core.utils.error_handling.html b/main/output/pydis_core.utils.error_handling.html index 2b4cfd85..039a7f4c 100644 --- a/main/output/pydis_core.utils.error_handling.html +++ b/main/output/pydis_core.utils.error_handling.html @@ -449,7 +449,7 @@

      error_handling#

      -async handle_forbidden_from_block(error, message=None)[source]#
      +async handle_forbidden_from_block(error, message=None)[source]#

      Handles discord.Forbidden 90001 errors, or re-raises if error isn’t a 90001 error.

      Parameters:
      diff --git a/main/output/pydis_core.utils.function.html b/main/output/pydis_core.utils.function.html index 6b2295bd..2f1ab2dd 100644 --- a/main/output/pydis_core.utils.function.html +++ b/main/output/pydis_core.utils.function.html @@ -450,14 +450,14 @@

      Utils for manipulating functions.

      -exception GlobalNameConflictError[source]#
      +exception GlobalNameConflictError[source]#

      Bases: Exception

      Raised on a conflict between the globals used to resolve annotations of a wrapped function and its wrapper.

      -command_wraps(wrapped, assigned=('__module__', '__name__', '__qualname__', '__doc__', '__annotations__'), updated=('__dict__',), *, ignored_conflict_names=frozenset({}))[source]#
      +command_wraps(wrapped, assigned=('__module__', '__name__', '__qualname__', '__doc__', '__annotations__'), updated=('__dict__',), *, ignored_conflict_names=frozenset({}))[source]#

      Update the decorated function to look like wrapped, and update globals for discord.py forwardref evaluation.

      See update_wrapper_globals() for more details on how the globals are updated.

      @@ -481,7 +481,7 @@ with the wrapper replaced with the function
      -update_wrapper_globals(wrapper, wrapped, *, ignored_conflict_names=frozenset({}))[source]#
      +update_wrapper_globals(wrapper, wrapped, *, ignored_conflict_names=frozenset({}))[source]#

      Create a copy of wrapper, the copy’s globals are updated with wrapped's globals.

      For forwardrefs in command annotations, discord.py uses the __global__ attribute of the function to resolve their values. This breaks for decorators that replace the function because they have diff --git a/main/output/pydis_core.utils.html b/main/output/pydis_core.utils.html index 72d683df..75085048 100644 --- a/main/output/pydis_core.utils.html +++ b/main/output/pydis_core.utils.html @@ -450,7 +450,7 @@

      Useful utilities and tools for Discord bot development.

      -apply_monkey_patches()[source]#
      +apply_monkey_patches()[source]#

      Applies all common monkey patches for our bots.

      Return type:
      @@ -469,7 +469,7 @@ that will act as top-level groups rather than being aliases of the command’s g
      -unqualify(name)[source]#
      +unqualify(name)[source]#

      Return an unqualified name given a qualified module/package name.

      Parameters:
      @@ -552,6 +552,7 @@ that will act as top-level groups rather than being aliases of the command’s g
    • ViewWithUserAndRoleCheck.stop()
  • +
  • user_has_access()
  • logging
      diff --git a/main/output/pydis_core.utils.interactions.html b/main/output/pydis_core.utils.interactions.html index 4c06273f..ed668f22 100644 --- a/main/output/pydis_core.utils.interactions.html +++ b/main/output/pydis_core.utils.interactions.html @@ -449,7 +449,7 @@

      interactions#

      -class DeleteMessageButton(*, style=('secondary', 2), label='Delete', **kwargs)[source]#
      +class DeleteMessageButton(*, style=('secondary', 2), label='Delete', **kwargs)[source]#

      Bases: Button

      A button that can be added to a view to delete the message containing the view on click.

      This button itself carries out no interaction checks, these should be done by the parent view.

      @@ -464,12 +464,12 @@
      -__init__(*, style=('secondary', 2), label='Delete', **kwargs)[source]#
      +__init__(*, style=('secondary', 2), label='Delete', **kwargs)[source]#
      -async callback(interaction)[source]#
      +async callback(interaction)[source]#

      Delete the original message on button click.

      Return type:
      @@ -482,7 +482,7 @@
      -class ViewWithUserAndRoleCheck(*, allowed_users, allowed_roles, timeout=180.0, message=None)[source]#
      +class ViewWithUserAndRoleCheck(*, allowed_users, allowed_roles, timeout=180.0, message=None)[source]#

      Bases: View

      A view that allows the original invoker and moderators to interact with it.

      @@ -499,12 +499,12 @@ If None
      -__init__(*, allowed_users, allowed_roles, timeout=180.0, message=None)[source]#
      +__init__(*, allowed_users, allowed_roles, timeout=180.0, message=None)[source]#
      -async interaction_check(interaction)[source]#
      +async interaction_check(interaction)[source]#

      Ensure the user clicking the button is the view invoker, or a moderator.

      Parameters:
      @@ -518,7 +518,7 @@ If None
      -async on_timeout()[source]#
      +async on_timeout()[source]#

      Remove the view from self.message if set.

      Return type:
      @@ -529,7 +529,7 @@ If None
      -stop()[source]#
      +stop()[source]#

      Stop listening for interactions, and remove the view from self.message if set.

      Return type:
      @@ -540,6 +540,24 @@ If None
      +
      +
      +user_has_access(user, *, allowed_users=(), allowed_roles=())[source]#
      +

      Return whether the user is in the allowed_users list, or has a role from allowed_roles.

      +
      +
      Parameters:
      +
        +
      • user (User | Member) – The user to check

      • +
      • allowed_users (Sequence[int]) – A sequence of user ids that are allowed access

      • +
      • allowed_roles (Sequence[int]) – A sequence of role ids that are allowed access

      • +
      +
      +
      Return type:
      +

      bool

      +
      +
      +
      +