From a16fc23c00a11b53d05cfb0005ce5d710387abd8 Mon Sep 17 00:00:00 2001 From: Lumouille <144063653+Lumabots@users.noreply.github.com> Date: Fri, 5 Dec 2025 10:29:18 +0200 Subject: [PATCH 01/19] =?UTF-8?q?fix:=20=20=E2=99=BB=EF=B8=8F=20Handle=20d?= =?UTF-8?q?iscord.HTTPException=20during=20message=20edits=20in=20Paginato?= =?UTF-8?q?r=20and=20BaseView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- discord/ext/pages/pagination.py | 26 +++++++++++++++----------- discord/ui/view.py | 31 ++++++++++++++++++------------- 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/discord/ext/pages/pagination.py b/discord/ext/pages/pagination.py index 8dbf1c0f43..59a1158472 100644 --- a/discord/ext/pages/pagination.py +++ b/discord/ext/pages/pagination.py @@ -24,6 +24,7 @@ from __future__ import annotations +import contextlib from typing import List import discord @@ -456,7 +457,8 @@ def __init__( async def update( self, - pages: None | ( + pages: None + | ( list[PageGroup] | list[Page] | list[str] @@ -527,7 +529,7 @@ async def update( | list[str] | list[Page] | list[list[discord.Embed] | discord.Embed] - ) = (pages if pages is not None else self.pages) + ) = pages if pages is not None else self.pages self.show_menu = show_menu if show_menu is not None else self.show_menu if pages is not None and all(isinstance(pg, PageGroup) for pg in pages): self.page_groups = self.pages if self.show_menu else None @@ -597,11 +599,12 @@ async def on_timeout(self) -> None: page = self.pages[self.current_page] page = self.get_page_content(page) files = page.update_files() - await self.message.edit( - view=self, - files=files or [], - attachments=[], - ) + async with contextlib.suppress(discord.HTTPException): + await self.message.edit( + view=self, + files=files or [], + attachments=[], + ) async def disable( self, @@ -709,7 +712,9 @@ async def goto_page( try: if interaction: - await interaction.response.defer() # needed to force webhook message edit route for files kwarg support + await ( + interaction.response.defer() + ) # needed to force webhook message edit route for files kwarg support await interaction.followup.edit_message( message_id=self.message.id, content=page.content, @@ -952,9 +957,8 @@ async def send( ctx: Context, target: discord.abc.Messageable | None = None, target_message: str | None = None, - reference: None | ( - discord.Message | discord.MessageReference | discord.PartialMessage - ) = None, + reference: None + | (discord.Message | discord.MessageReference | discord.PartialMessage) = None, allowed_mentions: discord.AllowedMentions | None = None, mention_author: bool | None = None, delete_after: float | None = None, diff --git a/discord/ui/view.py b/discord/ui/view.py index 9d03339d09..07d5154469 100644 --- a/discord/ui/view.py +++ b/discord/ui/view.py @@ -26,6 +26,7 @@ from __future__ import annotations import asyncio +import contextlib import os import sys import time @@ -42,11 +43,12 @@ from typing_extensions import Self +import discord + from ..components import ActionRow as ActionRowComponent from ..components import Button as ButtonComponent -from ..components import Component +from ..components import Component, FileComponent, _component_factory from ..components import Container as ContainerComponent -from ..components import FileComponent from ..components import Label as LabelComponent from ..components import MediaGallery as MediaGalleryComponent from ..components import Section as SectionComponent @@ -54,8 +56,6 @@ from ..components import Separator as SeparatorComponent from ..components import TextDisplay as TextDisplayComponent from ..components import Thumbnail as ThumbnailComponent -from ..components import _component_factory -from ..utils import find from .core import ItemInterface from .item import ItemCallbackType, ViewItem @@ -96,7 +96,6 @@ def _walk_all_components_v2(components: list[Component]) -> Iterator[Component]: def _component_to_item(component: Component) -> ViewItem[V]: - if isinstance(component, ButtonComponent): from .button import Button @@ -309,7 +308,8 @@ async def on_timeout(self) -> None: message = self.message if message: - m = await message.edit(view=self) + async with contextlib.suppress(discord.HTTPException): + m = await message.edit(view=self) if m: self._message = m @@ -681,7 +681,7 @@ def add_item(self, item: ViewItem[V]) -> Self: if item._underlying.is_v2(): raise ValueError( - f"cannot use V2 components in View. Use DesignerView instead." + "cannot use V2 components in View. Use DesignerView instead." ) if isinstance(item._underlying, ActionRowComponent): for i in item.children: @@ -718,7 +718,9 @@ def clear_items(self) -> None: def refresh(self, components: list[Component]): # This is pretty hacky at the moment old_state: dict[tuple[int, str], ViewItem[V]] = { - (item.type.value, item.custom_id): item for item in self.children if item.is_dispatchable() # type: ignore + (item.type.value, item.custom_id): item + for item in self.children + if item.is_dispatchable() # type: ignore } children: list[ViewItem[V]] = [ item for item in self.children if not item.is_dispatchable() @@ -878,7 +880,7 @@ def add_item(self, item: ViewItem[V]) -> Self: if isinstance(item._underlying, (SelectComponent, ButtonComponent)): raise ValueError( - f"cannot add Select or Button to DesignerView directly. Use ActionRow instead." + "cannot add Select or Button to DesignerView directly. Use ActionRow instead." ) super().add_item(item) @@ -909,9 +911,9 @@ def is_components_v2(self) -> bool: class ViewStore: def __init__(self, state: ConnectionState): # (component_type, message_id, custom_id): (BaseView, ViewItem) - self._views: dict[tuple[int, int | None, str], tuple[BaseView, ViewItem[V]]] = ( - {} - ) + self._views: dict[ + tuple[int, int | None, str], tuple[BaseView, ViewItem[V]] + ] = {} # message_id: View self._synced_message_views: dict[int, BaseView] = {} self._state: ConnectionState = state @@ -942,7 +944,10 @@ def add_view(self, view: BaseView, message_id: int | None = None): view._start_listening_from_store(self) for item in view.walk_children(): if item.is_storable(): - self._views[(item.type.value, message_id, item.custom_id)] = (view, item) # type: ignore + self._views[(item.type.value, message_id, item.custom_id)] = ( + view, + item, + ) # type: ignore if message_id is not None: self._synced_message_views[message_id] = view From c09094a59f0adf94e777505d1b6b54f280cf887b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 5 Dec 2025 08:32:36 +0000 Subject: [PATCH 02/19] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/ext/pages/pagination.py | 10 +++++----- discord/ui/view.py | 10 ++++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/discord/ext/pages/pagination.py b/discord/ext/pages/pagination.py index 59a1158472..5db5c80fa4 100644 --- a/discord/ext/pages/pagination.py +++ b/discord/ext/pages/pagination.py @@ -457,8 +457,7 @@ def __init__( async def update( self, - pages: None - | ( + pages: None | ( list[PageGroup] | list[Page] | list[str] @@ -529,7 +528,7 @@ async def update( | list[str] | list[Page] | list[list[discord.Embed] | discord.Embed] - ) = pages if pages is not None else self.pages + ) = (pages if pages is not None else self.pages) self.show_menu = show_menu if show_menu is not None else self.show_menu if pages is not None and all(isinstance(pg, PageGroup) for pg in pages): self.page_groups = self.pages if self.show_menu else None @@ -957,8 +956,9 @@ async def send( ctx: Context, target: discord.abc.Messageable | None = None, target_message: str | None = None, - reference: None - | (discord.Message | discord.MessageReference | discord.PartialMessage) = None, + reference: None | ( + discord.Message | discord.MessageReference | discord.PartialMessage + ) = None, allowed_mentions: discord.AllowedMentions | None = None, mention_author: bool | None = None, delete_after: float | None = None, diff --git a/discord/ui/view.py b/discord/ui/view.py index 07d5154469..ab2224e347 100644 --- a/discord/ui/view.py +++ b/discord/ui/view.py @@ -47,8 +47,9 @@ from ..components import ActionRow as ActionRowComponent from ..components import Button as ButtonComponent -from ..components import Component, FileComponent, _component_factory +from ..components import Component from ..components import Container as ContainerComponent +from ..components import FileComponent from ..components import Label as LabelComponent from ..components import MediaGallery as MediaGalleryComponent from ..components import Section as SectionComponent @@ -56,6 +57,7 @@ from ..components import Separator as SeparatorComponent from ..components import TextDisplay as TextDisplayComponent from ..components import Thumbnail as ThumbnailComponent +from ..components import _component_factory from .core import ItemInterface from .item import ItemCallbackType, ViewItem @@ -911,9 +913,9 @@ def is_components_v2(self) -> bool: class ViewStore: def __init__(self, state: ConnectionState): # (component_type, message_id, custom_id): (BaseView, ViewItem) - self._views: dict[ - tuple[int, int | None, str], tuple[BaseView, ViewItem[V]] - ] = {} + self._views: dict[tuple[int, int | None, str], tuple[BaseView, ViewItem[V]]] = ( + {} + ) # message_id: View self._synced_message_views: dict[int, BaseView] = {} self._state: ConnectionState = state From a198b8d89f49d603b121e1bc2a9df0f36591ff1c Mon Sep 17 00:00:00 2001 From: Lumouille <144063653+Lumabots@users.noreply.github.com> Date: Fri, 5 Dec 2025 10:33:36 +0200 Subject: [PATCH 03/19] =?UTF-8?q?fix:=20=20=E2=99=BB=EF=B8=8F=20Update=20c?= =?UTF-8?q?hangelog=20to=20reflect=20changes=20in=20BaseView=20and=20Pagin?= =?UTF-8?q?ator=20timeout=20behavior?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5696f04d6..49122efaf0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,10 @@ These changes are available on the `master` branch, but have not yet been releas ### Changed +- Changed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer + raise errors on timeout. + ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) + ### Fixed - Fixed breaking change in `ui.Select` Generic typing by adding default values to From 56379e94c2b4998b465cfab74aff9472e8131e66 Mon Sep 17 00:00:00 2001 From: Lumouille <144063653+Lumabots@users.noreply.github.com> Date: Mon, 29 Dec 2025 16:21:11 +0100 Subject: [PATCH 04/19] Update discord/ext/pages/pagination.py Co-authored-by: Paillat Signed-off-by: Lumouille <144063653+Lumabots@users.noreply.github.com> --- discord/ext/pages/pagination.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discord/ext/pages/pagination.py b/discord/ext/pages/pagination.py index 651eb697a6..4417d9f3e7 100644 --- a/discord/ext/pages/pagination.py +++ b/discord/ext/pages/pagination.py @@ -605,7 +605,7 @@ async def on_timeout(self) -> None: page = self.pages[self.current_page] page = self.get_page_content(page) files = page.update_files() - async with contextlib.suppress(discord.HTTPException): + with contextlib.suppress(discord.HTTPException): await self.message.edit( view=self, files=files or [], From abb471380830c3f473c83d08c210114b89545cd5 Mon Sep 17 00:00:00 2001 From: Lumouille <144063653+Lumabots@users.noreply.github.com> Date: Mon, 29 Dec 2025 16:25:51 +0100 Subject: [PATCH 05/19] fix: reorder timeout error handling in changelog --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62ea028dec..211c7060cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,9 +20,6 @@ These changes are available on the `master` branch, but have not yet been releas ### Changed -- Changed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer - raise errors on timeout. - ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) ### Fixed @@ -33,6 +30,9 @@ These changes are available on the `master` branch, but have not yet been releas TypeVars. ([#3002](https://github.com/Pycord-Development/pycord/pull/3002)) - Fixed `View`'s `disable_on_timeout` not working in private (DM) channels. ([#3016](https://github.com/Pycord-Development/pycord/pull/3016)) +- Fixed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer + raise errors on timeout. + ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) ### Deprecated From 568d4c2f7f0660b32ef568d155826fadb422c53a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 29 Dec 2025 15:27:38 +0000 Subject: [PATCH 06/19] style(pre-commit): auto fixes from pre-commit.com hooks --- CHANGELOG.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 211c7060cb..d2ee1f56f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,6 @@ These changes are available on the `master` branch, but have not yet been releas ### Changed - ### Fixed - Fixed `TypeError` in paginator implementation when only passing `PageGroup` objects @@ -30,9 +29,8 @@ These changes are available on the `master` branch, but have not yet been releas TypeVars. ([#3002](https://github.com/Pycord-Development/pycord/pull/3002)) - Fixed `View`'s `disable_on_timeout` not working in private (DM) channels. ([#3016](https://github.com/Pycord-Development/pycord/pull/3016)) -- Fixed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer - raise errors on timeout. - ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) +- Fixed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer raise + errors on timeout. ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) ### Deprecated From 7751415ddb1e6e9f6e08a849afb88ec5efb4e57a Mon Sep 17 00:00:00 2001 From: Lumouille <144063653+Lumabots@users.noreply.github.com> Date: Mon, 29 Dec 2025 16:28:35 +0100 Subject: [PATCH 07/19] fix: format changelog for better readability --- CHANGELOG.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2ee1f56f0..211c7060cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ These changes are available on the `master` branch, but have not yet been releas ### Changed + ### Fixed - Fixed `TypeError` in paginator implementation when only passing `PageGroup` objects @@ -29,8 +30,9 @@ These changes are available on the `master` branch, but have not yet been releas TypeVars. ([#3002](https://github.com/Pycord-Development/pycord/pull/3002)) - Fixed `View`'s `disable_on_timeout` not working in private (DM) channels. ([#3016](https://github.com/Pycord-Development/pycord/pull/3016)) -- Fixed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer raise - errors on timeout. ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) +- Fixed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer + raise errors on timeout. + ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) ### Deprecated From 2711579b659aa284d5956f51ba10508ae9000b5b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 29 Dec 2025 15:29:04 +0000 Subject: [PATCH 08/19] style(pre-commit): auto fixes from pre-commit.com hooks --- CHANGELOG.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 211c7060cb..d2ee1f56f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,6 @@ These changes are available on the `master` branch, but have not yet been releas ### Changed - ### Fixed - Fixed `TypeError` in paginator implementation when only passing `PageGroup` objects @@ -30,9 +29,8 @@ These changes are available on the `master` branch, but have not yet been releas TypeVars. ([#3002](https://github.com/Pycord-Development/pycord/pull/3002)) - Fixed `View`'s `disable_on_timeout` not working in private (DM) channels. ([#3016](https://github.com/Pycord-Development/pycord/pull/3016)) -- Fixed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer - raise errors on timeout. - ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) +- Fixed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer raise + errors on timeout. ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) ### Deprecated From 85027c73931f52698e960871451832a016086d7f Mon Sep 17 00:00:00 2001 From: Lumouille <144063653+Lumabots@users.noreply.github.com> Date: Mon, 29 Dec 2025 16:30:06 +0100 Subject: [PATCH 09/19] chore: update changelog with new features, changes, and fixes for version 2.7.0 --- CHANGELOG.md | 170 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 165 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2ee1f56f0..f770878269 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,18 +10,157 @@ possible (see our [Version Guarantees] for more info). These changes are available on the `master` branch, but have not yet been released. -⚠️ **This version removes support for Python 3.9.** ⚠️ +### Added + +### Changed + +- Updated `Role.is_assignable()` to also check whether the bot has the `MANAGE_ROLES` + permission. ([#3048](https://github.com/Pycord-Development/pycord/pull/3048)) + +### Fixed + +- Fixed `RawMessageUpdateEvent.cached_message` being always `None` even when the message + was cached. ([#3038](https://github.com/Pycord-Development/pycord/pull/3038)) +- Fixed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer + raise errors on timeout. + ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) + +### Deprecated + +### Removed + +## [2.7.0] - 2025-12-24 ### Added - Added `Attachment.read_chunked` and added optional `chunksize` argument to `Attachment.save` for retrieving attachments in chunks. ([#2956](https://github.com/Pycord-Development/pycord/pull/2956)) +- Added `Guild.fetch_roles_member_counts` method and `GuildRoleCounts` class. + ([#3020](https://github.com/Pycord-Development/pycord/pull/3020)) +- Implemented `with_response` for interaction callbacks, adding + `Interaction.callback.is_loading()` and `Interaction.callback.is_ephemeral()`. + ([#2711](https://github.com/Pycord-Development/pycord/pull/2711)) +- Added `RawMessageUpdateEvent.new_message` - message update events now contain full + message objects ([#2780](https://github.com/Pycord-Development/pycord/pull/2780)) +- Added `Guild.get_or_fetch()` and `Client.get_or_fetch()` shortcut methods. + ([#2776](https://github.com/Pycord-Development/pycord/pull/2776)) +- Added support for setting guild-specific `avatar`, `banner`, and `bio` for the bot + user through `Member.edit`. + ([#2908](https://github.com/Pycord-Development/pycord/pull/2908)) +- Added support for select default values. + ([#2899](https://github.com/Pycord-Development/pycord/pull/2899)) + - Adds a new generic parameter to selects to type `ui.Select.values` return type. + - Adds `SelectDefaultValue` object to create select default values. + - Adds `SelectDefaultValueType` enum. + - Adds pre-typed and pre-constructed with select_type `ui.Select` aliases for the + different select types: `ui.StringSelect`, `ui.UserSelect`, `ui.RoleSelect`, + `ui.MentionableSelect`, and `ui.ChannelSelect`. +- Added `store` parameter to `View` and `Modal` classes. + ([#2904](https://github.com/Pycord-Development/pycord/pull/2904/)) +- Added `Webhook.parent` and `Webhook.from_interaction` + ([#2904](https://github.com/Pycord-Development/pycord/pull/2904/)) +- Added the ability to use functions with any number of optional arguments and functions + returning an awaitable as `Option.autocomplete`. + ([#2914](https://github.com/Pycord-Development/pycord/pull/2914)) +- Added `ui.FileUpload` for modals and the `FileUpload` component. + ([#2938](https://github.com/Pycord-Development/pycord/pull/2938)) +- Added `Permissions.bypass_slowmode`. + ([#2939](https://github.com/Pycord-Development/pycord/pull/2939)) +- Added support for Guild Incidents via `Guild.incidents_data` and + `Guild.modify_incident_actions()`. + ([#2955](https://github.com/Pycord-Development/pycord/pull/2955)) +- Added `mention` property to `BaseEmoji`. + ([#2972](https://github.com/Pycord-Development/pycord/pull/2972)) +- Added `positional` argument to `commands.Flag`. + ([#2443](https://github.com/Pycord-Development/pycord/pull/2443)) +- Added `Guild.fetch_role` method. + ([#2528](https://github.com/Pycord-Development/pycord/pull/2528)) +- Added the following `AppInfo` attributes: `approximate_guild_count`, + `approximate_user_install_count`, `custom_install_url`, `install_params`, + `interactions_endpoint_url`, `redirect_uris`, `role_connections_verification_url`, and + `tags`. ([#2520](https://github.com/Pycord-Development/pycord/pull/2520)) +- Added `Member.guild_banner` and `Member.display_banner` properties. + ([#2556](https://github.com/Pycord-Development/pycord/pull/2556)) +- Added support for Application Emojis. + ([#2501](https://github.com/Pycord-Development/pycord/pull/2501)) +- Added `cache_app_emojis` parameter to `Client`. + ([#2501](https://github.com/Pycord-Development/pycord/pull/2501)) +- Added `elapsed` method to `VoiceClient`. + ([#2587](https://github.com/Pycord-Development/pycord/pull/2587/)) +- Added optional `filter` parameter to `utils.basic_autocomplete()`. + ([#2590](https://github.com/Pycord-Development/pycord/pull/2590)) +- Added role tags: `subscription_listing_id`, `guild_connections`, and + `available_for_purchase`. + ([#2606](https://github.com/Pycord-Development/pycord/pull/2606)) +- Added missing `with_counts` parameter to `fetch_guilds` method. + ([#2615](https://github.com/Pycord-Development/pycord/pull/2615)) +- Added the following missing permissions: `Permissions.use_soundboard`, + `Permissions.use_external_sounds`, and + `Permissions.view_creator_monetization_analytics`. + ([#2620](https://github.com/Pycord-Development/pycord/pull/2620)) +- Added `MediaChannel` channel type. + ([#2641](https://github.com/Pycord-Development/pycord/pull/2641)) +- Added `Message._raw_data` attribute. + ([#2670](https://github.com/Pycord-Development/pycord/pull/2670)) +- Added helper methods to determine the authorizing party of an `Interaction`. + ([#2659](https://github.com/Pycord-Development/pycord/pull/2659)) +- Added `VoiceMessage` subclass of `File` to allow voice messages to be sent. + ([#2579](https://github.com/Pycord-Development/pycord/pull/2579)) +- Added the following soundboard-related features: + - Manage guild soundboard sounds with `Guild.fetch_sounds()`, `Guild.create_sound()`, + `SoundboardSound.edit()`, and `SoundboardSound.delete()`. + - Access Discord default sounds with `Client.fetch_default_sounds()`. + - Play sounds in voice channels with `VoiceChannel.send_soundboard_sound()`. + - New `on_voice_channel_effect_send` event for sound and emoji effects. + - Soundboard limits based on guild premium tier (8-48 slots) in + `Guild.soundboard_limit`. + ([#2623](https://github.com/Pycord-Development/pycord/pull/2623)) +- Added new `Subscription` object and related methods/events. + ([#2564](https://github.com/Pycord-Development/pycord/pull/2564)) +- Added `Message.forward_to`, `Message.snapshots`, and other related attributes. + ([#2598](https://github.com/Pycord-Development/pycord/pull/2598)) +- Add missing `Guild` feature flags and `Guild.edit` parameters. + ([#2672](https://github.com/Pycord-Development/pycord/pull/2672)) +- Added the ability to change the API's base URL with `Route.API_BASE_URL`. + ([#2714](https://github.com/Pycord-Development/pycord/pull/2714)) +- Added the ability to pass a `datetime.time` object to `format_dt`. + ([#2747](https://github.com/Pycord-Development/pycord/pull/2747)) +- Added the ability to pass an `overlap` parameter to the `loop` decorator and `Loop` + class, allowing concurrent iterations if enabled. + ([#2765](https://github.com/Pycord-Development/pycord/pull/2765)) +- Added various missing channel parameters and allow `default_reaction_emoji` to be + `None`. ([#2772](https://github.com/Pycord-Development/pycord/pull/2772)) +- Added support for type hinting slash command options with `typing.Annotated`. + ([#2782](https://github.com/Pycord-Development/pycord/pull/2782)) +- Added conversion to `Member` in `MentionableConverter`. + ([#2775](https://github.com/Pycord-Development/pycord/pull/2775)) +- Added `discord.Interaction.created_at`. + ([#2801](https://github.com/Pycord-Development/pycord/pull/2801)) +- Added `User.nameplate` property. + ([#2817](https://github.com/Pycord-Development/pycord/pull/2817)) +- Added role gradients support with `Role.colours` and the `RoleColours` class. + ([#2818](https://github.com/Pycord-Development/pycord/pull/2818)) +- Added `ThreadArchiveDuration` enum to improve clarity of thread archive durations. + ([#2826](https://github.com/Pycord-Development/pycord/pull/2826)) +- Added `Interaction.attachment_size_limit`. + ([#2854](https://github.com/Pycord-Development/pycord/pull/2854)) +- Added support for selects and text displays in modals. + ([#2858](https://github.com/Pycord-Development/pycord/pull/2858)) +- Added `AuditLogDiff.communication_disabled_until`. + ([#2883](https://github.com/Pycord-Development/pycord/pull/2883)) +- Added `discord.User.primary_guild` and the `PrimaryGuild` class. + ([#2876](https://github.com/Pycord-Development/pycord/pull/2876)) +- Added `get_component` to `Message`, `Section`, `Container` and `ActionRow`. + ([#2849](https://github.com/Pycord-Development/pycord/pull/2849)) ### Changed + ### Fixed +- Fixed the `view` attribute on many view items being incorrect. + ([#2981](https://github.com/Pycord-Development/pycord/pull/2981)) - Fixed `TypeError` in paginator implementation when only passing `PageGroup` objects and `show_menu` is falsy. ([#2993](https://github.com/Pycord-Development/pycord/pull/2993)) @@ -29,15 +168,35 @@ These changes are available on the `master` branch, but have not yet been releas TypeVars. ([#3002](https://github.com/Pycord-Development/pycord/pull/3002)) - Fixed `View`'s `disable_on_timeout` not working in private (DM) channels. ([#3016](https://github.com/Pycord-Development/pycord/pull/3016)) -- Fixed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer raise - errors on timeout. ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) +- Fixed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer + raise errors on timeout. + ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) ### Deprecated +- Deprecated manually setting the `view` attribute on view items. + ([#2981](https://github.com/Pycord-Development/pycord/pull/2981)) +- Deprecated `utils.get_or_fetch(attr, id)` and `Client.get_or_fetch_user(id)` in favour + of `utils.get_or_fetch(object_type, object_id)` and `Client.get_or_fetch(User, id)`. + ([#2776](https://github.com/Pycord-Development/pycord/pull/2776)) +- Deprecated `AppInfo.summary` in favor of `AppInfo.description`. + ([#2520](https://github.com/Pycord-Development/pycord/pull/2520)) +- Deprecated `Emoji` in favor of `GuildEmoji`. + ([#2501](https://github.com/Pycord-Development/pycord/pull/2501)) +- Deprecated `Interaction.cached_channel` in favor of `Interaction.channel`. + ([#2658](https://github.com/Pycord-Development/pycord/pull/2658)) +- Deprecated `is_nsfw` for categories since it was never supported by the API. + ([#2772](https://github.com/Pycord-Development/pycord/pull/2772)) +- Deprecated `Messageable.pins()` returning a list of `Message`; it should be used as an + iterator of `MessagePin` instead. + ([#2872](https://github.com/Pycord-Development/pycord/pull/2872)) + ### Removed - ⚠️ **Removed support for Python 3.9.** ([#2986](https://github.com/Pycord-Development/pycord/pull/2986)) +- Removed deprecated support for `Option` in `BridgeCommand`, use `BridgeOption` + instead. ([#2731](https://github.com/Pycord-Development/pycord/pull/2731)) ## [2.7.0rc2] - 2025-10-22 @@ -1249,7 +1408,8 @@ These changes are available on the `master` branch, but have not yet been releas - Fix py3.10 UnionType checks issue. ([#1240](https://github.com/Pycord-Development/pycord/pull/1240)) -[unreleased]: https://github.com/Pycord-Development/pycord/compare/v2.7.0rc2...HEAD +[unreleased]: https://github.com/Pycord-Development/pycord/compare/v2.7.0...HEAD +[2.7.0]: https://github.com/Pycord-Development/pycord/compare/v2.7.0rc2...v2.7.0 [2.7.0rc2]: https://github.com/Pycord-Development/pycord/compare/v2.7.0rc1...v2.7.0rc2 [2.7.0rc1]: https://github.com/Pycord-Development/pycord/compare/v2.6.0...v2.7.0rc1 [2.6.1]: https://github.com/Pycord-Development/pycord/compare/v2.6.0...v2.6.1 @@ -1286,4 +1446,4 @@ These changes are available on the `master` branch, but have not yet been releas https://github.com/Pycord-Development/pycord/compare/v2.0.0-beta.1...v2.0.0-beta.2 [2.0.0-beta.1]: https://github.com/Pycord-Development/pycord/compare/v1.7.3...v2.0.0-beta.1 -[version guarantees]: https://docs.pycord.dev/en/stable/version_guarantees.html +[version guarantees]: https://docs.pycord.dev/en/stable/version_guarantees.html \ No newline at end of file From 3e14dea280cac793783178ddd3cb377605aeb92c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 29 Dec 2025 15:32:18 +0000 Subject: [PATCH 10/19] style(pre-commit): auto fixes from pre-commit.com hooks --- CHANGELOG.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f770878269..e448c4a4ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,9 +21,8 @@ These changes are available on the `master` branch, but have not yet been releas - Fixed `RawMessageUpdateEvent.cached_message` being always `None` even when the message was cached. ([#3038](https://github.com/Pycord-Development/pycord/pull/3038)) -- Fixed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer - raise errors on timeout. - ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) +- Fixed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer raise + errors on timeout. ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) ### Deprecated @@ -156,7 +155,6 @@ These changes are available on the `master` branch, but have not yet been releas ### Changed - ### Fixed - Fixed the `view` attribute on many view items being incorrect. @@ -168,9 +166,8 @@ These changes are available on the `master` branch, but have not yet been releas TypeVars. ([#3002](https://github.com/Pycord-Development/pycord/pull/3002)) - Fixed `View`'s `disable_on_timeout` not working in private (DM) channels. ([#3016](https://github.com/Pycord-Development/pycord/pull/3016)) -- Fixed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer - raise errors on timeout. - ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) +- Fixed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer raise + errors on timeout. ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) ### Deprecated @@ -1446,4 +1443,4 @@ These changes are available on the `master` branch, but have not yet been releas https://github.com/Pycord-Development/pycord/compare/v2.0.0-beta.1...v2.0.0-beta.2 [2.0.0-beta.1]: https://github.com/Pycord-Development/pycord/compare/v1.7.3...v2.0.0-beta.1 -[version guarantees]: https://docs.pycord.dev/en/stable/version_guarantees.html \ No newline at end of file +[version guarantees]: https://docs.pycord.dev/en/stable/version_guarantees.html From a3f04b0650db5febe33c4db2899804b6d7cca3a0 Mon Sep 17 00:00:00 2001 From: Lumouille <144063653+Lumabots@users.noreply.github.com> Date: Mon, 29 Dec 2025 16:35:01 +0100 Subject: [PATCH 11/19] chore: update changelog with new features, changes, and fixes for Components V2 and other improvements --- CHANGELOG.md | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 142 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e448c4a4ab..fcb947be46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -155,6 +155,43 @@ These changes are available on the `master` branch, but have not yet been releas ### Changed +- Overhauled support for Components V2 and new Modal components + ([#2904](https://github.com/Pycord-Development/pycord/pull/2904/)) + - Revert `discord.ui.View` and `discord.ui.Modal` to 2.6.1 behavior; not compatible + with new features. + - Implemented `discord.ui.DesignerView` and `discord.ui.DesignerModal` to support new + components. + - `DesignerView` and `Container` do not support `Button` and `Select` directly; use + `discord.ui.ActionRow` instead. + - `DesignerModal` does not support `InputText` and `Select` directly; use + `discord.ui.Label` instead. + - Removed `InputText.description`, `Select.label` and `Select.description`; these are + now attributes of `Label`. + - `discord.ui.Item` is now a base class for `ViewItem` and `ModalItem`; all items + inherit from these. + - All view and modal classes now inherit from a base `ItemInterface` class, split into + `BaseView` and `BaseModal` +- Renamed `cover` property of `ScheduledEvent` and `cover` argument of + `ScheduledEvent.edit` to `image`. + ([#2496](https://github.com/Pycord-Development/pycord/pull/2496)) +- ⚠️ **Removed support for Python 3.8.** + ([#2521](https://github.com/Pycord-Development/pycord/pull/2521)) +- `Emoji` has been renamed to `GuildEmoji`. + ([#2501](https://github.com/Pycord-Development/pycord/pull/2501)) +- Replaced audioop (deprecated module) implementation of `PCMVolumeTransformer.read` + method with a pure Python equivalent. + ([#2176](https://github.com/Pycord-Development/pycord/pull/2176)) +- Updated `Guild.filesize_limit` to 10 MB instead of 25 MB following Discord's API + changes. ([#2671](https://github.com/Pycord-Development/pycord/pull/2671)) +- `Entitlement.ends_at` can now be `None`. + ([#2564](https://github.com/Pycord-Development/pycord/pull/2564)) +- Changed the default value of `ApplicationCommand.nsfw` to `False`. + ([#2797](https://github.com/Pycord-Development/pycord/pull/2797)) +- Upgraded voice websocket version to v8. + ([#2812](https://github.com/Pycord-Development/pycord/pull/2812)) +- `Messageable.pins()` now returns a `MessagePinIterator` and has new arguments. + ([#2872](https://github.com/Pycord-Development/pycord/pull/2872)) + ### Fixed - Fixed the `view` attribute on many view items being incorrect. @@ -166,8 +203,111 @@ These changes are available on the `master` branch, but have not yet been releas TypeVars. ([#3002](https://github.com/Pycord-Development/pycord/pull/3002)) - Fixed `View`'s `disable_on_timeout` not working in private (DM) channels. ([#3016](https://github.com/Pycord-Development/pycord/pull/3016)) -- Fixed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer raise - errors on timeout. ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) +- Manage silence for new SSRC with existing user_id. + ([#2808](https://github.com/Pycord-Development/pycord/pull/2808)) +- Unbound `raw` reference in `parse_message_update` causing errors on message updates. + ([#2905](https://github.com/Pycord-Development/pycord/pull/2905)) +- `view=None` in various methods causing an AttributeError. + ([#2915](https://github.com/Pycord-Development/pycord/pull/2915)) +- `View.message` being `None` when it had not been interacted with yet. + ([#2916](https://github.com/Pycord-Development/pycord/pull/2916)) +- Fixed a crash when processing message edit events while message cache was disabled. + ([#2924](https://github.com/Pycord-Development/pycord/pull/2924)) +- Fixed OPUS Decode Error when recording audio. + ([#2925](https://github.com/Pycord-Development/pycord/pull/2925)) +- Fixed a `TypeError` when typing `ui.Select` without providing optional type arguments. + ([#2943](https://github.com/Pycord-Development/pycord/pull/2943)) +- Fixed modal input values being misordered when using the `row` parameter and inserting + items out of row order. + ([#2938](https://github.com/Pycord-Development/pycord/pull/2938)) +- Fixed a KeyError when a text input is left blank in a modal. + ([#2938](https://github.com/Pycord-Development/pycord/pull/2938)) +- Fixed `TypeError` when using Python 3.12+ `type` syntax for typing slash command + parameters. ([#2952](https://github.com/Pycord-Development/pycord/pull/2952)) +- Fixed autocomplete crashing when using an async staticmethod. + ([#2966](https://github.com/Pycord-Development/pycord/pull/2966)) +- Fixed attributes like :attr:`Member.display_banner` being `None` when the member has + no guild specific banner, but does have a global one. + ([#2968](https://github.com/Pycord-Development/pycord/pull/2949)) +- Fixed `__repr__` formatting for `AppEmoji`. + ([#2972](https://github.com/Pycord-Development/pycord/pull/2972)) +- Fixed `Enum` options not setting the correct type when only one choice is available. + ([#2577](https://github.com/Pycord-Development/pycord/pull/2577)) +- Fixed `codec` option for `FFmpegOpusAudio` class to make it in line with + documentation. ([#2581](https://github.com/Pycord-Development/pycord/pull/2581)) +- Fixed a possible bug where audio would play too fast at the beginning of audio files. + ([#2584](https://github.com/Pycord-Development/pycord/pull/2584)) +- Fixed paginator not responding when using `Paginator.edit()` with default parameters. + ([#2594](https://github.com/Pycord-Development/pycord/pull/2594)) +- Fixed the `is_owner()` `user` type hint: `User` -> `User | Member`. + ([#2593](https://github.com/Pycord-Development/pycord/pull/2593)) +- Fixed `Guild.create_test_entitlement()` and `User.create_test_entitlement()` using the + guild/user ID instead of the application ID. + ([#2595](https://github.com/Pycord-Development/pycord/pull/2595)) +- Fixed `BucketType.category` cooldown commands not functioning correctly in private + channels. ([#2603](https://github.com/Pycord-Development/pycord/pull/2603)) +- Fixed `ctx` parameter of a `SlashCommand` not being `Union` type. + ([#2611](https://github.com/Pycord-Development/pycord/pull/2611)) +- Fixed `TypeError` when passing `skus` parameter in `Client.entitlements()`. + ([#2627](https://github.com/Pycord-Development/pycord/issues/2627)) +- Fixed `AttributeError` when sending polls with `PartialWebook`. + ([#2624](https://github.com/Pycord-Development/pycord/pull/2624)) +- Fixed editing `ForumChannel` flags not working. + ([#2641](https://github.com/Pycord-Development/pycord/pull/2641)) +- Fixed `AttributeError` when accessing `Member.guild_permissions` for user installed + apps. ([#2650](https://github.com/Pycord-Development/pycord/pull/2650)) +- Fixed type annotations of cached properties. + ([#2635](https://github.com/Pycord-Development/pycord/issues/2635)) +- Fixed malformed properties in `Interaction.channel`. + ([#2658](https://github.com/Pycord-Development/pycord/pull/2658)) +- Fixed an error when responding non-ephemerally with a `Paginator` to an ephemerally + deferred interaction. + ([#2661](https://github.com/Pycord-Development/pycord/pull/2661)) +- Fixed attachment metadata being set incorrectly in interaction responses causing the + metadata to be ignored by Discord. + ([#2679](https://github.com/Pycord-Development/pycord/pull/2679)) +- Fixed unexpected backoff behavior in the handling of task failures + ([#2700](https://github.com/Pycord-Development/pycord/pull/2700)). +- Fixed `BridgeCommand` duplicate in default help command. + ([#2656](https://github.com/Pycord-Development/pycord/pull/2656)) +- Fixed `AttributeError` when trying to consume a consumable entitlement. + ([#2564](https://github.com/Pycord-Development/pycord/pull/2564)) +- Fixed `Subscription.renewal_sku_ids` not accepting `None` from the received payload. + ([#2709](https://github.com/Pycord-Development/pycord/pull/2709)) +- Fixed `ForumChannel.edit` allowing `default_reaction_emoji` to be `None`. + ([#2739](https://github.com/Pycord-Development/pycord/pull/2739)) +- Fixed missing `None` type hints in `Select.__init__`. + ([#2746](https://github.com/Pycord-Development/pycord/pull/2746)) +- Fixed `TypeError` when using `Flag` with Python 3.11+. + ([#2759](https://github.com/Pycord-Development/pycord/pull/2759)) +- Fixed `TypeError` when specifying `thread_name` in `Webhook.send`. + ([#2761](https://github.com/Pycord-Development/pycord/pull/2761)) +- Updated `valid_locales` to support `in` and `es-419`. + ([#2767](https://github.com/Pycord-Development/pycord/pull/2767)) +- Added support for emoji aliases like `:smile:` in PartialEmoji.from_str. Also applied + the same logic in PartialEmojiConverter. + ([#2815](https://github.com/Pycord-Development/pycord/pull/2815)) +- Fixed `Webhook.edit` not working with `attachments=[]`. + ([#2779](https://github.com/Pycord-Development/pycord/pull/2779)) +- Fixed GIF-based `Sticker` returning the wrong `url`. + ([#2781](https://github.com/Pycord-Development/pycord/pull/2781)) +- Fixed `VoiceClient` crashing randomly while receiving audio + ([#2800](https://github.com/Pycord-Development/pycord/pull/2800)) +- Fixed `VoiceClient.connect` failing to do initial connection. + ([#2812](https://github.com/Pycord-Development/pycord/pull/2812)) +- Fixed `AttributeError` when printing a File component's `__repr__`. + ([#2843](https://github.com/Pycord-Development/pycord/pull/2843)) +- Fixed `TypeError` when using `@option` with certain annotations and along with + `channel_types`. ([#2835](https://github.com/Pycord-Development/pycord/pull/2835)) +- Fixed `TypeError` when using `Optional[...]` or `... | None` in command option type. + ([#2852](https://github.com/Pycord-Development/pycord/pull/2852)) +- Fixed type-hinting for `PermissionOverwrite.update`. + ([#2878](https://github.com/Pycord-Development/pycord/pull/2878)) +- Fixed `AttributeError` when accessing `AuditLogEntry.changes` more than once. + ([#2882])(https://github.com/Pycord-Development/pycord/pull/2882)) +- Fixed type hint for argument `start_time` and `end_time` of + `Guild.create_scheduled_event` + ([#2879](https://github.com/Pycord-Development/pycord/pull/2879)) ### Deprecated From b2251148fda563046c73fe4dddc4013a913700d5 Mon Sep 17 00:00:00 2001 From: Lumouille <144063653+Lumabots@users.noreply.github.com> Date: Mon, 29 Dec 2025 16:41:03 +0100 Subject: [PATCH 12/19] fix: improve error handling and clean up type annotations in Paginator and BaseView --- discord/ext/pages/pagination.py | 12 ++++++------ discord/ui/view.py | 9 ++++----- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/discord/ext/pages/pagination.py b/discord/ext/pages/pagination.py index 4417d9f3e7..e7992d9f33 100644 --- a/discord/ext/pages/pagination.py +++ b/discord/ext/pages/pagination.py @@ -460,7 +460,8 @@ def __init__( async def update( self, - pages: None | ( + pages: None + | ( list[PageGroup] | list[Page] | list[str] @@ -531,7 +532,7 @@ async def update( | list[str] | list[Page] | list[list[discord.Embed] | discord.Embed] - ) = (pages if pages is not None else self.pages) + ) = pages if pages is not None else self.pages self.show_menu = show_menu if show_menu is not None else self.show_menu if pages is not None and all(isinstance(pg, PageGroup) for pg in pages): if sum(pg.default is True for pg in pages) > 1: @@ -605,7 +606,7 @@ async def on_timeout(self) -> None: page = self.pages[self.current_page] page = self.get_page_content(page) files = page.update_files() - with contextlib.suppress(discord.HTTPException): + with contextlib.suppress(discord.NotFound, discord.Forbidden): await self.message.edit( view=self, files=files or [], @@ -963,9 +964,8 @@ async def send( ctx: Context, target: discord.abc.Messageable | None = None, target_message: str | None = None, - reference: None | ( - discord.Message | discord.MessageReference | discord.PartialMessage - ) = None, + reference: None + | (discord.Message | discord.MessageReference | discord.PartialMessage) = None, allowed_mentions: discord.AllowedMentions | None = None, mention_author: bool | None = None, delete_after: float | None = None, diff --git a/discord/ui/view.py b/discord/ui/view.py index 0be60f1145..6a50d921dc 100644 --- a/discord/ui/view.py +++ b/discord/ui/view.py @@ -59,7 +59,6 @@ from ..components import Thumbnail as ThumbnailComponent from ..components import _component_factory from ..enums import ChannelType -from ..utils import find from .core import ItemInterface from .item import ItemCallbackType, ViewItem @@ -323,7 +322,7 @@ async def on_timeout(self) -> None: message = self.message if message: - async with contextlib.suppress(discord.HTTPException): + with contextlib.suppress(discord.NotFound, discord.Forbidden): m = await message.edit(view=self) if m: self._message = m @@ -923,9 +922,9 @@ def is_components_v2(self) -> bool: class ViewStore: def __init__(self, state: ConnectionState): # (component_type, message_id, custom_id): (BaseView, ViewItem) - self._views: dict[tuple[int, int | None, str], tuple[BaseView, ViewItem[V]]] = ( - {} - ) + self._views: dict[ + tuple[int, int | None, str], tuple[BaseView, ViewItem[V]] + ] = {} # message_id: View self._synced_message_views: dict[int, BaseView] = {} self._state: ConnectionState = state From 97c748eb1675f754ebfa91817cc3ef75d994b12c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 29 Dec 2025 15:41:38 +0000 Subject: [PATCH 13/19] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/ext/pages/pagination.py | 10 +++++----- discord/ui/view.py | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/discord/ext/pages/pagination.py b/discord/ext/pages/pagination.py index e7992d9f33..ab328723c4 100644 --- a/discord/ext/pages/pagination.py +++ b/discord/ext/pages/pagination.py @@ -460,8 +460,7 @@ def __init__( async def update( self, - pages: None - | ( + pages: None | ( list[PageGroup] | list[Page] | list[str] @@ -532,7 +531,7 @@ async def update( | list[str] | list[Page] | list[list[discord.Embed] | discord.Embed] - ) = pages if pages is not None else self.pages + ) = (pages if pages is not None else self.pages) self.show_menu = show_menu if show_menu is not None else self.show_menu if pages is not None and all(isinstance(pg, PageGroup) for pg in pages): if sum(pg.default is True for pg in pages) > 1: @@ -964,8 +963,9 @@ async def send( ctx: Context, target: discord.abc.Messageable | None = None, target_message: str | None = None, - reference: None - | (discord.Message | discord.MessageReference | discord.PartialMessage) = None, + reference: None | ( + discord.Message | discord.MessageReference | discord.PartialMessage + ) = None, allowed_mentions: discord.AllowedMentions | None = None, mention_author: bool | None = None, delete_after: float | None = None, diff --git a/discord/ui/view.py b/discord/ui/view.py index 6a50d921dc..917d8aae81 100644 --- a/discord/ui/view.py +++ b/discord/ui/view.py @@ -922,9 +922,9 @@ def is_components_v2(self) -> bool: class ViewStore: def __init__(self, state: ConnectionState): # (component_type, message_id, custom_id): (BaseView, ViewItem) - self._views: dict[ - tuple[int, int | None, str], tuple[BaseView, ViewItem[V]] - ] = {} + self._views: dict[tuple[int, int | None, str], tuple[BaseView, ViewItem[V]]] = ( + {} + ) # message_id: View self._synced_message_views: dict[int, BaseView] = {} self._state: ConnectionState = state From 1f6922fa139baf870a89dce112aadb3219d2cd2c Mon Sep 17 00:00:00 2001 From: Lumouille <144063653+Lumabots@users.noreply.github.com> Date: Tue, 30 Dec 2025 15:15:14 +0100 Subject: [PATCH 14/19] fix: improve message handling and type hint formatting in BaseView and ViewStore --- discord/ui/view.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/discord/ui/view.py b/discord/ui/view.py index 917d8aae81..a5afbbc484 100644 --- a/discord/ui/view.py +++ b/discord/ui/view.py @@ -324,8 +324,8 @@ async def on_timeout(self) -> None: if message: with contextlib.suppress(discord.NotFound, discord.Forbidden): m = await message.edit(view=self) - if m: - self._message = m + if m: + self._message = m async def on_check_failure(self, interaction: Interaction) -> None: """|coro| @@ -922,9 +922,9 @@ def is_components_v2(self) -> bool: class ViewStore: def __init__(self, state: ConnectionState): # (component_type, message_id, custom_id): (BaseView, ViewItem) - self._views: dict[tuple[int, int | None, str], tuple[BaseView, ViewItem[V]]] = ( - {} - ) + self._views: dict[ + tuple[int, int | None, str], tuple[BaseView, ViewItem[V]] + ] = {} # message_id: View self._synced_message_views: dict[int, BaseView] = {} self._state: ConnectionState = state From 0f74942422ffcc267d502cf53e042746d557d989 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 30 Dec 2025 14:16:32 +0000 Subject: [PATCH 15/19] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/ui/view.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/discord/ui/view.py b/discord/ui/view.py index a5afbbc484..486ab3c0d3 100644 --- a/discord/ui/view.py +++ b/discord/ui/view.py @@ -922,9 +922,9 @@ def is_components_v2(self) -> bool: class ViewStore: def __init__(self, state: ConnectionState): # (component_type, message_id, custom_id): (BaseView, ViewItem) - self._views: dict[ - tuple[int, int | None, str], tuple[BaseView, ViewItem[V]] - ] = {} + self._views: dict[tuple[int, int | None, str], tuple[BaseView, ViewItem[V]]] = ( + {} + ) # message_id: View self._synced_message_views: dict[int, BaseView] = {} self._state: ConnectionState = state From b0f02394eafd3e0e22f362d5548084c3332bd7f5 Mon Sep 17 00:00:00 2001 From: Lumouille <144063653+Lumabots@users.noreply.github.com> Date: Thu, 1 Jan 2026 18:24:12 +0100 Subject: [PATCH 16/19] fix: replace discord error references with local imports in BaseView --- discord/ui/view.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/discord/ui/view.py b/discord/ui/view.py index 486ab3c0d3..fe20318c1e 100644 --- a/discord/ui/view.py +++ b/discord/ui/view.py @@ -43,7 +43,6 @@ from typing_extensions import Self -import discord from ..components import ActionRow as ActionRowComponent from ..components import Button as ButtonComponent @@ -61,6 +60,7 @@ from ..enums import ChannelType from .core import ItemInterface from .item import ItemCallbackType, ViewItem +from ..errors import NotFound, Forbidden __all__ = ( "BaseView", @@ -322,7 +322,7 @@ async def on_timeout(self) -> None: message = self.message if message: - with contextlib.suppress(discord.NotFound, discord.Forbidden): + with contextlib.suppress(NotFound, Forbidden): m = await message.edit(view=self) if m: self._message = m From 8defd981049a1cf09489600a9e952120615321a7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 4 Jan 2026 15:40:32 +0000 Subject: [PATCH 17/19] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/ui/view.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/discord/ui/view.py b/discord/ui/view.py index fe20318c1e..fce6b616e5 100644 --- a/discord/ui/view.py +++ b/discord/ui/view.py @@ -43,7 +43,6 @@ from typing_extensions import Self - from ..components import ActionRow as ActionRowComponent from ..components import Button as ButtonComponent from ..components import Component @@ -58,9 +57,9 @@ from ..components import Thumbnail as ThumbnailComponent from ..components import _component_factory from ..enums import ChannelType +from ..errors import Forbidden, NotFound from .core import ItemInterface from .item import ItemCallbackType, ViewItem -from ..errors import NotFound, Forbidden __all__ = ( "BaseView", From fe0f9bf53ea8c9488c791b39d2596083180a4dbc Mon Sep 17 00:00:00 2001 From: Paillat Date: Fri, 16 Jan 2026 11:54:21 +0100 Subject: [PATCH 18/19] Apply suggestion from @Paillat-dev Signed-off-by: Paillat --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b3987ca32..b9dad30fd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,7 +23,7 @@ These changes are available on the `master` branch, but have not yet been releas ### Fixed - Fixed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer raise - errors on timeout. ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) + unnecessary errors on timeout. ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) - Fixed `RawMessageUpdateEvent.cached_message` being always `None` even when the message was cached. ([#3038](https://github.com/Pycord-Development/pycord/pull/3038)) - Fixed downloading animated emojis which were originally uploaded as WebP files by From b2953f1fd593b7dbda042e8574bd3ceead8b8bec Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 10:54:49 +0000 Subject: [PATCH 19/19] style(pre-commit): auto fixes from pre-commit.com hooks --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9dad30fd4..b26cf1595b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,7 +23,8 @@ These changes are available on the `master` branch, but have not yet been releas ### Fixed - Fixed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer raise - unnecessary errors on timeout. ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) + unnecessary errors on timeout. + ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) - Fixed `RawMessageUpdateEvent.cached_message` being always `None` even when the message was cached. ([#3038](https://github.com/Pycord-Development/pycord/pull/3038)) - Fixed downloading animated emojis which were originally uploaded as WebP files by