Skip to content

Commit 76a3e4c

Browse files
Icebluewolfpre-commit-ci[bot]plun1331LulalabyDorukyum
authored
feat: implement voice channel statuses (#2368)
Signed-off-by: Icebluewolf <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: plun1331 <[email protected]> Co-authored-by: Lala Sabathil <[email protected]> Co-authored-by: Dorukyum <[email protected]>
1 parent 2276914 commit 76a3e4c

File tree

10 files changed

+155
-2
lines changed

10 files changed

+155
-2
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ These changes are available on the `master` branch, but have not yet been releas
9393
([#2342](https://github.com/Pycord-Development/pycord/pull/2342))
9494
- Added `invitable` and `slowmode_delay` to `Thread` creation methods.
9595
([#2350](https://github.com/Pycord-Development/pycord/pull/2350))
96+
- Added support for voice channel statuses.
97+
([#2368](https://github.com/Pycord-Development/pycord/pull/2368))
9698

9799
### Changed
98100

discord/channel.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,20 +1519,37 @@ class VoiceChannel(discord.abc.Messageable, VocalGuildChannel):
15191519
Bots and users with :attr:`~Permissions.manage_channels` or
15201520
:attr:`~Permissions.manage_messages` bypass slowmode.
15211521
1522+
.. versionadded:: 2.5
1523+
status: Optional[:class:`str`]
1524+
The channel's status, if set.
1525+
15221526
.. versionadded:: 2.5
15231527
flags: :class:`ChannelFlags`
15241528
Extra features of the channel.
15251529
15261530
.. versionadded:: 2.0
15271531
"""
15281532

1533+
def __init__(
1534+
self,
1535+
*,
1536+
state: ConnectionState,
1537+
guild: Guild,
1538+
data: VoiceChannelPayload,
1539+
):
1540+
self.status: str | None = None
1541+
super().__init__(state=state, guild=guild, data=data)
1542+
15291543
def _update(self, guild: Guild, data: VoiceChannelPayload):
15301544
super()._update(guild, data)
1545+
if data.get("status"):
1546+
self.status = data.get("status")
15311547

15321548
def __repr__(self) -> str:
15331549
attrs = [
15341550
("id", self.id),
15351551
("name", self.name),
1552+
("status", self.status),
15361553
("rtc_region", self.rtc_region),
15371554
("position", self.position),
15381555
("bitrate", self.bitrate),
@@ -1955,6 +1972,31 @@ async def create_activity_invite(
19551972
**kwargs,
19561973
)
19571974

1975+
async def set_status(
1976+
self, status: str | None, *, reason: str | None = None
1977+
) -> None:
1978+
"""|coro|
1979+
1980+
Sets the status of the voice channel.
1981+
1982+
You must have the :attr:`~Permissions.set_voice_channel_status` permission to use this.
1983+
1984+
Parameters
1985+
----------
1986+
status: Union[:class:`str`, None]
1987+
The new status.
1988+
reason: Optional[:class:`str`]
1989+
The reason for setting the status. Shows up on the audit log.
1990+
1991+
Raises
1992+
------
1993+
Forbidden
1994+
You do not have proper permissions to set the status.
1995+
HTTPException
1996+
Setting the status failed.
1997+
"""
1998+
await self._state.http.set_voice_channel_status(self.id, status, reason=reason)
1999+
19582000

19592001
class StageChannel(discord.abc.Messageable, VocalGuildChannel):
19602002
"""Represents a Discord guild stage channel.

discord/http.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2185,6 +2185,13 @@ def move_member(
21852185
guild_id=guild_id, user_id=user_id, channel_id=channel_id, reason=reason
21862186
)
21872187

2188+
def set_voice_channel_status(
2189+
self, channel_id: Snowflake, status: str | None, *, reason: str | None = None
2190+
) -> Response[None]:
2191+
payload = {"status": status}
2192+
r = Route("PUT", "/channels/{channel_id}/voice-status", channel_id=channel_id)
2193+
return self.request(r, json=payload, reason=reason)
2194+
21882195
# Stage instance management
21892196

21902197
def get_stage_instance(

discord/permissions.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ def all(cls: type[P]) -> P:
180180
"""A factory method that creates a :class:`Permissions` with all
181181
permissions set to ``True``.
182182
"""
183-
return cls(0b11111111111111111111111111111111111111111)
183+
return cls(0b1111111111111111111111111111111111111111111111111)
184184

185185
@classmethod
186186
def all_channel(cls: type[P]) -> P:
@@ -250,7 +250,7 @@ def voice(cls: type[P]) -> P:
250250
"""A factory method that creates a :class:`Permissions` with all
251251
"Voice" permissions from the official Discord UI set to ``True``.
252252
"""
253-
return cls(0b00000011111100000000001100000000)
253+
return cls(0b1000000001000000000000011111100000000001100000000)
254254

255255
@classmethod
256256
def stage(cls: type[P]) -> P:
@@ -618,6 +618,14 @@ def send_voice_messages(self) -> int:
618618
"""
619619
return 1 << 46
620620

621+
@flag_value
622+
def set_voice_channel_status(self) -> int:
623+
""":class:`bool`: Returns ``True`` if a member can set voice channel status.
624+
625+
.. versionadded:: 2.5
626+
"""
627+
return 1 << 48
628+
621629

622630
PO = TypeVar("PO", bound="PermissionOverwrite")
623631

@@ -736,6 +744,7 @@ class PermissionOverwrite:
736744
start_embedded_activities: bool | None
737745
moderate_members: bool | None
738746
send_voice_messages: bool | None
747+
set_voice_channel_status: bool | None
739748

740749
def __init__(self, **kwargs: bool | None):
741750
self._values: dict[str, bool | None] = {}

discord/raw_models.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
ThreadMembersUpdateEvent,
5757
ThreadUpdateEvent,
5858
TypingEvent,
59+
VoiceChannelStatusUpdateEvent,
5960
)
6061

6162

@@ -75,6 +76,7 @@
7576
"AutoModActionExecutionEvent",
7677
"RawThreadMembersUpdateEvent",
7778
"RawAuditLogEntryEvent",
79+
"RawVoiceChannelStatusUpdateEvent",
7880
)
7981

8082

@@ -441,6 +443,36 @@ def __init__(self, data: ThreadDeleteEvent) -> None:
441443
self.data: ThreadDeleteEvent = data
442444

443445

446+
class RawVoiceChannelStatusUpdateEvent(_RawReprMixin):
447+
"""Represents the payload for an :func:`on_raw_voice_channel_status_update` event.
448+
449+
.. versionadded:: 2.5
450+
451+
Attributes
452+
----------
453+
id: :class:`int`
454+
The channel ID where the voice channel status update originated from.
455+
guild_id: :class:`int`
456+
The guild ID where the voice channel status update originated from.
457+
status: Optional[:class:`str`]
458+
The new new voice channel status.
459+
data: :class:`dict`
460+
The raw data sent by the `gateway <https://discord.com/developers/docs/topics/gateway-events#voice-channel-status-update>`_.
461+
"""
462+
463+
__slots__ = ("id", "guild_id", "status", "data")
464+
465+
def __init__(self, data: VoiceChannelStatusUpdateEvent) -> None:
466+
self.id: int = int(data["id"])
467+
self.guild_id: int = int(data["guild_id"])
468+
469+
try:
470+
self.status: str | None = data["status"]
471+
except KeyError:
472+
self.status: str | None = None
473+
self.data: VoiceChannelStatusUpdateEvent = data
474+
475+
444476
class RawTypingEvent(_RawReprMixin):
445477
"""Represents the payload for a :func:`on_raw_typing` event.
446478

discord/state.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1785,6 +1785,30 @@ def parse_voice_server_update(self, data) -> None:
17851785
)
17861786
)
17871787

1788+
def parse_voice_channel_status_update(self, data) -> None:
1789+
raw = RawVoiceChannelStatusUpdateEvent(data)
1790+
self.dispatch("raw_voice_channel_status_update", raw)
1791+
guild = self._get_guild(int(data["guild_id"]))
1792+
channel_id = int(data["id"])
1793+
if guild is not None:
1794+
channel = guild.get_channel(channel_id)
1795+
if channel is not None:
1796+
old_status = channel.status
1797+
channel.status = data.get("status", None)
1798+
self.dispatch(
1799+
"voice_channel_status_update", channel, old_status, channel.status
1800+
)
1801+
else:
1802+
_log.debug(
1803+
"VOICE_CHANNEL_STATUS_UPDATE referencing an unknown channel ID: %s. Discarding.",
1804+
channel_id,
1805+
)
1806+
else:
1807+
_log.debug(
1808+
"VOICE_CHANNEL_STATUS_UPDATE referencing unknown guild ID: %s. Discarding.",
1809+
data["guild_id"],
1810+
)
1811+
17881812
def parse_typing_start(self, data) -> None:
17891813
raw = RawTypingEvent(data)
17901814

discord/types/channel.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ class NewsChannel(_BaseGuildChannel, _TextChannelOptional):
108108
class VoiceChannel(_BaseGuildChannel):
109109
rtc_region: NotRequired[str | None]
110110
video_quality_mode: NotRequired[VideoQualityMode]
111+
status: NotRequired[str | None]
111112
type: Literal[2]
112113
bitrate: int
113114
user_limit: int

discord/types/raw_models.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ class MemberRemoveEvent(TypedDict):
131131
user: User
132132

133133

134+
class VoiceChannelStatusUpdateEvent(TypedDict):
135+
id: Snowflake
136+
guild_id: Snowflake
137+
status: NotRequired[str]
138+
139+
134140
class ThreadMembersUpdateEvent(TypedDict):
135141
id: Snowflake
136142
guild_id: Snowflake

docs/api/events.rst

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,3 +1299,28 @@ Typing
12991299

13001300
:param payload: The raw typing payload.
13011301
:type payload: :class:`RawTypingEvent`
1302+
1303+
1304+
Voice Channel Status Update
1305+
---------------------------
1306+
.. function:: on_voice_channel_status_update(channel, before, after)
1307+
1308+
Called when someone updates a voice channel status.
1309+
1310+
.. versionadded:: 2.5
1311+
1312+
:param channel: The channel where the voice channel status update originated from.
1313+
:type channel: :class:`abc.GuildChannel`
1314+
:param before: The old voice channel status.
1315+
:type before: Optional[:class:`str`]
1316+
:param after: The new voice channel status.
1317+
:type after: Optional[:class:`str`]
1318+
1319+
.. function:: on_raw_voice_channel_status_update(payload)
1320+
1321+
Called when someone updates a voice channels status.
1322+
1323+
.. versionadded:: 2.5
1324+
1325+
:param payload: The raw voice channel status update payload.
1326+
:type payload: :class:`RawVoiceChannelStatusUpdateEvent`

docs/api/models.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,11 @@ Events
556556
.. autoclass:: RawAuditLogEntryEvent()
557557
:members:
558558

559+
.. attributetable:: RawVoiceChannelStatusUpdateEvent
560+
561+
.. autoclass:: RawVoiceChannelStatusUpdateEvent()
562+
:members:
563+
559564

560565

561566
Webhooks

0 commit comments

Comments
 (0)