Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into fix/route-param-uriencode
Browse files Browse the repository at this point in the history
shiftinv authored Dec 29, 2024
2 parents 8b72790 + 6cde332 commit 873a156
Showing 46 changed files with 881 additions and 197 deletions.
4 changes: 2 additions & 2 deletions changelog/1113.feature.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Support application subscriptions and one-time purchases (see the :ddocs:`official docs <monetization/overview>` for more info).
- New types: :class:`SKU`, :class:`Entitlement`.
- New types: :class:`SKU`, :class:`Entitlement`, :class:`Subscription`.
- New :attr:`Interaction.entitlements` attribute, and :meth:`InteractionResponse.require_premium` response type.
- New events: :func:`on_entitlement_create`, :func:`on_entitlement_update`, :func:`on_entitlement_delete`.
- New events: :func:`on_entitlement_create`, :func:`on_entitlement_update`, :func:`on_entitlement_delete`, :func:`on_subscription_create`, :func:`on_subscription_update` and :func:`on_subscription_delete`.
- New :class:`Client` methods: :meth:`~Client.skus`, :meth:`~Client.entitlements`, :meth:`~Client.fetch_entitlement`, :meth:`~Client.create_entitlement`.
1 change: 1 addition & 0 deletions changelog/1173.feature.rst
Original file line number Diff line number Diff line change
@@ -11,3 +11,4 @@ Add support for user-installed commands. See :ref:`app_command_contexts` for fur
- |commands| Add ``install_types`` and ``contexts`` parameters to application command decorators.
- |commands| Add :func:`~ext.commands.install_types` and :func:`~ext.commands.contexts` decorators.
- |commands| Using the :class:`GuildCommandInteraction` annotation now sets :attr:`~ApplicationCommand.install_types` and :attr:`~ApplicationCommand.contexts`, instead of :attr:`~ApplicationCommand.dm_permission`.
- |commands| Add ``default_install_types`` and ``default_contexts`` parameters to :class:`~ext.commands.Bot`.
4 changes: 2 additions & 2 deletions changelog/1186.feature.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Support application subscriptions and one-time purchases (see the :ddocs:`official docs <monetization/overview>` for more info).
- New types: :class:`SKU`, :class:`Entitlement`.
- New types: :class:`SKU`, :class:`Entitlement`, :class:`Subscription`.
- New :attr:`Interaction.entitlements` attribute, and :meth:`InteractionResponse.require_premium` response type.
- New events: :func:`on_entitlement_create`, :func:`on_entitlement_update`, :func:`on_entitlement_delete`.
- New events: :func:`on_entitlement_create`, :func:`on_entitlement_update`, :func:`on_entitlement_delete`, :func:`on_subscription_create`, :func:`on_subscription_update` and :func:`on_subscription_delete`.
- New :class:`Client` methods: :meth:`~Client.skus`, :meth:`~Client.entitlements`, :meth:`~Client.fetch_entitlement`, :meth:`~Client.create_entitlement`.
1 change: 1 addition & 0 deletions changelog/1190.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The ``cls`` parameter of UI component decorators (such as :func:`ui.button`) now accepts any matching callable, in addition to item subclasses.
4 changes: 2 additions & 2 deletions changelog/1249.feature.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Support application subscriptions and one-time purchases (see the :ddocs:`official docs <monetization/overview>` for more info).
- New types: :class:`SKU`, :class:`Entitlement`.
- New types: :class:`SKU`, :class:`Entitlement`, :class:`Subscription`.
- New :attr:`Interaction.entitlements` attribute, and :meth:`InteractionResponse.require_premium` response type.
- New events: :func:`on_entitlement_create`, :func:`on_entitlement_update`, :func:`on_entitlement_delete`.
- New events: :func:`on_entitlement_create`, :func:`on_entitlement_update`, :func:`on_entitlement_delete`, :func:`on_subscription_create`, :func:`on_subscription_update` and :func:`on_subscription_delete`.
- New :class:`Client` methods: :meth:`~Client.skus`, :meth:`~Client.entitlements`, :meth:`~Client.fetch_entitlement`, :meth:`~Client.create_entitlement`.
5 changes: 5 additions & 0 deletions changelog/1257.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Support application subscriptions and one-time purchases (see the :ddocs:`official docs <monetization/overview>` for more info).
- New types: :class:`SKU`, :class:`Entitlement`, :class:`Subscription`.
- New :attr:`Interaction.entitlements` attribute, and :meth:`InteractionResponse.require_premium` response type.
- New events: :func:`on_entitlement_create`, :func:`on_entitlement_update`, :func:`on_entitlement_delete`, :func:`on_subscription_create`, :func:`on_subscription_update` and :func:`on_subscription_delete`.
- New :class:`Client` methods: :meth:`~Client.skus`, :meth:`~Client.entitlements`, :meth:`~Client.fetch_entitlement`, :meth:`~Client.create_entitlement`.
14 changes: 14 additions & 0 deletions changelog/1261.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Add support for user-installed commands. See :ref:`app_command_contexts` for further details.
- Add :attr:`ApplicationCommand.install_types` and :attr:`ApplicationCommand.contexts` fields,
with respective :class:`ApplicationInstallTypes` and :class:`InteractionContextTypes` flag types.
- :class:`Interaction` changes:
- Add :attr:`Interaction.context` field, reflecting the context in which the interaction occurred.
- Add :attr:`Interaction.authorizing_integration_owners` field and :class:`AuthorizingIntegrationOwners` class, containing details about the application installation.
- :attr:`Interaction.app_permissions` is now always provided by Discord.
- Add :attr:`Message.interaction_metadata` and :class:`InteractionMetadata` type, containing metadata for the interaction associated with a message.
- Add ``integration_type`` parameter to :func:`utils.oauth_url`.
- Add :attr:`AppInfo.guild_install_type_config` and :attr:`AppInfo.user_install_type_config` fields.
- |commands| Add ``install_types`` and ``contexts`` parameters to application command decorators.
- |commands| Add :func:`~ext.commands.install_types` and :func:`~ext.commands.contexts` decorators.
- |commands| Using the :class:`GuildCommandInteraction` annotation now sets :attr:`~ApplicationCommand.install_types` and :attr:`~ApplicationCommand.contexts`, instead of :attr:`~ApplicationCommand.dm_permission`.
- |commands| Add ``default_install_types`` and ``default_contexts`` parameters to :class:`~ext.commands.Bot`.
1 change: 1 addition & 0 deletions changelog/914.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix :class:`ui.Modal` timeout issues with long-running callbacks, and multiple modals with the same user and ``custom_id``.
1 change: 1 addition & 0 deletions disnake/__init__.py
Original file line number Diff line number Diff line change
@@ -66,6 +66,7 @@
from .soundboard import *
from .stage_instance import *
from .sticker import *
from .subscription import *
from .team import *
from .template import *
from .threads import *
37 changes: 34 additions & 3 deletions disnake/app_commands.py
Original file line number Diff line number Diff line change
@@ -547,6 +547,13 @@ def __init__(
self.install_types: Optional[ApplicationInstallTypes] = install_types
self.contexts: Optional[InteractionContextTypes] = contexts

# TODO(3.0): refactor
# These are for ext.commands defaults. It's quite ugly to do it this way,
# but since __eq__ and to_dict functionality is encapsulated here and can't be moved trivially,
# it'll do until the presumably soon-ish refactor of the entire commands framework.
self._default_install_types: Optional[ApplicationInstallTypes] = None
self._default_contexts: Optional[InteractionContextTypes] = None

self._always_synced: bool = False

# reset `default_permission` if set before
@@ -614,6 +621,9 @@ def __str__(self) -> str:
return self.name

def __eq__(self, other) -> bool:
if not isinstance(other, ApplicationCommand):
return False

if not (
self.type == other.type
and self.name == other.name
@@ -634,8 +644,10 @@ def __eq__(self, other) -> bool:
# `contexts` takes priority over `dm_permission`;
# ignore `dm_permission` if `contexts` is set,
# since the API returns both even when only `contexts` was provided
if self.contexts is not None or other.contexts is not None:
if self.contexts != other.contexts:
self_contexts = self._contexts_with_default
other_contexts = other._contexts_with_default
if self_contexts is not None or other_contexts is not None:
if self_contexts != other_contexts:
return False
else:
# this is a bit awkward; `None` is equivalent to `True` in this case
@@ -648,6 +660,9 @@ def __eq__(self, other) -> bool:
def _install_types_with_default(self) -> Optional[ApplicationInstallTypes]:
# if this is an api-provided command object, keep things as-is
if self.install_types is None and not isinstance(self, _APIApplicationCommandMixin):
if self._default_install_types is not None:
return self._default_install_types

# The purpose of this default is to avoid re-syncing after the updating to the new version,
# at least as long as the user hasn't enabled user installs in the dev portal
# (i.e. if they haven't, the api defaults to this value as well).
@@ -658,6 +673,20 @@ def _install_types_with_default(self) -> Optional[ApplicationInstallTypes]:

return self.install_types

@property
def _contexts_with_default(self) -> Optional[InteractionContextTypes]:
# (basically the same logic as `_install_types_with_default`, but without a fallback)
if (
self.contexts is None
and not isinstance(self, _APIApplicationCommandMixin)
and self._default_contexts is not None
# only use default if legacy `dm_permission` wasn't set
and self._dm_permission is None
):
return self._default_contexts

return self.contexts

def to_dict(self) -> EditApplicationCommandPayload:
data: EditApplicationCommandPayload = {
"type": try_enum_to_int(self.type),
@@ -678,7 +707,9 @@ def to_dict(self) -> EditApplicationCommandPayload:
)
data["integration_types"] = install_types

contexts = self.contexts.values if self.contexts is not None else None
contexts = (
self._contexts_with_default.values if self._contexts_with_default is not None else None
)
data["contexts"] = contexts

# don't set `dm_permission` if `contexts` is set
2 changes: 1 addition & 1 deletion disnake/client.py
Original file line number Diff line number Diff line change
@@ -3180,7 +3180,7 @@ async def skus(self) -> List[SKU]:
The list of SKUs.
"""
data = await self.http.get_skus(self.application_id)
return [SKU(data=d) for d in data]
return [SKU(data=d, state=self._connection) for d in data]

def entitlements(
self,
1 change: 0 additions & 1 deletion disnake/entitlement.py
Original file line number Diff line number Diff line change
@@ -76,7 +76,6 @@ class Entitlement(Hashable):
Set to ``None`` when this is a test entitlement.
ends_at: Optional[:class:`datetime.datetime`]
The time at which the entitlement stops being active.
Set to ``None`` when this is a test entitlement.
You can use :meth:`is_active` to check whether this entitlement is still active.
"""
24 changes: 23 additions & 1 deletion disnake/enums.py
Original file line number Diff line number Diff line change
@@ -72,6 +72,7 @@
"OnboardingPromptType",
"SKUType",
"EntitlementType",
"SubscriptionStatus",
"PollLayoutType",
"VoiceChannelEffectAnimationType",
"MessageReferenceType",
@@ -1340,7 +1341,22 @@ class Event(Enum):
"""
entitlement_delete = "entitlement_delete"
"""Called when a user's entitlement is deleted.
Represents the :func:`on_entitlement_delete` event.
Represents the :func:`on_entitlement_delete` event."""
subscription_create = "subscription_create"
"""Called when a subscription for a premium app is created.
Represents the :func:`on_subscription_create` event.
.. versionadded:: 2.10
"""
subscription_update = "subscription_update"
"""Called when a subscription for a premium app is updated.
Represents the :func:`on_subscription_update` event.
.. versionadded:: 2.10
"""
subscription_delete = "subscription_delete"
"""Called when a subscription for a premium app is deleted.
Represents the :func:`on_subscription_delete` event.
.. versionadded:: 2.10
"""
@@ -1429,6 +1445,12 @@ class EntitlementType(Enum):
application_subscription = 8


class SubscriptionStatus(Enum):
active = 0
ending = 1
inactive = 2


class PollLayoutType(Enum):
default = 1

5 changes: 5 additions & 0 deletions disnake/ext/commands/base_core.py
Original file line number Diff line number Diff line change
@@ -36,6 +36,7 @@

from ._types import AppCheck, Coro, Error, Hook
from .cog import Cog
from .interaction_bot_base import InteractionBotBase

ApplicationCommandInteractionT = TypeVar(
"ApplicationCommandInteractionT", bound=ApplicationCommandInteraction, covariant=True
@@ -268,6 +269,10 @@ def _apply_guild_only(self) -> None:
self.body.contexts = InteractionContextTypes(guild=True)
self.body.install_types = ApplicationInstallTypes(guild=True)

def _apply_defaults(self, bot: InteractionBotBase) -> None:
self.body._default_install_types = bot._default_install_types
self.body._default_contexts = bot._default_contexts

@property
def dm_permission(self) -> bool:
""":class:`bool`: Whether this command can be used in DMs."""
67 changes: 62 additions & 5 deletions disnake/ext/commands/bot.py
Original file line number Diff line number Diff line change
@@ -18,7 +18,12 @@
from disnake.activity import BaseActivity
from disnake.client import GatewayParams
from disnake.enums import Status
from disnake.flags import Intents, MemberCacheFlags
from disnake.flags import (
ApplicationInstallTypes,
Intents,
InteractionContextTypes,
MemberCacheFlags,
)
from disnake.i18n import LocalizationProtocol
from disnake.mentions import AllowedMentions
from disnake.message import Message
@@ -117,6 +122,28 @@ class Bot(BotBase, InteractionBotBase, disnake.Client):
.. versionadded:: 2.5
default_install_types: Optional[:class:`.ApplicationInstallTypes`]
The default installation types where application commands will be available.
This applies to all commands added either through the respective decorators
or directly using :meth:`.add_slash_command` (etc.).
Any value set directly on the command, e.g. using the :func:`.install_types` decorator,
the ``install_types`` parameter, ``slash_command_attrs`` (etc.) at the cog-level, or from
the :class:`.GuildCommandInteraction` annotation, takes precedence over this default.
.. versionadded:: 2.10
default_contexts: Optional[:class:`.InteractionContextTypes`]
The default contexts where application commands will be usable.
This applies to all commands added either through the respective decorators
or directly using :meth:`.add_slash_command` (etc.).
Any value set directly on the command, e.g. using the :func:`.contexts` decorator,
the ``contexts`` parameter, ``slash_command_attrs`` (etc.) at the cog-level, or from
the :class:`.GuildCommandInteraction` annotation, takes precedence over this default.
.. versionadded:: 2.10
Attributes
----------
command_prefix
@@ -233,10 +260,12 @@ def __init__(
reload: bool = False,
case_insensitive: bool = False,
command_sync_flags: CommandSyncFlags = ...,
test_guilds: Optional[Sequence[int]] = None,
sync_commands: bool = ...,
sync_commands_debug: bool = ...,
sync_commands_on_cog_unload: bool = ...,
test_guilds: Optional[Sequence[int]] = None,
default_install_types: Optional[ApplicationInstallTypes] = None,
default_contexts: Optional[InteractionContextTypes] = None,
asyncio_debug: bool = False,
loop: Optional[asyncio.AbstractEventLoop] = None,
shard_id: Optional[int] = None,
@@ -285,10 +314,12 @@ def __init__(
reload: bool = False,
case_insensitive: bool = False,
command_sync_flags: CommandSyncFlags = ...,
test_guilds: Optional[Sequence[int]] = None,
sync_commands: bool = ...,
sync_commands_debug: bool = ...,
sync_commands_on_cog_unload: bool = ...,
test_guilds: Optional[Sequence[int]] = None,
default_install_types: Optional[ApplicationInstallTypes] = None,
default_contexts: Optional[InteractionContextTypes] = None,
asyncio_debug: bool = False,
loop: Optional[asyncio.AbstractEventLoop] = None,
shard_ids: Optional[List[int]] = None, # instead of shard_id
@@ -391,6 +422,28 @@ class InteractionBot(InteractionBotBase, disnake.Client):
.. versionadded:: 2.5
default_install_types: Optional[:class:`.ApplicationInstallTypes`]
The default installation types where application commands will be available.
This applies to all commands added either through the respective decorators
or directly using :meth:`.add_slash_command` (etc.).
Any value set directly on the command, e.g. using the :func:`.install_types` decorator,
the ``install_types`` parameter, ``slash_command_attrs`` (etc.) at the cog-level, or from
the :class:`.GuildCommandInteraction` annotation, takes precedence over this default.
.. versionadded:: 2.10
default_contexts: Optional[:class:`.InteractionContextTypes`]
The default contexts where application commands will be usable.
This applies to all commands added either through the respective decorators
or directly using :meth:`.add_slash_command` (etc.).
Any value set directly on the command, e.g. using the :func:`.contexts` decorator,
the ``contexts`` parameter, ``slash_command_attrs`` (etc.) at the cog-level, or from
the :class:`.GuildCommandInteraction` annotation, takes precedence over this default.
.. versionadded:: 2.10
Attributes
----------
owner_id: Optional[:class:`int`]
@@ -434,10 +487,12 @@ def __init__(
owner_ids: Optional[Set[int]] = None,
reload: bool = False,
command_sync_flags: CommandSyncFlags = ...,
test_guilds: Optional[Sequence[int]] = None,
sync_commands: bool = ...,
sync_commands_debug: bool = ...,
sync_commands_on_cog_unload: bool = ...,
test_guilds: Optional[Sequence[int]] = None,
default_install_types: Optional[ApplicationInstallTypes] = None,
default_contexts: Optional[InteractionContextTypes] = None,
asyncio_debug: bool = False,
loop: Optional[asyncio.AbstractEventLoop] = None,
shard_id: Optional[int] = None,
@@ -479,10 +534,12 @@ def __init__(
owner_ids: Optional[Set[int]] = None,
reload: bool = False,
command_sync_flags: CommandSyncFlags = ...,
test_guilds: Optional[Sequence[int]] = None,
sync_commands: bool = ...,
sync_commands_debug: bool = ...,
sync_commands_on_cog_unload: bool = ...,
test_guilds: Optional[Sequence[int]] = None,
default_install_types: Optional[ApplicationInstallTypes] = None,
default_contexts: Optional[InteractionContextTypes] = None,
asyncio_debug: bool = False,
loop: Optional[asyncio.AbstractEventLoop] = None,
shard_ids: Optional[List[int]] = None, # instead of shard_id
4 changes: 3 additions & 1 deletion disnake/ext/commands/cooldowns.py
Original file line number Diff line number Diff line change
@@ -49,7 +49,9 @@ def get_key(self, msg: Message) -> Any:
elif self is BucketType.role:
# if author is not a Member we are in a private-channel context; returning its id
# yields the same result as for a guild with only the @everyone role
return (msg.author.top_role if isinstance(msg.author, Member) else msg.channel).id
return (
msg.author.top_role if msg.guild and isinstance(msg.author, Member) else msg.channel
).id

def __call__(self, msg: Message) -> Any:
return self.get_key(msg)
Loading

0 comments on commit 873a156

Please sign in to comment.