From 3c61693dc5e3d5aad99785f17eeb86d983b5b6c9 Mon Sep 17 00:00:00 2001 From: vmphase Date: Tue, 11 Aug 2026 15:09:09 +0300 Subject: [PATCH 01/16] feat: deprecate VoiceRegion enum in favour of dynamic voice regions --- CHANGELOG.md | 7 ++++++ discord/enums.py | 62 ++++++++++++++++++++++++++++++---------------- discord/guild.py | 39 +++++++++++++++++++++++++++++ discord/http.py | 7 ++++++ docs/api/enums.rst | 52 ++++++++------------------------------ 5 files changed, 104 insertions(+), 63 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c42ff5f256..e893aba9b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ These changes are available on the `master` branch, but have not yet been releas - Added `Member.vr_status` property. ([#3328](https://github.com/Pycord-Development/pycord/pull/3328)) +- Added `Guild.fetch_voice_regions()` method to retrieve the currently available voice + regions for the guild. + ([#3347](https://github.com/Pycord-Development/pycord/pull/3347)) ### Changed @@ -27,6 +30,10 @@ These changes are available on the `master` branch, but have not yet been releas ### Deprecated +- Deprecated the `VoiceRegion` enum in favor of the region ID `str` or + `Guild.fetch_voice_regions()`. + ([#3347](https://github.com/Pycord-Development/pycord/pull/3347)) + ### Removed ## [2.8.1] - 2026-07-25 diff --git a/discord/enums.py b/discord/enums.py index 5011a338c2..19cdc61240 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -30,6 +30,8 @@ from enum import IntEnum from typing import TYPE_CHECKING, Any, ClassVar, TypeVar, Union +from .utils import warn_deprecated + __all__ = ( "Enum", "ChannelType", @@ -286,32 +288,50 @@ class MessageType(Enum): poll_result = 46 -class VoiceRegion(Enum): - """Voice region""" +class _VoiceRegionMeta(Enum.__class__): + def _warn(self, label: str) -> None: + warn_deprecated( + label, + instead="the region ID string or Guild.fetch_voice_regions()", + since="2.9", + removed="3.0", + stacklevel=4, + ) + + def __getattribute__(cls, name: str) -> Any: + members = super().__getattribute__("_enum_member_map_") + if name in members: + cls._warn(f"VoiceRegion.{name}") + return super().__getattribute__(name) + + def __getitem__(cls, name: str) -> Any: + member = super().__getitem__(name) + cls._warn(f"VoiceRegion[{name!r}]") + return member + + +class VoiceRegion(Enum, metaclass=_VoiceRegionMeta): + """Specifies the region a voice server belongs to. + + .. deprecated:: 2.9 + The list of voice regions is dynamic, so this enum is deprecated in favor + of the region ID :class:`str` or :meth:`Guild.fetch_voice_regions` and + will be removed in version 3.0. + """ - us_west = "us-west" - us_east = "us-east" - us_south = "us-south" - us_central = "us-central" - eu_west = "eu-west" - eu_central = "eu-central" - singapore = "singapore" - london = "london" - sydney = "sydney" - amsterdam = "amsterdam" - frankfurt = "frankfurt" brazil = "brazil" hongkong = "hongkong" - russia = "russia" + india = "india" japan = "japan" - southafrica = "southafrica" + rotterdam = "rotterdam" + singapore = "singapore" south_korea = "south-korea" - india = "india" - europe = "europe" - dubai = "dubai" - vip_us_east = "vip-us-east" - vip_us_west = "vip-us-west" - vip_amsterdam = "vip-amsterdam" + southafrica = "southafrica" + sydney = "sydney" + us_central = "us-central" + us_east = "us-east" + us_south = "us-south" + us_west = "us-west" def __str__(self): return self.value diff --git a/discord/guild.py b/discord/guild.py index b485123b52..cb7964ccdf 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -121,6 +121,7 @@ from .types.guild import ModifyIncidents as ModifyIncidentsPayload from .types.member import Member as MemberPayload from .types.threads import Thread as ThreadPayload + from .types.voice import VoiceRegion as VoiceRegionPayload from .types.voice import VoiceState as GuildVoiceState from .voice import VoiceClient from .webhook import Webhook @@ -3786,6 +3787,44 @@ async def vanity_invite(self) -> Invite | None: payload["uses"] = payload.get("uses", 0) return Invite(state=self._state, data=payload, guild=self, channel=channel) + async def fetch_voice_regions(self) -> list[VoiceRegionPayload]: + """|coro| + + Retrieves the voice regions that the guild has access to. + + The list of voice regions is dynamic, so this method is the + recommended way to get the currently available regions instead of + relying on the deprecated :class:`VoiceRegion` enum. + + .. versionadded:: 2.9 + + Each payload is a :class:`~discord.types.voice.VoiceRegion` TypedDict + with the following keys: + + ``id`` + The region ID, e.g. ``"us-west"``. Use this as the + :attr:`~discord.VoiceChannel.rtc_region` of a voice channel. + ``name`` + The region's display name, e.g. ``"US West"``. + ``optimal`` + Whether the region is optimal for the guild's members. + ``deprecated`` + Whether the region is deprecated. + ``custom`` + Whether the region is a custom region. + + Raises + ------- + HTTPException + Retrieving the voice regions failed. + + Returns + -------- + List[:class:`~discord.types.voice.VoiceRegion`] + The list of voice regions the guild has access to. + """ + return await self._state.http.get_guild_voice_regions(self.id) + # TODO: use MISSING when async iterators get refactored def audit_logs( self, diff --git a/discord/http.py b/discord/http.py index 40ebcd7c1f..15fc2a81ae 100644 --- a/discord/http.py +++ b/discord/http.py @@ -85,6 +85,7 @@ template, threads, user, + voice, webhook, welcome_screen, widget, @@ -1043,6 +1044,12 @@ def guild_voice_state( return self.request(r, json=payload, reason=reason) + def get_guild_voice_regions(self, guild_id: Snowflake) -> Response[list[voice.VoiceRegion]]: + return self.request(Route("GET", "/guilds/{guild_id}/regions", guild_id=guild_id)) + + def get_voice_regions(self) -> Response[list[voice.VoiceRegion]]: + return self.request(Route("GET", "/voice/regions")) + def edit_profile(self, payload: dict[str, Any]) -> Response[user.User]: return self.request(Route("PATCH", "/users/@me"), json=payload) diff --git a/docs/api/enums.rst b/docs/api/enums.rst index efa16a4a5e..139588e8a1 100644 --- a/docs/api/enums.rst +++ b/docs/api/enums.rst @@ -615,60 +615,37 @@ of :class:`enum.Enum`. Specifies the region a voice server belongs to. - .. attribute:: amsterdam + .. deprecated:: 2.9 + + The list of voice regions is dynamic, so this enum is deprecated in favor + of the region ID :class:`str` or :meth:`Guild.fetch_voice_regions` and + will be removed in version 3.0. - The Amsterdam region. .. attribute:: brazil The Brazil region. - .. attribute:: dubai - - The Dubai region. - - .. versionadded:: 1.3 - - .. attribute:: eu_central - - The EU Central region. - .. attribute:: eu_west - - The EU West region. - .. attribute:: europe - - The Europe region. - - .. versionadded:: 1.3 - - .. attribute:: frankfurt - - The Frankfurt region. .. attribute:: hongkong The Hong Kong region. .. attribute:: india The India region. - - .. versionadded:: 1.2 - .. attribute:: japan The Japan region. - .. attribute:: london + .. attribute:: rotterdam - The London region. - .. attribute:: russia + The Rotterdam region. - The Russia region. .. attribute:: singapore The Singapore region. - .. attribute:: southafrica - - The South Africa region. .. attribute:: south_korea The South Korea region. + .. attribute:: southafrica + + The South Africa region. .. attribute:: sydney The Sydney region. @@ -684,15 +661,6 @@ of :class:`enum.Enum`. .. attribute:: us_west The US West region. - .. attribute:: vip_amsterdam - - The Amsterdam region for VIP guilds. - .. attribute:: vip_us_east - - The US East region for VIP guilds. - .. attribute:: vip_us_west - - The US West region for VIP guilds. .. class:: VerificationLevel From ddd0d1b4b49c834940deb6e148b04d6c3de04e2d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 11 Aug 2026 12:17:43 +0000 Subject: [PATCH 02/16] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/guild.py | 12 ++++++------ discord/http.py | 8 ++++++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/discord/guild.py b/discord/guild.py index cb7964ccdf..502837338b 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -3813,15 +3813,15 @@ async def fetch_voice_regions(self) -> list[VoiceRegionPayload]: ``custom`` Whether the region is a custom region. - Raises - ------- - HTTPException - Retrieving the voice regions failed. - Returns - -------- + ------- List[:class:`~discord.types.voice.VoiceRegion`] The list of voice regions the guild has access to. + + Raises + ------ + HTTPException + Retrieving the voice regions failed. """ return await self._state.http.get_guild_voice_regions(self.id) diff --git a/discord/http.py b/discord/http.py index 15fc2a81ae..7cf87639a0 100644 --- a/discord/http.py +++ b/discord/http.py @@ -1044,8 +1044,12 @@ def guild_voice_state( return self.request(r, json=payload, reason=reason) - def get_guild_voice_regions(self, guild_id: Snowflake) -> Response[list[voice.VoiceRegion]]: - return self.request(Route("GET", "/guilds/{guild_id}/regions", guild_id=guild_id)) + def get_guild_voice_regions( + self, guild_id: Snowflake + ) -> Response[list[voice.VoiceRegion]]: + return self.request( + Route("GET", "/guilds/{guild_id}/regions", guild_id=guild_id) + ) def get_voice_regions(self) -> Response[list[voice.VoiceRegion]]: return self.request(Route("GET", "/voice/regions")) From b9e9c6c8c277785aceb38d682122bdf0cfc6eb0b Mon Sep 17 00:00:00 2001 From: vmphase Date: Tue, 11 Aug 2026 16:21:25 +0300 Subject: [PATCH 03/16] feat(enums): deprecate VoiceRegion enum for LSP; warn on VoiceRegion("") --- discord/enums.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/discord/enums.py b/discord/enums.py index 19cdc61240..e48c70cb0b 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -27,9 +27,20 @@ import types from collections import namedtuple +from collections.abc import Callable from enum import IntEnum from typing import TYPE_CHECKING, Any, ClassVar, TypeVar, Union +if TYPE_CHECKING: + from typing_extensions import deprecated +else: + + def deprecated(message: str) -> Callable[[T], T]: + def decorator(value: T) -> T: + return value + + return decorator + from .utils import warn_deprecated __all__ = ( @@ -309,7 +320,15 @@ def __getitem__(cls, name: str) -> Any: cls._warn(f"VoiceRegion[{name!r}]") return member + def __call__(cls, *args: Any, **kwargs: Any) -> Any: + cls._warn(f"VoiceRegion({', '.join(map(repr, args))})") + return super().__call__(*args, **kwargs) + +@deprecated( + "VoiceRegion is deprecated in favour of the region ID str or " + "Guild.fetch_voice_regions() since version 2.9, and will be removed in version 3.0." +) class VoiceRegion(Enum, metaclass=_VoiceRegionMeta): """Specifies the region a voice server belongs to. From 19dfe2a134fccd79e644a1827def38307a70d017 Mon Sep 17 00:00:00 2001 From: vmphase Date: Tue, 11 Aug 2026 16:29:09 +0300 Subject: [PATCH 04/16] feat(enums): unknown attribute fallback --- discord/enums.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/discord/enums.py b/discord/enums.py index e48c70cb0b..b17060467b 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -324,6 +324,12 @@ def __call__(cls, *args: Any, **kwargs: Any) -> Any: cls._warn(f"VoiceRegion({', '.join(map(repr, args))})") return super().__call__(*args, **kwargs) + def __getattr__(cls, name: str) -> Any: + if name.startswith("_"): + raise AttributeError(name) + cls._warn(f"VoiceRegion.{name}") + return create_unknown_value(cls, name) + @deprecated( "VoiceRegion is deprecated in favour of the region ID str or " From 53eb1285682651690a4262b8f205bb4ce23f72bb Mon Sep 17 00:00:00 2001 From: vmphase Date: Tue, 11 Aug 2026 16:30:47 +0300 Subject: [PATCH 05/16] feat: make rtc_region paramater accept str (region id) for channel create / edut --- CHANGELOG.md | 4 ++++ discord/channel.py | 26 +++++++++++++++++--------- discord/guild.py | 22 ++++++++++++++++------ 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e893aba9b0..7a629d820e 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 +- The `rtc_region` parameters of channel creation and edit methods now also accept a + region ID `str` in addition to a `VoiceRegion` member. + ([#3347](https://github.com/Pycord-Development/pycord/pull/3347)) + ### Fixed - Fix `TypeError` when accessing `ApplicationCommand.guild_only` or diff --git a/discord/channel.py b/discord/channel.py index dab70c4a92..2749c4b3e2 100644 --- a/discord/channel.py +++ b/discord/channel.py @@ -48,14 +48,12 @@ InviteTarget, SortOrder, StagePrivacyLevel, -) -from .enums import ThreadArchiveDuration as ThreadArchiveDurationEnum -from .enums import ( VideoQualityMode, VoiceChannelEffectAnimationType, VoiceRegion, try_enum, ) +from .enums import ThreadArchiveDuration as ThreadArchiveDurationEnum from .errors import ClientException, InvalidArgument from .file import File from .flags import ChannelFlags, MessageFlags @@ -2091,7 +2089,7 @@ async def edit( sync_permissions: int = ..., category: CategoryChannel | None = ..., overwrites: Mapping[Role | Member, PermissionOverwrite] = ..., - rtc_region: VoiceRegion | None = ..., + rtc_region: VoiceRegion | str | None = ..., video_quality_mode: VideoQualityMode = ..., slowmode_delay: int = ..., nsfw: bool = ..., @@ -2135,10 +2133,15 @@ async def edit(self, *, reason=None, **options): The reason for editing this channel. Shows up on the audit log. overwrites: Dict[Union[:class:`Role`, :class:`Member`, :class:`~discord.abc.Snowflake`], :class:`PermissionOverwrite`] The overwrites to apply to channel permissions. Useful for creating secret channels. - rtc_region: Optional[:class:`VoiceRegion`] - The new region for the voice channel's voice communication. + rtc_region: Optional[Union[:class:`str`, :class:`VoiceRegion`]] + The new region ID for the voice channel's voice communication. A value of ``None`` indicates automatic voice region detection. + .. versionchanged:: 2.9 + + A :class:`VoiceRegion` member is still accepted, but it is + deprecated in favor of the region ID :class:`str`. + .. versionadded:: 1.7 video_quality_mode: :class:`VideoQualityMode` The camera video quality for the voice channel's participants. @@ -2778,7 +2781,7 @@ async def edit( sync_permissions: int = ..., category: CategoryChannel | None = ..., overwrites: Mapping[Role | Member, PermissionOverwrite] = ..., - rtc_region: VoiceRegion | None = ..., + rtc_region: VoiceRegion | str | None = ..., video_quality_mode: VideoQualityMode = ..., reason: str | None = ..., ) -> StageChannel | None: ... @@ -2816,9 +2819,14 @@ async def edit(self, *, reason=None, **options): The reason for editing this channel. Shows up on the audit log. overwrites: Dict[Union[:class:`Role`, :class:`Member`, :class:`~discord.abc.Snowflake`], :class:`PermissionOverwrite`] The overwrites to apply to channel permissions. Useful for creating secret channels. - rtc_region: Optional[:class:`VoiceRegion`] - The new region for the stage channel's voice communication. + rtc_region: Optional[Union[:class:`str`, :class:`VoiceRegion`]] + The new region ID for the stage channel's voice communication. A value of ``None`` indicates automatic voice region detection. + + .. versionchanged:: 2.9 + + A :class:`VoiceRegion` member is still accepted, but it is + deprecated in favor of the region ID :class:`str`. video_quality_mode: :class:`VideoQualityMode` The camera video quality for the stage channel's participants. diff --git a/discord/guild.py b/discord/guild.py index 502837338b..a7993442e6 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -1603,7 +1603,7 @@ async def create_voice_channel( position: int = MISSING, bitrate: int = MISSING, user_limit: int = MISSING, - rtc_region: VoiceRegion | None = MISSING, + rtc_region: VoiceRegion | str | None = MISSING, video_quality_mode: VideoQualityMode = MISSING, overwrites: dict[Role | Member, PermissionOverwrite] = MISSING, slowmode_delay: int = MISSING, @@ -1630,10 +1630,15 @@ async def create_voice_channel( The channel's preferred audio bitrate in bits per second. user_limit: :class:`int` The channel's limit for number of members that can be in a voice channel. - rtc_region: Optional[:class:`VoiceRegion`] - The region for the voice channel's voice communication. + rtc_region: Optional[Union[:class:`str`, :class:`VoiceRegion`]] + The region ID for the voice channel's voice communication. A value of ``None`` indicates automatic voice region detection. + .. versionchanged:: 2.9 + + A :class:`VoiceRegion` member is still accepted, but it is + deprecated in favor of the region ID :class:`str`. + .. versionadded:: 1.7 video_quality_mode: :class:`VideoQualityMode` The camera video quality for the voice channel's participants. @@ -1714,7 +1719,7 @@ async def create_stage_channel( reason: str | None = None, bitrate: int = MISSING, user_limit: int = MISSING, - rtc_region: VoiceRegion | None = MISSING, + rtc_region: VoiceRegion | str | None = MISSING, video_quality_mode: VideoQualityMode = MISSING, slowmode_delay: int = MISSING, nsfw: bool = MISSING, @@ -1753,10 +1758,15 @@ async def create_stage_channel( .. versionadded:: 2.7 - rtc_region: Optional[:class:`VoiceRegion`] - The region for the voice channel's voice communication. + rtc_region: Optional[Union[:class:`str`, :class:`VoiceRegion`]] + The region ID for the voice channel's voice communication. A value of ``None`` indicates automatic voice region detection. + .. versionchanged:: 2.9 + + A :class:`VoiceRegion` member is still accepted, but it is + deprecated in favor of the region ID :class:`str`. + .. versionadded:: 2.7 video_quality_mode: :class:`VideoQualityMode` From 12acd61494a0c0c771b3731fccd585facb842fc6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 11 Aug 2026 13:31:26 +0000 Subject: [PATCH 06/16] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/channel.py | 4 +++- discord/enums.py | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/discord/channel.py b/discord/channel.py index 2749c4b3e2..d05c8f0ce1 100644 --- a/discord/channel.py +++ b/discord/channel.py @@ -48,12 +48,14 @@ InviteTarget, SortOrder, StagePrivacyLevel, +) +from .enums import ThreadArchiveDuration as ThreadArchiveDurationEnum +from .enums import ( VideoQualityMode, VoiceChannelEffectAnimationType, VoiceRegion, try_enum, ) -from .enums import ThreadArchiveDuration as ThreadArchiveDurationEnum from .errors import ClientException, InvalidArgument from .file import File from .flags import ChannelFlags, MessageFlags diff --git a/discord/enums.py b/discord/enums.py index b17060467b..904b68c340 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -34,13 +34,14 @@ if TYPE_CHECKING: from typing_extensions import deprecated else: - + def deprecated(message: str) -> Callable[[T], T]: def decorator(value: T) -> T: return value - + return decorator + from .utils import warn_deprecated __all__ = ( From 2e474dc02e13e08640462d338e1040a3584455aa Mon Sep 17 00:00:00 2001 From: vmphase Date: Tue, 11 Aug 2026 16:32:48 +0300 Subject: [PATCH 07/16] refactor(enums): import ordering --- discord/enums.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/discord/enums.py b/discord/enums.py index 904b68c340..bc1a5f4878 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -31,6 +31,8 @@ from enum import IntEnum from typing import TYPE_CHECKING, Any, ClassVar, TypeVar, Union +from .utils import warn_deprecated + if TYPE_CHECKING: from typing_extensions import deprecated else: @@ -42,8 +44,6 @@ def decorator(value: T) -> T: return decorator -from .utils import warn_deprecated - __all__ = ( "Enum", "ChannelType", From 0a47380654d9cfbce6b39ab17384f6aee469ebfe Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 11 Aug 2026 16:58:01 +0300 Subject: [PATCH 08/16] Update discord/guild.py Co-authored-by: Paillat Signed-off-by: Michael --- discord/guild.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/discord/guild.py b/discord/guild.py index a7993442e6..8ce4a9ca48 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -3803,9 +3803,7 @@ async def fetch_voice_regions(self) -> list[VoiceRegionPayload]: Retrieves the voice regions that the guild has access to. The list of voice regions is dynamic, so this method is the - recommended way to get the currently available regions instead of - relying on the deprecated :class:`VoiceRegion` enum. - + recommended way to get the currently available regions. .. versionadded:: 2.9 Each payload is a :class:`~discord.types.voice.VoiceRegion` TypedDict From 9faa30838570c8358919fc5a33103f625c024ca6 Mon Sep 17 00:00:00 2001 From: vmphase Date: Tue, 11 Aug 2026 20:19:59 +0300 Subject: [PATCH 09/16] refactor(types): make VoiceRegion a dataclass --- discord/guild.py | 20 ++++++++++---------- discord/http.py | 7 ++++--- discord/types/voice.py | 18 +++++++++++++++++- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/discord/guild.py b/discord/guild.py index 8ce4a9ca48..f7c21e14d7 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -91,6 +91,7 @@ from .stage_instance import StageInstance from .sticker import GuildSticker from .threads import Thread, ThreadMember +from .types.voice import VoiceRegion as VoiceRegionData from .user import User from .utils import _D, _FETCHABLE from .welcome_screen import WelcomeScreen, WelcomeScreenChannel @@ -121,7 +122,6 @@ from .types.guild import ModifyIncidents as ModifyIncidentsPayload from .types.member import Member as MemberPayload from .types.threads import Thread as ThreadPayload - from .types.voice import VoiceRegion as VoiceRegionPayload from .types.voice import VoiceState as GuildVoiceState from .voice import VoiceClient from .webhook import Webhook @@ -3797,7 +3797,7 @@ async def vanity_invite(self) -> Invite | None: payload["uses"] = payload.get("uses", 0) return Invite(state=self._state, data=payload, guild=self, channel=channel) - async def fetch_voice_regions(self) -> list[VoiceRegionPayload]: + async def fetch_voice_regions(self) -> list[VoiceRegionData]: """|coro| Retrieves the voice regions that the guild has access to. @@ -3806,19 +3806,18 @@ async def fetch_voice_regions(self) -> list[VoiceRegionPayload]: recommended way to get the currently available regions. .. versionadded:: 2.9 - Each payload is a :class:`~discord.types.voice.VoiceRegion` TypedDict - with the following keys: + Each :class:`~discord.types.voice.VoiceRegion` has the following attributes: - ``id`` + :attr:`~discord.types.voice.VoiceRegion.id` The region ID, e.g. ``"us-west"``. Use this as the :attr:`~discord.VoiceChannel.rtc_region` of a voice channel. - ``name`` + :attr:`~discord.types.voice.VoiceRegion.name` The region's display name, e.g. ``"US West"``. - ``optimal`` + :attr:`~discord.types.voice.VoiceRegion.optimal` Whether the region is optimal for the guild's members. - ``deprecated`` + :attr:`~discord.types.voice.VoiceRegion.deprecated` Whether the region is deprecated. - ``custom`` + :attr:`~discord.types.voice.VoiceRegion.custom` Whether the region is a custom region. Returns @@ -3831,7 +3830,8 @@ async def fetch_voice_regions(self) -> list[VoiceRegionPayload]: HTTPException Retrieving the voice regions failed. """ - return await self._state.http.get_guild_voice_regions(self.id) + regions = await self._state.http.get_guild_voice_regions(self.id) + return [VoiceRegionData(**region) for region in regions] # TODO: use MISSING when async iterators get refactored def audit_logs( diff --git a/discord/http.py b/discord/http.py index 7cf87639a0..e967921fe4 100644 --- a/discord/http.py +++ b/discord/http.py @@ -1045,13 +1045,14 @@ def guild_voice_state( return self.request(r, json=payload, reason=reason) def get_guild_voice_regions( - self, guild_id: Snowflake - ) -> Response[list[voice.VoiceRegion]]: + self, + guild_id: Snowflake, + ) -> Response[list[voice.VoiceRegionPayload]]: return self.request( Route("GET", "/guilds/{guild_id}/regions", guild_id=guild_id) ) - def get_voice_regions(self) -> Response[list[voice.VoiceRegion]]: + def get_voice_regions(self) -> Response[list[voice.VoiceRegionPayload]]: return self.request(Route("GET", "/voice/regions")) def edit_profile(self, payload: dict[str, Any]) -> Response[user.User]: diff --git a/discord/types/voice.py b/discord/types/voice.py index 307f98cee3..3f4e4dfd4a 100644 --- a/discord/types/voice.py +++ b/discord/types/voice.py @@ -25,6 +25,7 @@ from __future__ import annotations +from dataclasses import dataclass from typing import Literal from typing_extensions import NotRequired, TypedDict @@ -59,7 +60,22 @@ class VoiceState(TypedDict): GuildVoiceState = VoiceState -class VoiceRegion(TypedDict): +class VoiceRegionPayload(TypedDict): + id: str + name: str + vip: bool + optimal: bool + deprecated: bool + custom: bool + + +@dataclass(frozen=True, slots=True) +class VoiceRegion: + """Represents a voice region a guild can use for voice channels. + + This is returned by :meth:`Guild.fetch_voice_regions`. + """ + id: str name: str vip: bool From 0927a51cf5afca94eb57a26bb1142a08e9cbbd6b Mon Sep 17 00:00:00 2001 From: vmphase Date: Tue, 11 Aug 2026 20:31:29 +0300 Subject: [PATCH 10/16] refactor(regions): apply review suggestions Co-authored-by: Paillat --- discord/guild.py | 31 +++++++++++++++++++++++-------- discord/http.py | 6 +++--- discord/types/voice.py | 17 +---------------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/discord/guild.py b/discord/guild.py index f7c21e14d7..614229273e 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -29,6 +29,7 @@ import datetime import unicodedata from collections.abc import Sequence +from dataclasses import dataclass from typing import ( TYPE_CHECKING, Any, @@ -65,9 +66,9 @@ SortOrder, VerificationLevel, VideoQualityMode, - VoiceRegion, try_enum, ) +from .enums import VoiceRegion as VoiceRegionType from .errors import ClientException, HTTPException, InvalidArgument, InvalidData from .file import File from .flags import SystemChannelFlags @@ -91,7 +92,6 @@ from .stage_instance import StageInstance from .sticker import GuildSticker from .threads import Thread, ThreadMember -from .types.voice import VoiceRegion as VoiceRegionData from .user import User from .utils import _D, _FETCHABLE from .welcome_screen import WelcomeScreen, WelcomeScreenChannel @@ -148,6 +148,21 @@ class _GuildLimit(NamedTuple): filesize: int +@dataclass(frozen=True, slots=True) +class VoiceRegion: + """Represents a voice region a guild can use for voice channels. + + This is returned by :meth:`Guild.fetch_voice_regions`. + """ + + id: str + name: str + vip: bool + optimal: bool + deprecated: bool + custom: bool + + class GuildRoleCounts(dict[int, int]): """A dictionary subclass that maps role IDs to their member counts. @@ -1603,7 +1618,7 @@ async def create_voice_channel( position: int = MISSING, bitrate: int = MISSING, user_limit: int = MISSING, - rtc_region: VoiceRegion | str | None = MISSING, + rtc_region: VoiceRegionType | str | None = MISSING, video_quality_mode: VideoQualityMode = MISSING, overwrites: dict[Role | Member, PermissionOverwrite] = MISSING, slowmode_delay: int = MISSING, @@ -1719,7 +1734,7 @@ async def create_stage_channel( reason: str | None = None, bitrate: int = MISSING, user_limit: int = MISSING, - rtc_region: VoiceRegion | str | None = MISSING, + rtc_region: VoiceRegionType | str | None = MISSING, video_quality_mode: VideoQualityMode = MISSING, slowmode_delay: int = MISSING, nsfw: bool = MISSING, @@ -3797,7 +3812,7 @@ async def vanity_invite(self) -> Invite | None: payload["uses"] = payload.get("uses", 0) return Invite(state=self._state, data=payload, guild=self, channel=channel) - async def fetch_voice_regions(self) -> list[VoiceRegionData]: + async def fetch_voice_regions(self) -> list[VoiceRegion]: """|coro| Retrieves the voice regions that the guild has access to. @@ -3806,7 +3821,7 @@ async def fetch_voice_regions(self) -> list[VoiceRegionData]: recommended way to get the currently available regions. .. versionadded:: 2.9 - Each :class:`~discord.types.voice.VoiceRegion` has the following attributes: + Each :class:`~discord.guild.VoiceRegion` has the following attributes: :attr:`~discord.types.voice.VoiceRegion.id` The region ID, e.g. ``"us-west"``. Use this as the @@ -3822,7 +3837,7 @@ async def fetch_voice_regions(self) -> list[VoiceRegionData]: Returns ------- - List[:class:`~discord.types.voice.VoiceRegion`] + List[:class:`~discord.guild.VoiceRegion`] The list of voice regions the guild has access to. Raises @@ -3831,7 +3846,7 @@ async def fetch_voice_regions(self) -> list[VoiceRegionData]: Retrieving the voice regions failed. """ regions = await self._state.http.get_guild_voice_regions(self.id) - return [VoiceRegionData(**region) for region in regions] + return [VoiceRegion(**region) for region in regions] # TODO: use MISSING when async iterators get refactored def audit_logs( diff --git a/discord/http.py b/discord/http.py index e967921fe4..223db40713 100644 --- a/discord/http.py +++ b/discord/http.py @@ -85,7 +85,6 @@ template, threads, user, - voice, webhook, welcome_screen, widget, @@ -95,6 +94,7 @@ ) from .types.snowflake import Snowflake, SnowflakeList from .types.soundboard import SoundboardSound as SoundboardSoundPayload + from .types.voice import VoiceRegion as VoiceRegionPayload T = TypeVar("T") BE = TypeVar("BE", bound=BaseException) @@ -1047,12 +1047,12 @@ def guild_voice_state( def get_guild_voice_regions( self, guild_id: Snowflake, - ) -> Response[list[voice.VoiceRegionPayload]]: + ) -> Response[list[VoiceRegionPayload]]: return self.request( Route("GET", "/guilds/{guild_id}/regions", guild_id=guild_id) ) - def get_voice_regions(self) -> Response[list[voice.VoiceRegionPayload]]: + def get_voice_regions(self) -> Response[list[VoiceRegionPayload]]: return self.request(Route("GET", "/voice/regions")) def edit_profile(self, payload: dict[str, Any]) -> Response[user.User]: diff --git a/discord/types/voice.py b/discord/types/voice.py index 3f4e4dfd4a..4f9b534b27 100644 --- a/discord/types/voice.py +++ b/discord/types/voice.py @@ -60,22 +60,7 @@ class VoiceState(TypedDict): GuildVoiceState = VoiceState -class VoiceRegionPayload(TypedDict): - id: str - name: str - vip: bool - optimal: bool - deprecated: bool - custom: bool - - -@dataclass(frozen=True, slots=True) -class VoiceRegion: - """Represents a voice region a guild can use for voice channels. - - This is returned by :meth:`Guild.fetch_voice_regions`. - """ - +class VoiceRegion(TypedDict): id: str name: str vip: bool From fe66309e789b295cd6a6f98c69c120690b016cac Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 11 Aug 2026 17:32:08 +0000 Subject: [PATCH 11/16] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/guild.py | 2 +- discord/types/voice.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/discord/guild.py b/discord/guild.py index 614229273e..ff3e4b123e 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -66,9 +66,9 @@ SortOrder, VerificationLevel, VideoQualityMode, - try_enum, ) from .enums import VoiceRegion as VoiceRegionType +from .enums import try_enum from .errors import ClientException, HTTPException, InvalidArgument, InvalidData from .file import File from .flags import SystemChannelFlags diff --git a/discord/types/voice.py b/discord/types/voice.py index 4f9b534b27..307f98cee3 100644 --- a/discord/types/voice.py +++ b/discord/types/voice.py @@ -25,7 +25,6 @@ from __future__ import annotations -from dataclasses import dataclass from typing import Literal from typing_extensions import NotRequired, TypedDict From fd2b819f27813dd19b7fb5d76c45c5780fb321e3 Mon Sep 17 00:00:00 2001 From: vmphase Date: Tue, 11 Aug 2026 20:35:20 +0300 Subject: [PATCH 12/16] chore: rename VoiceRegion to VoiceRegionType for consistency with guild.py --- discord/channel.py | 14 ++++++-------- discord/guild.py | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/discord/channel.py b/discord/channel.py index d05c8f0ce1..a5bbbeb67d 100644 --- a/discord/channel.py +++ b/discord/channel.py @@ -48,14 +48,12 @@ InviteTarget, SortOrder, StagePrivacyLevel, -) -from .enums import ThreadArchiveDuration as ThreadArchiveDurationEnum -from .enums import ( VideoQualityMode, VoiceChannelEffectAnimationType, - VoiceRegion, try_enum, ) +from .enums import ThreadArchiveDuration as ThreadArchiveDurationEnum +from .enums import VoiceRegion as VoiceRegionType from .errors import ClientException, InvalidArgument from .file import File from .flags import ChannelFlags, MessageFlags @@ -1638,8 +1636,8 @@ def _update( # This data may be missing depending on how this object is being created/updated if not data.pop("_invoke_flag", False): rtc = data.get("rtc_region") - self.rtc_region: VoiceRegion | None = ( - try_enum(VoiceRegion, rtc) if rtc is not None else None + self.rtc_region: VoiceRegionType | None = ( + try_enum(VoiceRegionType, rtc) if rtc is not None else None ) self.video_quality_mode: VideoQualityMode = try_enum( VideoQualityMode, data.get("video_quality_mode", 1) @@ -2091,7 +2089,7 @@ async def edit( sync_permissions: int = ..., category: CategoryChannel | None = ..., overwrites: Mapping[Role | Member, PermissionOverwrite] = ..., - rtc_region: VoiceRegion | str | None = ..., + rtc_region: VoiceRegionType | str | None = ..., video_quality_mode: VideoQualityMode = ..., slowmode_delay: int = ..., nsfw: bool = ..., @@ -2783,7 +2781,7 @@ async def edit( sync_permissions: int = ..., category: CategoryChannel | None = ..., overwrites: Mapping[Role | Member, PermissionOverwrite] = ..., - rtc_region: VoiceRegion | str | None = ..., + rtc_region: VoiceRegionType | str | None = ..., video_quality_mode: VideoQualityMode = ..., reason: str | None = ..., ) -> StageChannel | None: ... diff --git a/discord/guild.py b/discord/guild.py index ff3e4b123e..614229273e 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -66,9 +66,9 @@ SortOrder, VerificationLevel, VideoQualityMode, + try_enum, ) from .enums import VoiceRegion as VoiceRegionType -from .enums import try_enum from .errors import ClientException, HTTPException, InvalidArgument, InvalidData from .file import File from .flags import SystemChannelFlags From 74d66230b908260287ffc15a954a4db3ec05a654 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 11 Aug 2026 17:35:58 +0000 Subject: [PATCH 13/16] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/channel.py | 5 ++--- discord/guild.py | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/discord/channel.py b/discord/channel.py index a5bbbeb67d..f8a1ec431e 100644 --- a/discord/channel.py +++ b/discord/channel.py @@ -48,12 +48,11 @@ InviteTarget, SortOrder, StagePrivacyLevel, - VideoQualityMode, - VoiceChannelEffectAnimationType, - try_enum, ) from .enums import ThreadArchiveDuration as ThreadArchiveDurationEnum +from .enums import VideoQualityMode, VoiceChannelEffectAnimationType from .enums import VoiceRegion as VoiceRegionType +from .enums import try_enum from .errors import ClientException, InvalidArgument from .file import File from .flags import ChannelFlags, MessageFlags diff --git a/discord/guild.py b/discord/guild.py index 614229273e..ff3e4b123e 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -66,9 +66,9 @@ SortOrder, VerificationLevel, VideoQualityMode, - try_enum, ) from .enums import VoiceRegion as VoiceRegionType +from .enums import try_enum from .errors import ClientException, HTTPException, InvalidArgument, InvalidData from .file import File from .flags import SystemChannelFlags From defeffb8add6b4dc6d8678c241c6d012740285f3 Mon Sep 17 00:00:00 2001 From: vmphase Date: Tue, 11 Aug 2026 21:31:16 +0300 Subject: [PATCH 14/16] refactor: change dataclass naming Co-authored-by: ToothyDev --- discord/channel.py | 15 ++++++++------- discord/guild.py | 18 +++++++++--------- 2 files changed, 17 insertions(+), 16 deletions(-) mode change 100644 => 100755 discord/channel.py diff --git a/discord/channel.py b/discord/channel.py old mode 100644 new mode 100755 index f8a1ec431e..2749c4b3e2 --- a/discord/channel.py +++ b/discord/channel.py @@ -48,11 +48,12 @@ InviteTarget, SortOrder, StagePrivacyLevel, + VideoQualityMode, + VoiceChannelEffectAnimationType, + VoiceRegion, + try_enum, ) from .enums import ThreadArchiveDuration as ThreadArchiveDurationEnum -from .enums import VideoQualityMode, VoiceChannelEffectAnimationType -from .enums import VoiceRegion as VoiceRegionType -from .enums import try_enum from .errors import ClientException, InvalidArgument from .file import File from .flags import ChannelFlags, MessageFlags @@ -1635,8 +1636,8 @@ def _update( # This data may be missing depending on how this object is being created/updated if not data.pop("_invoke_flag", False): rtc = data.get("rtc_region") - self.rtc_region: VoiceRegionType | None = ( - try_enum(VoiceRegionType, rtc) if rtc is not None else None + self.rtc_region: VoiceRegion | None = ( + try_enum(VoiceRegion, rtc) if rtc is not None else None ) self.video_quality_mode: VideoQualityMode = try_enum( VideoQualityMode, data.get("video_quality_mode", 1) @@ -2088,7 +2089,7 @@ async def edit( sync_permissions: int = ..., category: CategoryChannel | None = ..., overwrites: Mapping[Role | Member, PermissionOverwrite] = ..., - rtc_region: VoiceRegionType | str | None = ..., + rtc_region: VoiceRegion | str | None = ..., video_quality_mode: VideoQualityMode = ..., slowmode_delay: int = ..., nsfw: bool = ..., @@ -2780,7 +2781,7 @@ async def edit( sync_permissions: int = ..., category: CategoryChannel | None = ..., overwrites: Mapping[Role | Member, PermissionOverwrite] = ..., - rtc_region: VoiceRegionType | str | None = ..., + rtc_region: VoiceRegion | str | None = ..., video_quality_mode: VideoQualityMode = ..., reason: str | None = ..., ) -> StageChannel | None: ... diff --git a/discord/guild.py b/discord/guild.py index ff3e4b123e..24b0b9134e 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -66,9 +66,9 @@ SortOrder, VerificationLevel, VideoQualityMode, + VoiceRegion, + try_enum, ) -from .enums import VoiceRegion as VoiceRegionType -from .enums import try_enum from .errors import ClientException, HTTPException, InvalidArgument, InvalidData from .file import File from .flags import SystemChannelFlags @@ -149,7 +149,7 @@ class _GuildLimit(NamedTuple): @dataclass(frozen=True, slots=True) -class VoiceRegion: +class VoiceServerRegion: """Represents a voice region a guild can use for voice channels. This is returned by :meth:`Guild.fetch_voice_regions`. @@ -1618,7 +1618,7 @@ async def create_voice_channel( position: int = MISSING, bitrate: int = MISSING, user_limit: int = MISSING, - rtc_region: VoiceRegionType | str | None = MISSING, + rtc_region: VoiceRegion | str | None = MISSING, video_quality_mode: VideoQualityMode = MISSING, overwrites: dict[Role | Member, PermissionOverwrite] = MISSING, slowmode_delay: int = MISSING, @@ -1734,7 +1734,7 @@ async def create_stage_channel( reason: str | None = None, bitrate: int = MISSING, user_limit: int = MISSING, - rtc_region: VoiceRegionType | str | None = MISSING, + rtc_region: VoiceRegion | str | None = MISSING, video_quality_mode: VideoQualityMode = MISSING, slowmode_delay: int = MISSING, nsfw: bool = MISSING, @@ -3812,7 +3812,7 @@ async def vanity_invite(self) -> Invite | None: payload["uses"] = payload.get("uses", 0) return Invite(state=self._state, data=payload, guild=self, channel=channel) - async def fetch_voice_regions(self) -> list[VoiceRegion]: + async def fetch_voice_regions(self) -> list[VoiceServerRegion]: """|coro| Retrieves the voice regions that the guild has access to. @@ -3821,7 +3821,7 @@ async def fetch_voice_regions(self) -> list[VoiceRegion]: recommended way to get the currently available regions. .. versionadded:: 2.9 - Each :class:`~discord.guild.VoiceRegion` has the following attributes: + Each :class:`~discord.guild.VoiceServerRegion` has the following attributes: :attr:`~discord.types.voice.VoiceRegion.id` The region ID, e.g. ``"us-west"``. Use this as the @@ -3837,7 +3837,7 @@ async def fetch_voice_regions(self) -> list[VoiceRegion]: Returns ------- - List[:class:`~discord.guild.VoiceRegion`] + List[:class:`~discord.guild.VoiceServerRegion`] The list of voice regions the guild has access to. Raises @@ -3846,7 +3846,7 @@ async def fetch_voice_regions(self) -> list[VoiceRegion]: Retrieving the voice regions failed. """ regions = await self._state.http.get_guild_voice_regions(self.id) - return [VoiceRegion(**region) for region in regions] + return [VoiceServerRegion(**region) for region in regions] # TODO: use MISSING when async iterators get refactored def audit_logs( From 82bf07f570be4c197c52da64b45af64153cec127 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 11 Aug 2026 18:31:55 +0000 Subject: [PATCH 15/16] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/channel.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/discord/channel.py b/discord/channel.py index 2749c4b3e2..d05c8f0ce1 100755 --- a/discord/channel.py +++ b/discord/channel.py @@ -48,12 +48,14 @@ InviteTarget, SortOrder, StagePrivacyLevel, +) +from .enums import ThreadArchiveDuration as ThreadArchiveDurationEnum +from .enums import ( VideoQualityMode, VoiceChannelEffectAnimationType, VoiceRegion, try_enum, ) -from .enums import ThreadArchiveDuration as ThreadArchiveDurationEnum from .errors import ClientException, InvalidArgument from .file import File from .flags import ChannelFlags, MessageFlags From 3278b8985ca9e54a4e42004e711ffdece417f8bf Mon Sep 17 00:00:00 2001 From: vmphase Date: Wed, 12 Aug 2026 18:52:35 +0300 Subject: [PATCH 16/16] refactor: apply code review suggestions Co-authored-by: ToothyDev --- discord/channel.py | 6 ++++-- discord/enums.py | 4 ++-- discord/guild.py | 20 ++++++++++++-------- docs/api/enums.rst | 4 ++-- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/discord/channel.py b/discord/channel.py index d05c8f0ce1..14520be005 100755 --- a/discord/channel.py +++ b/discord/channel.py @@ -2142,7 +2142,8 @@ async def edit(self, *, reason=None, **options): .. versionchanged:: 2.9 A :class:`VoiceRegion` member is still accepted, but it is - deprecated in favor of the region ID :class:`str`. + deprecated in favor of the region ID :class:`str`, which + can be retrieved via :meth:`Guild.fetch_voice_regions`. .. versionadded:: 1.7 video_quality_mode: :class:`VideoQualityMode` @@ -2828,7 +2829,8 @@ async def edit(self, *, reason=None, **options): .. versionchanged:: 2.9 A :class:`VoiceRegion` member is still accepted, but it is - deprecated in favor of the region ID :class:`str`. + deprecated in favor of the region ID :class:`str`, which + can be retrieved via :meth:`Guild.fetch_voice_regions`. video_quality_mode: :class:`VideoQualityMode` The camera video quality for the stage channel's participants. diff --git a/discord/enums.py b/discord/enums.py index bc1a5f4878..5cb720e414 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -341,8 +341,8 @@ class VoiceRegion(Enum, metaclass=_VoiceRegionMeta): .. deprecated:: 2.9 The list of voice regions is dynamic, so this enum is deprecated in favor - of the region ID :class:`str` or :meth:`Guild.fetch_voice_regions` and - will be removed in version 3.0. + of the region ID :class:`str`, which can be retrieved via + :meth:`Guild.fetch_voice_regions`, and will be removed in version 3.0. """ brazil = "brazil" diff --git a/discord/guild.py b/discord/guild.py index 24b0b9134e..f84cf8c32e 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -153,11 +153,12 @@ class VoiceServerRegion: """Represents a voice region a guild can use for voice channels. This is returned by :meth:`Guild.fetch_voice_regions`. + + .. versionadded:: 2.9 """ id: str name: str - vip: bool optimal: bool deprecated: bool custom: bool @@ -1652,7 +1653,8 @@ async def create_voice_channel( .. versionchanged:: 2.9 A :class:`VoiceRegion` member is still accepted, but it is - deprecated in favor of the region ID :class:`str`. + deprecated in favor of the region ID :class:`str`, which + can be retrieved via :meth:`Guild.fetch_voice_regions`. .. versionadded:: 1.7 video_quality_mode: :class:`VideoQualityMode` @@ -1780,7 +1782,8 @@ async def create_stage_channel( .. versionchanged:: 2.9 A :class:`VoiceRegion` member is still accepted, but it is - deprecated in favor of the region ID :class:`str`. + deprecated in favor of the region ID :class:`str`, which + can be retrieved via :meth:`Guild.fetch_voice_regions`. .. versionadded:: 2.7 @@ -3819,20 +3822,21 @@ async def fetch_voice_regions(self) -> list[VoiceServerRegion]: The list of voice regions is dynamic, so this method is the recommended way to get the currently available regions. + .. versionadded:: 2.9 Each :class:`~discord.guild.VoiceServerRegion` has the following attributes: - :attr:`~discord.types.voice.VoiceRegion.id` + :attr:`~discord.guild.VoiceServerRegion.id` The region ID, e.g. ``"us-west"``. Use this as the :attr:`~discord.VoiceChannel.rtc_region` of a voice channel. - :attr:`~discord.types.voice.VoiceRegion.name` + :attr:`~discord.guild.VoiceServerRegion.name` The region's display name, e.g. ``"US West"``. - :attr:`~discord.types.voice.VoiceRegion.optimal` + :attr:`~discord.guild.VoiceServerRegion.optimal` Whether the region is optimal for the guild's members. - :attr:`~discord.types.voice.VoiceRegion.deprecated` + :attr:`~discord.guild.VoiceServerRegion.deprecated` Whether the region is deprecated. - :attr:`~discord.types.voice.VoiceRegion.custom` + :attr:`~discord.guild.VoiceServerRegion.custom` Whether the region is a custom region. Returns diff --git a/docs/api/enums.rst b/docs/api/enums.rst index 139588e8a1..f9ca7fb9a7 100644 --- a/docs/api/enums.rst +++ b/docs/api/enums.rst @@ -618,8 +618,8 @@ of :class:`enum.Enum`. .. deprecated:: 2.9 The list of voice regions is dynamic, so this enum is deprecated in favor - of the region ID :class:`str` or :meth:`Guild.fetch_voice_regions` and - will be removed in version 3.0. + of the region ID :class:`str`, which can be retrieved via + :meth:`Guild.fetch_voice_regions`, and will be removed in version 3.0. .. attribute:: brazil