Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions discord/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,10 @@ def __init__(
): ...

def __str__(self) -> str:
flags = getattr(self, "flags", None)
if flags is not None and getattr(flags, "obfuscated", False):
return f"Obfuscated Channel ({self.id})"

return self.name

@property
Expand Down
4 changes: 4 additions & 0 deletions discord/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ class Client:
If not given, defaults to a regularly constructed :class:`Intents` class.

.. versionadded:: 1.5
capabilities: :class:`GatewayCapabilities`
Gateway capabilities to include with the IDENTIFY payload. Defaults to
:meth:`GatewayCapabilities.none`. These are mostly undocumented and may not
be supported for bot accounts.
member_cache_flags: :class:`MemberCacheFlags`
Allows for finer control over how the library caches members.
If not given, defaults to cache as much as possible with the
Expand Down
37 changes: 37 additions & 0 deletions discord/flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"MessageFlags",
"AttachmentFlags",
"PublicUserFlags",
"GatewayCapabilities",
"Intents",
"MemberCacheFlags",
"ApplicationFlags",
Expand Down Expand Up @@ -587,6 +588,36 @@ def all(self) -> list[UserFlags]:
]


@fill_with_flags()
class GatewayCapabilities(BaseFlags):
"""Wraps Discord gateway capabilities.

These bits are mostly undocumented and meant for specialized clients. They are
sent with the IDENTIFY payload as the ``capabilities`` field.

Attributes
----------
value: :class:`int`
The raw capability value. Prefer toggling via the provided attributes.
"""

__slots__ = ()

@classmethod
def none(cls) -> GatewayCapabilities:
"""Creates a :class:`GatewayCapabilities` instance with no bits enabled."""

self = cls.__new__(cls)
self.value = cls.DEFAULT_VALUE
return self

@flag_value
def obfuscated_channels(self):
""":class:`bool`: Obfuscates channel identifiers in gateway events."""

return 1 << 15


@fill_with_flags()
class Intents(BaseFlags):
r"""Wraps up a Discord gateway intent flag.
Expand Down Expand Up @@ -1585,6 +1616,12 @@ def hide_media_download_options(self):
"""
return 1 << 15

@flag_value
def obfuscated(self):
""":class:`bool`: Returns ``True`` if the channel is obfuscated by the gateway."""

return 1 << 17


@fill_with_flags()
class AttachmentFlags(BaseFlags):
Expand Down
4 changes: 4 additions & 0 deletions discord/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ async def from_client(
ws.session_id = session
ws.sequence = sequence
ws._max_heartbeat_timeout = client._connection.heartbeat_timeout
ws.capabilities = client._connection.capabilities.value

if client._enable_debug_events:
ws.send = ws.debug_send
Expand Down Expand Up @@ -420,6 +421,9 @@ async def identify(self):
},
"compress": True,
"large_threshold": 250,
"capabilities": (
self.capabilities if hasattr(self, "capabilities") else 0
),
},
}

Expand Down
14 changes: 13 additions & 1 deletion discord/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
from .channel import _channel_factory
from .emoji import AppEmoji, GuildEmoji
from .enums import ChannelType, InteractionType, ScheduledEventStatus, Status, try_enum
from .flags import ApplicationFlags, Intents, MemberCacheFlags
from .flags import ApplicationFlags, GatewayCapabilities, Intents, MemberCacheFlags
from .guild import Guild
from .integrations import _integration_factory
from .interactions import Interaction
Expand Down Expand Up @@ -248,6 +248,18 @@ def __init__(
self._status: str | None = status
self._intents: Intents = intents

capabilities = options.get("capabilities")
if capabilities is None:
capabilities = GatewayCapabilities.none()
elif isinstance(capabilities, int):
capabilities = GatewayCapabilities._from_value(capabilities)
elif not isinstance(capabilities, GatewayCapabilities):
raise TypeError(
"capabilities parameter must be GatewayCapabilities or int."
)

self.capabilities: GatewayCapabilities = capabilities

if not intents.members or cache_flags._empty:
self.store_user = self.create_user # type: ignore
self.deref_user = self.deref_user_no_intents # type: ignore
Expand Down