Skip to content

Commit 2b81493

Browse files
committed
feat: gateway capabilities
1 parent 924a8f2 commit 2b81493

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
@@ -351,6 +351,10 @@ def __init__(
351351
): ...
352352

353353
def __str__(self) -> str:
354+
flags = getattr(self, "flags", None)
355+
if flags is not None and getattr(flags, "obfuscated", False):
356+
return f"Obfuscated Channel ({self.id})"
357+
354358
return self.name
355359

356360
@property

discord/client.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ class Client:
169169
If not given, defaults to a regularly constructed :class:`Intents` class.
170170
171171
.. versionadded:: 1.5
172+
capabilities: :class:`GatewayCapabilities`
173+
Gateway capabilities to include with the IDENTIFY payload. Defaults to
174+
:meth:`GatewayCapabilities.none`. These are mostly undocumented and may not
175+
be supported for bot accounts.
172176
member_cache_flags: :class:`MemberCacheFlags`
173177
Allows for finer control over how the library caches members.
174178
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
@@ -35,6 +35,7 @@
3535
"MessageFlags",
3636
"AttachmentFlags",
3737
"PublicUserFlags",
38+
"GatewayCapabilities",
3839
"Intents",
3940
"MemberCacheFlags",
4041
"ApplicationFlags",
@@ -588,6 +589,36 @@ def all(self) -> list[UserFlags]:
588589
]
589590

590591

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

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

15911628
@fill_with_flags()
15921629
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
@@ -49,7 +49,7 @@
4949
from .channel import _channel_factory
5050
from .emoji import AppEmoji, GuildEmoji
5151
from .enums import ChannelType, InteractionType, ScheduledEventStatus, Status, try_enum
52-
from .flags import ApplicationFlags, Intents, MemberCacheFlags
52+
from .flags import ApplicationFlags, GatewayCapabilities, Intents, MemberCacheFlags
5353
from .guild import Guild
5454
from .integrations import _integration_factory
5555
from .interactions import Interaction
@@ -247,6 +247,18 @@ def __init__(
247247
self._status: str | None = status
248248
self._intents: Intents = intents
249249

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

0 commit comments

Comments
 (0)