Skip to content

Commit 15f96ee

Browse files
committed
feat: gateway capabilities
1 parent d9890f3 commit 15f96ee

5 files changed

Lines changed: 62 additions & 1 deletion

File tree

discord/abc.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,10 @@ def __init__(
347347
): ...
348348

349349
def __str__(self) -> str:
350+
flags = getattr(self, "flags", None)
351+
if flags is not None and getattr(flags, "obfuscated", False):
352+
return f"Obfuscated Channel ({self.id})"
353+
350354
return self.name
351355

352356
@property

discord/client.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ class Client:
166166
If not given, defaults to a regularly constructed :class:`Intents` class.
167167
168168
.. versionadded:: 1.5
169+
capabilities: :class:`GatewayCapabilities`
170+
Gateway capabilities to include with the IDENTIFY payload. Defaults to
171+
:meth:`GatewayCapabilities.none`. These are mostly undocumented and may not
172+
be supported for bot accounts.
169173
member_cache_flags: :class:`MemberCacheFlags`
170174
Allows for finer control over how the library caches members.
171175
If not given, defaults to cache as much as possible with the

discord/flags.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"MessageFlags",
3535
"AttachmentFlags",
3636
"PublicUserFlags",
37+
"GatewayCapabilities",
3738
"Intents",
3839
"MemberCacheFlags",
3940
"ApplicationFlags",
@@ -587,6 +588,36 @@ def all(self) -> list[UserFlags]:
587588
]
588589

589590

591+
@fill_with_flags()
592+
class GatewayCapabilities(BaseFlags):
593+
"""Wraps Discord gateway capabilities.
594+
595+
These bits are mostly undocumented and meant for specialized clients. They are
596+
sent with the IDENTIFY payload as the ``capabilities`` field.
597+
598+
Attributes
599+
----------
600+
value: :class:`int`
601+
The raw capability value. Prefer toggling via the provided attributes.
602+
"""
603+
604+
__slots__ = ()
605+
606+
@classmethod
607+
def none(cls) -> GatewayCapabilities:
608+
"""Creates a :class:`GatewayCapabilities` instance with no bits enabled."""
609+
610+
self = cls.__new__(cls)
611+
self.value = cls.DEFAULT_VALUE
612+
return self
613+
614+
@flag_value
615+
def obfuscated_channels(self):
616+
""":class:`bool`: Obfuscates channel identifiers in gateway events."""
617+
618+
return 1 << 15
619+
620+
590621
@fill_with_flags()
591622
class Intents(BaseFlags):
592623
r"""Wraps up a Discord gateway intent flag.
@@ -1586,6 +1617,12 @@ def hide_media_download_options(self):
15861617
"""
15871618
return 1 << 15
15881619

1620+
@flag_value
1621+
def obfuscated(self):
1622+
""":class:`bool`: Returns ``True`` if the channel is obfuscated by the gateway."""
1623+
1624+
return 1 << 17
1625+
15891626

15901627
@fill_with_flags()
15911628
class AttachmentFlags(BaseFlags):

discord/gateway.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ async def from_client(
368368
ws.session_id = session
369369
ws.sequence = sequence
370370
ws._max_heartbeat_timeout = client._connection.heartbeat_timeout
371+
ws.capabilities = client._connection.capabilities.value
371372

372373
if client._enable_debug_events:
373374
ws.send = ws.debug_send
@@ -432,6 +433,9 @@ async def identify(self) -> None:
432433
},
433434
"compress": True,
434435
"large_threshold": 250,
436+
"capabilities": (
437+
self.capabilities if hasattr(self, "capabilities") else 0
438+
),
435439
},
436440
}
437441

discord/state.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
from .channel import _channel_factory
5252
from .emoji import AppEmoji, GuildEmoji
5353
from .enums import ChannelType, InteractionType, ScheduledEventStatus, Status, try_enum
54-
from .flags import ApplicationFlags, Intents, MemberCacheFlags
54+
from .flags import ApplicationFlags, GatewayCapabilities, Intents, MemberCacheFlags
5555
from .guild import Guild
5656
from .integrations import _integration_factory
5757
from .interactions import Interaction
@@ -249,6 +249,18 @@ def __init__(
249249
self._status: str | None = status
250250
self._intents: Intents = intents
251251

252+
capabilities = options.get("capabilities")
253+
if capabilities is None:
254+
capabilities = GatewayCapabilities.none()
255+
elif isinstance(capabilities, int):
256+
capabilities = GatewayCapabilities._from_value(capabilities)
257+
elif not isinstance(capabilities, GatewayCapabilities):
258+
raise TypeError(
259+
"capabilities parameter must be GatewayCapabilities or int."
260+
)
261+
262+
self.capabilities: GatewayCapabilities = capabilities
263+
252264
if not intents.members or cache_flags._empty:
253265
self.store_user = self.create_user # type: ignore
254266
self.deref_user = self.deref_user_no_intents # type: ignore

0 commit comments

Comments
 (0)