mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-04-11 20:04:17 +00:00
Add raw presence update evemt
This commit is contained in:
parent
afbbc07e98
commit
418a7915e6
@ -72,6 +72,7 @@ from .automod import *
|
||||
from .poll import *
|
||||
from .soundboard import *
|
||||
from .subscription import *
|
||||
from .presences import *
|
||||
|
||||
|
||||
class VersionInfo(NamedTuple):
|
||||
|
@ -237,6 +237,15 @@ class Client:
|
||||
To enable these events, this must be set to ``True``. Defaults to ``False``.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
enable_raw_presences: :class:`bool`
|
||||
Whether to manually enable or disable the :func:`on_raw_presence_update` event.
|
||||
|
||||
Setting this flag to ``True`` requires :attr:`Intents.presences` to be enabled.
|
||||
|
||||
By default, this flag is set to ``True`` only when :attr:`Intents.presences` is enabled and :attr:`Intents.members`
|
||||
is disabled, otherwise it's set to ``False``.
|
||||
|
||||
.. versionadded:: 2.5
|
||||
http_trace: :class:`aiohttp.TraceConfig`
|
||||
The trace configuration to use for tracking HTTP requests the library does using ``aiohttp``.
|
||||
This allows you to check requests the library is using. For more information, check the
|
||||
|
@ -95,7 +95,7 @@ from .welcome_screen import WelcomeScreen, WelcomeChannel
|
||||
from .automod import AutoModRule, AutoModTrigger, AutoModRuleAction
|
||||
from .partial_emoji import _EmojiTag, PartialEmoji
|
||||
from .soundboard import SoundboardSound
|
||||
|
||||
from .presences import RawPresenceUpdateEvent
|
||||
|
||||
__all__ = (
|
||||
'Guild',
|
||||
@ -653,10 +653,11 @@ class Guild(Hashable):
|
||||
|
||||
empty_tuple = ()
|
||||
for presence in guild.get('presences', []):
|
||||
user_id = int(presence['user']['id'])
|
||||
member = self.get_member(user_id)
|
||||
raw_presence = RawPresenceUpdateEvent(data=presence, state=self._state)
|
||||
member = self.get_member(raw_presence.user_id)
|
||||
|
||||
if member is not None:
|
||||
member._presence_update(presence, empty_tuple) # type: ignore
|
||||
member._presence_update(raw_presence, empty_tuple) # type: ignore
|
||||
|
||||
if 'threads' in guild:
|
||||
threads = guild['threads']
|
||||
|
@ -36,13 +36,13 @@ from . import utils
|
||||
from .asset import Asset
|
||||
from .utils import MISSING
|
||||
from .user import BaseUser, ClientUser, User, _UserTag
|
||||
from .activity import create_activity, ActivityTypes
|
||||
from .permissions import Permissions
|
||||
from .enums import Status, try_enum
|
||||
from .enums import Status
|
||||
from .errors import ClientException
|
||||
from .colour import Colour
|
||||
from .object import Object
|
||||
from .flags import MemberFlags
|
||||
from .presences import ClientStatus
|
||||
|
||||
__all__ = (
|
||||
'VoiceState',
|
||||
@ -57,10 +57,8 @@ if TYPE_CHECKING:
|
||||
from .channel import DMChannel, VoiceChannel, StageChannel
|
||||
from .flags import PublicUserFlags
|
||||
from .guild import Guild
|
||||
from .types.activity import (
|
||||
ClientStatus as ClientStatusPayload,
|
||||
PartialPresenceUpdate,
|
||||
)
|
||||
from .activity import ActivityTypes
|
||||
from .presences import RawPresenceUpdateEvent
|
||||
from .types.member import (
|
||||
MemberWithUser as MemberWithUserPayload,
|
||||
Member as MemberPayload,
|
||||
@ -168,46 +166,6 @@ class VoiceState:
|
||||
return f'<{self.__class__.__name__} {inner}>'
|
||||
|
||||
|
||||
class _ClientStatus:
|
||||
__slots__ = ('_status', 'desktop', 'mobile', 'web')
|
||||
|
||||
def __init__(self):
|
||||
self._status: str = 'offline'
|
||||
|
||||
self.desktop: Optional[str] = None
|
||||
self.mobile: Optional[str] = None
|
||||
self.web: Optional[str] = None
|
||||
|
||||
def __repr__(self) -> str:
|
||||
attrs = [
|
||||
('_status', self._status),
|
||||
('desktop', self.desktop),
|
||||
('mobile', self.mobile),
|
||||
('web', self.web),
|
||||
]
|
||||
inner = ' '.join('%s=%r' % t for t in attrs)
|
||||
return f'<{self.__class__.__name__} {inner}>'
|
||||
|
||||
def _update(self, status: str, data: ClientStatusPayload, /) -> None:
|
||||
self._status = status
|
||||
|
||||
self.desktop = data.get('desktop')
|
||||
self.mobile = data.get('mobile')
|
||||
self.web = data.get('web')
|
||||
|
||||
@classmethod
|
||||
def _copy(cls, client_status: Self, /) -> Self:
|
||||
self = cls.__new__(cls) # bypass __init__
|
||||
|
||||
self._status = client_status._status
|
||||
|
||||
self.desktop = client_status.desktop
|
||||
self.mobile = client_status.mobile
|
||||
self.web = client_status.web
|
||||
|
||||
return self
|
||||
|
||||
|
||||
def flatten_user(cls: T) -> T:
|
||||
for attr, value in itertools.chain(BaseUser.__dict__.items(), User.__dict__.items()):
|
||||
# ignore private/special methods
|
||||
@ -306,6 +264,10 @@ class Member(discord.abc.Messageable, _UserTag):
|
||||
This will be set to ``None`` or a time in the past if the user is not timed out.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
client_status: :class:`ClientStatus`
|
||||
Model which holds information about the status of the member on various clients/platforms via presence updates.
|
||||
|
||||
.. versionadded:: 2.5
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
@ -318,7 +280,7 @@ class Member(discord.abc.Messageable, _UserTag):
|
||||
'nick',
|
||||
'timed_out_until',
|
||||
'_permissions',
|
||||
'_client_status',
|
||||
'client_status',
|
||||
'_user',
|
||||
'_state',
|
||||
'_avatar',
|
||||
@ -354,7 +316,7 @@ class Member(discord.abc.Messageable, _UserTag):
|
||||
self.joined_at: Optional[datetime.datetime] = utils.parse_time(data.get('joined_at'))
|
||||
self.premium_since: Optional[datetime.datetime] = utils.parse_time(data.get('premium_since'))
|
||||
self._roles: utils.SnowflakeList = utils.SnowflakeList(map(int, data['roles']))
|
||||
self._client_status: _ClientStatus = _ClientStatus()
|
||||
self.client_status: ClientStatus = ClientStatus()
|
||||
self.activities: Tuple[ActivityTypes, ...] = ()
|
||||
self.nick: Optional[str] = data.get('nick', None)
|
||||
self.pending: bool = data.get('pending', False)
|
||||
@ -430,7 +392,7 @@ class Member(discord.abc.Messageable, _UserTag):
|
||||
self._roles = utils.SnowflakeList(member._roles, is_sorted=True)
|
||||
self.joined_at = member.joined_at
|
||||
self.premium_since = member.premium_since
|
||||
self._client_status = _ClientStatus._copy(member._client_status)
|
||||
self.client_status = member.client_status
|
||||
self.guild = member.guild
|
||||
self.nick = member.nick
|
||||
self.pending = member.pending
|
||||
@ -473,13 +435,12 @@ class Member(discord.abc.Messageable, _UserTag):
|
||||
self._flags = data.get('flags', 0)
|
||||
self._avatar_decoration_data = data.get('avatar_decoration_data')
|
||||
|
||||
def _presence_update(self, data: PartialPresenceUpdate, user: UserPayload) -> Optional[Tuple[User, User]]:
|
||||
self.activities = tuple(create_activity(d, self._state) for d in data['activities'])
|
||||
self._client_status._update(data['status'], data['client_status'])
|
||||
def _presence_update(self, raw: RawPresenceUpdateEvent, user: UserPayload) -> Optional[Tuple[User, User]]:
|
||||
self.activities = raw.activities
|
||||
self.client_status = raw.client_status
|
||||
|
||||
if len(user) > 1:
|
||||
return self._update_inner_user(user)
|
||||
return None
|
||||
|
||||
def _update_inner_user(self, user: UserPayload) -> Optional[Tuple[User, User]]:
|
||||
u = self._user
|
||||
@ -518,7 +479,7 @@ class Member(discord.abc.Messageable, _UserTag):
|
||||
@property
|
||||
def status(self) -> Status:
|
||||
""":class:`Status`: The member's overall status. If the value is unknown, then it will be a :class:`str` instead."""
|
||||
return try_enum(Status, self._client_status._status)
|
||||
return self.client_status.status
|
||||
|
||||
@property
|
||||
def raw_status(self) -> str:
|
||||
@ -526,31 +487,36 @@ class Member(discord.abc.Messageable, _UserTag):
|
||||
|
||||
.. versionadded:: 1.5
|
||||
"""
|
||||
return self._client_status._status
|
||||
return self.client_status._status
|
||||
|
||||
@status.setter
|
||||
def status(self, value: Status) -> None:
|
||||
# internal use only
|
||||
self._client_status._status = str(value)
|
||||
self.client_status._status = str(value)
|
||||
|
||||
@property
|
||||
def mobile_status(self) -> Status:
|
||||
""":class:`Status`: The member's status on a mobile device, if applicable."""
|
||||
return try_enum(Status, self._client_status.mobile or 'offline')
|
||||
return self.client_status.mobile_status
|
||||
|
||||
@property
|
||||
def desktop_status(self) -> Status:
|
||||
""":class:`Status`: The member's status on the desktop client, if applicable."""
|
||||
return try_enum(Status, self._client_status.desktop or 'offline')
|
||||
return self.client_status.desktop_status
|
||||
|
||||
@property
|
||||
def web_status(self) -> Status:
|
||||
""":class:`Status`: The member's status on the web client, if applicable."""
|
||||
return try_enum(Status, self._client_status.web or 'offline')
|
||||
return self.client_status.web_status
|
||||
|
||||
def is_on_mobile(self) -> bool:
|
||||
""":class:`bool`: A helper function that determines if a member is active on a mobile device."""
|
||||
return self._client_status.mobile is not None
|
||||
"""A helper function that determines if a member is active on a mobile device.
|
||||
|
||||
Returns
|
||||
-------
|
||||
:class:`bool`
|
||||
"""
|
||||
return self.client_status.is_on_mobile()
|
||||
|
||||
@property
|
||||
def colour(self) -> Colour:
|
||||
|
150
discord/presences.py
Normal file
150
discord/presences.py
Normal file
@ -0,0 +1,150 @@
|
||||
"""
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-present Rapptz
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Optional, Tuple
|
||||
|
||||
from .activity import create_activity
|
||||
from .enums import Status, try_enum
|
||||
from .utils import MISSING, _get_as_snowflake, _RawReprMixin
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing_extensions import Self
|
||||
|
||||
from .activity import ActivityTypes
|
||||
from .guild import Guild
|
||||
from .state import ConnectionState
|
||||
from .types.activity import ClientStatus as ClientStatusPayload, PartialPresenceUpdate
|
||||
|
||||
|
||||
__all__ = (
|
||||
'RawPresenceUpdateEvent',
|
||||
'ClientStatus',
|
||||
)
|
||||
|
||||
|
||||
class ClientStatus:
|
||||
"""Represents the :ddocs:`Client Status Object <events/gateway-events#client-status-object>` from Discord,
|
||||
which holds information about the status of the user on various clients/platforms, with additional helpers.
|
||||
|
||||
.. versionadded:: 2.5
|
||||
"""
|
||||
|
||||
__slots__ = ('_status', 'desktop', 'mobile', 'web')
|
||||
|
||||
def __init__(self, *, status: str = MISSING, data: ClientStatusPayload = MISSING) -> None:
|
||||
self._status: str = status or 'offline'
|
||||
|
||||
data = data or {}
|
||||
self.desktop: Optional[str] = data.get('desktop')
|
||||
self.mobile: Optional[str] = data.get('mobile')
|
||||
self.web: Optional[str] = data.get('web')
|
||||
|
||||
def __repr__(self) -> str:
|
||||
attrs = [
|
||||
('_status', self._status),
|
||||
('desktop', self.desktop),
|
||||
('mobile', self.mobile),
|
||||
('web', self.web),
|
||||
]
|
||||
inner = ' '.join('%s=%r' % t for t in attrs)
|
||||
return f'<{self.__class__.__name__} {inner}>'
|
||||
|
||||
def _update(self, status: str, data: ClientStatusPayload, /) -> None:
|
||||
self._status = status
|
||||
|
||||
self.desktop = data.get('desktop')
|
||||
self.mobile = data.get('mobile')
|
||||
self.web = data.get('web')
|
||||
|
||||
@classmethod
|
||||
def _copy(cls, client_status: Self, /) -> Self:
|
||||
self = cls.__new__(cls) # bypass __init__
|
||||
|
||||
self._status = client_status._status
|
||||
|
||||
self.desktop = client_status.desktop
|
||||
self.mobile = client_status.mobile
|
||||
self.web = client_status.web
|
||||
|
||||
return self
|
||||
|
||||
@property
|
||||
def status(self) -> Status:
|
||||
""":class:`Status`: The user's overall status. If the value is unknown, then it will be a :class:`str` instead."""
|
||||
return try_enum(Status, self._status)
|
||||
|
||||
@property
|
||||
def raw_status(self) -> str:
|
||||
""":class:`str`: The user's overall status as a string value."""
|
||||
return self._status
|
||||
|
||||
@property
|
||||
def mobile_status(self) -> Status:
|
||||
""":class:`Status`: The user's status on a mobile device, if applicable."""
|
||||
return try_enum(Status, self.mobile or 'offline')
|
||||
|
||||
@property
|
||||
def desktop_status(self) -> Status:
|
||||
""":class:`Status`: The user's status on the desktop client, if applicable."""
|
||||
return try_enum(Status, self.desktop or 'offline')
|
||||
|
||||
@property
|
||||
def web_status(self) -> Status:
|
||||
""":class:`Status`: The user's status on the web client, if applicable."""
|
||||
return try_enum(Status, self.web or 'offline')
|
||||
|
||||
def is_on_mobile(self) -> bool:
|
||||
""":class:`bool`: A helper function that determines if a user is active on a mobile device."""
|
||||
return self.mobile is not None
|
||||
|
||||
|
||||
class RawPresenceUpdateEvent(_RawReprMixin):
|
||||
"""Represents the payload for a :func:`on_raw_presence_update` event.
|
||||
|
||||
.. versionadded:: 2.5
|
||||
|
||||
Attributes
|
||||
----------
|
||||
user_id: :class:`int`
|
||||
The ID of the user that triggered the presence update.
|
||||
guild_id: Optional[:class:`int`]
|
||||
The guild ID for the users presence update. Could be ``None``.
|
||||
guild: Optional[:class:`Guild`]
|
||||
The guild associated with the presence update and user. Could be ``None``.
|
||||
client_status: :class:`ClientStatus`
|
||||
The :class:`~.ClientStatus` model which holds information about the status of the user on various clients.
|
||||
activities: Tuple[Union[:class:`BaseActivity`, :class:`Spotify`]]
|
||||
The activities the user is currently doing. Due to a Discord API limitation, a user's Spotify activity may not appear
|
||||
if they are listening to a song with a title longer than ``128`` characters. See :issue:`1738` for more information.
|
||||
"""
|
||||
|
||||
__slots__ = ('user_id', 'guild_id', 'guild', 'client_status', 'activities')
|
||||
|
||||
def __init__(self, *, data: PartialPresenceUpdate, state: ConnectionState) -> None:
|
||||
self.user_id: int = int(data['user']['id'])
|
||||
self.client_status: ClientStatus = ClientStatus(status=data['status'], data=data['client_status'])
|
||||
self.activities: Tuple[ActivityTypes, ...] = tuple(create_activity(d, state) for d in data['activities'])
|
||||
self.guild_id: Optional[int] = _get_as_snowflake(data, 'guild_id')
|
||||
self.guild: Optional[Guild] = state._get_guild(self.guild_id)
|
@ -25,10 +25,10 @@ DEALINGS IN THE SOFTWARE.
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
from typing import TYPE_CHECKING, Literal, Optional, Set, List, Tuple, Union
|
||||
from typing import TYPE_CHECKING, Literal, Optional, Set, List, Union
|
||||
|
||||
from .enums import ChannelType, try_enum, ReactionType
|
||||
from .utils import _get_as_snowflake
|
||||
from .utils import _get_as_snowflake, _RawReprMixin
|
||||
from .app_commands import AppCommandPermissions
|
||||
from .colour import Colour
|
||||
|
||||
@ -82,14 +82,6 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class _RawReprMixin:
|
||||
__slots__: Tuple[str, ...] = ()
|
||||
|
||||
def __repr__(self) -> str:
|
||||
value = ' '.join(f'{attr}={getattr(self, attr)!r}' for attr in self.__slots__)
|
||||
return f'<{self.__class__.__name__} {value}>'
|
||||
|
||||
|
||||
class RawMessageDeleteEvent(_RawReprMixin):
|
||||
"""Represents the event payload for a :func:`on_raw_message_delete` event.
|
||||
|
||||
|
@ -62,6 +62,7 @@ from .message import Message
|
||||
from .channel import *
|
||||
from .channel import _channel_factory
|
||||
from .raw_models import *
|
||||
from .presences import RawPresenceUpdateEvent
|
||||
from .member import Member
|
||||
from .role import Role
|
||||
from .enums import ChannelType, try_enum, Status
|
||||
@ -261,6 +262,10 @@ class ConnectionState(Generic[ClientT]):
|
||||
if not intents.members or cache_flags._empty:
|
||||
self.store_user = self.store_user_no_intents
|
||||
|
||||
self.raw_presence_flag: bool = options.get('enable_raw_presences', utils.MISSING)
|
||||
if self.raw_presence_flag is utils.MISSING:
|
||||
self.raw_presence_flag = not intents.members and intents.presences
|
||||
|
||||
self.parsers: Dict[str, Callable[[Any], None]]
|
||||
self.parsers = parsers = {}
|
||||
for attr, func in inspect.getmembers(self):
|
||||
@ -827,22 +832,24 @@ class ConnectionState(Generic[ClientT]):
|
||||
self.dispatch('interaction', interaction)
|
||||
|
||||
def parse_presence_update(self, data: gw.PresenceUpdateEvent) -> None:
|
||||
guild_id = utils._get_as_snowflake(data, 'guild_id')
|
||||
# guild_id won't be None here
|
||||
guild = self._get_guild(guild_id)
|
||||
if guild is None:
|
||||
_log.debug('PRESENCE_UPDATE referencing an unknown guild ID: %s. Discarding.', guild_id)
|
||||
raw = RawPresenceUpdateEvent(data=data, state=self)
|
||||
|
||||
if self.raw_presence_flag:
|
||||
self.dispatch('raw_presence_update', raw)
|
||||
|
||||
if raw.guild is None:
|
||||
_log.debug('PRESENCE_UPDATE referencing an unknown guild ID: %s. Discarding.', raw.guild_id)
|
||||
return
|
||||
|
||||
user = data['user']
|
||||
member_id = int(user['id'])
|
||||
member = guild.get_member(member_id)
|
||||
member = raw.guild.get_member(raw.user_id)
|
||||
|
||||
if member is None:
|
||||
_log.debug('PRESENCE_UPDATE referencing an unknown member ID: %s. Discarding', member_id)
|
||||
_log.debug('PRESENCE_UPDATE referencing an unknown member ID: %s. Discarding', raw.user_id)
|
||||
return
|
||||
|
||||
old_member = Member._copy(member)
|
||||
user_update = member._presence_update(data=data, user=user)
|
||||
user_update = member._presence_update(raw=raw, user=data['user'])
|
||||
|
||||
if user_update:
|
||||
self.dispatch('user_update', user_update[0], user_update[1])
|
||||
|
||||
@ -1430,8 +1437,10 @@ class ConnectionState(Generic[ClientT]):
|
||||
user = presence['user']
|
||||
member_id = user['id']
|
||||
member = member_dict.get(member_id)
|
||||
|
||||
if member is not None:
|
||||
member._presence_update(presence, user)
|
||||
raw_presence = RawPresenceUpdateEvent(data=presence, state=self)
|
||||
member._presence_update(raw_presence, user)
|
||||
|
||||
complete = data.get('chunk_index', 0) + 1 == data.get('chunk_count')
|
||||
self.process_chunk_requests(guild_id, data.get('nonce'), members, complete)
|
||||
|
@ -1532,3 +1532,11 @@ def _format_call_duration(duration: datetime.timedelta) -> str:
|
||||
formatted = f"{years} years"
|
||||
|
||||
return formatted
|
||||
|
||||
|
||||
class _RawReprMixin:
|
||||
__slots__: Tuple[str, ...] = ()
|
||||
|
||||
def __repr__(self) -> str:
|
||||
value = ' '.join(f'{attr}={getattr(self, attr)!r}' for attr in self.__slots__)
|
||||
return f'<{self.__class__.__name__} {value}>'
|
||||
|
39
docs/api.rst
39
docs/api.rst
@ -916,6 +916,29 @@ Members
|
||||
:param after: The updated member's updated info.
|
||||
:type after: :class:`Member`
|
||||
|
||||
.. function:: on_raw_presence_update(payload)
|
||||
|
||||
Called when a :class:`Member` updates their presence.
|
||||
|
||||
This requires :attr:`Intents.presences` to be enabled.
|
||||
|
||||
Unlike :func:`on_presence_update`, when enabled, this is called regardless of the state of internal guild
|
||||
and member caches, and **does not** provide a comparison between the previous and updated states of the :class:`Member`.
|
||||
|
||||
.. important::
|
||||
|
||||
By default, this event is only dispatched when :attr:`Intents.presences` is enabled **and** :attr:`Intents.members`
|
||||
is disabled.
|
||||
|
||||
You can manually override this behaviour by setting the **enable_raw_presences** flag in the :class:`Client`,
|
||||
however :attr:`Intents.presences` is always required for this event to work.
|
||||
|
||||
.. versionadded:: 2.5
|
||||
|
||||
:param payload: The raw presence update event model.
|
||||
:type payload: :class:`RawPresenceUpdateEvent`
|
||||
|
||||
|
||||
Messages
|
||||
~~~~~~~~~
|
||||
|
||||
@ -5364,6 +5387,14 @@ RawPollVoteActionEvent
|
||||
.. autoclass:: RawPollVoteActionEvent()
|
||||
:members:
|
||||
|
||||
RawPresenceUpdateEvent
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. attributetable:: RawPresenceUpdateEvent
|
||||
|
||||
.. autoclass:: RawPresenceUpdateEvent()
|
||||
:members:
|
||||
|
||||
PartialWebhookGuild
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -5398,6 +5429,14 @@ MessageSnapshot
|
||||
.. autoclass:: MessageSnapshot
|
||||
:members:
|
||||
|
||||
ClientStatus
|
||||
~~~~~~~~~~~~
|
||||
|
||||
.. attributetable:: ClientStatus
|
||||
|
||||
.. autoclass:: ClientStatus()
|
||||
:members:
|
||||
|
||||
Data Classes
|
||||
--------------
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user