Skip to content

Commit

Permalink
Initial reworking (chunking at startup works :)
Browse files Browse the repository at this point in the history
  • Loading branch information
dolfies committed Feb 1, 2024
1 parent 43f46aa commit 110423d
Show file tree
Hide file tree
Showing 9 changed files with 799 additions and 370 deletions.
14 changes: 14 additions & 0 deletions discord/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,20 @@ def __str__(self) -> str:
def _sorting_bucket(self) -> int:
raise NotImplementedError

@property
def member_list_id(self) -> Union[str, Literal["everyone"]]:
if self.permissions_for(self.guild.default_role).read_messages:
return "everyone"

overwrites = []
for overwrite in self._overwrites:
allow, deny = Permissions(overwrite.allow), Permissions(overwrite.deny)
if allow.read_messages:
overwrites.append(f"allow:{overwrite.id}")
elif deny.read_messages:
overwrites.append(f"deny:{overwrite.id}")
return str(utils.murmurhash32(",".join(sorted(overwrites)), signed=False))

def _update(self, guild: Guild, data: Dict[str, Any]) -> None:
raise NotImplementedError

Expand Down
25 changes: 13 additions & 12 deletions discord/flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -367,8 +367,15 @@ def passive_guild_update(self):
@flag_value
def unknown_12(self):
""":class:`bool`: Unknown."""
# Might be pomelo or family center related
return 1 << 12

@flag_value
def message_reaction_debouncing(self):
""":class:`bool`: Unknown."""
# Almost definitely message reaction debouncing (MESSAGE_REACTION_ADD_MANY)
return 1 << 13


@fill_with_flags(inverted=True)
class SystemChannelFlags(BaseFlags):
Expand Down Expand Up @@ -1171,23 +1178,17 @@ def voice(self):
return 1

@flag_value
def other(self):
""":class:`bool`: Whether to cache members that are collected from other means.
This does not apply to members explicitly cached (e.g. :attr:`Guild.chunk`, :attr:`Guild.fetch_members`).
def joined(self):
""":class:`bool`: Whether to cache members that joined the guild
or are chunked as part of the initial log in flow.
There is an alias for this called :attr:`joined`.
Members that leave the guild are no longer cached.
"""
return 2

@alias_flag_value
def joined(self):
""":class:`bool`: Whether to cache members that are collected from other means.
This does not apply to members explicitly cached (e.g. :attr:`Guild.chunk`, :attr:`Guild.fetch_members`).
This is an alias for :attr:`other`.
"""
def other(self):
""":class:`bool`: Alias for :attr:`joined`."""
return 2

@property
Expand Down
96 changes: 18 additions & 78 deletions discord/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
from .enums import Status
from .state import ConnectionState
from .types.snowflake import Snowflake
from .types.gateway import BulkGuildSubscribePayload
from .voice_client import VoiceClient


Expand Down Expand Up @@ -238,45 +239,10 @@ class DiscordWebSocket:
Attributes
-----------
DISPATCH
Receive only. Denotes an event to be sent to Discord, such as READY.
HEARTBEAT
When received tells Discord to keep the connection alive.
When sent asks if your connection is currently alive.
IDENTIFY
Send only. Starts a new session.
PRESENCE
Send only. Updates your presence.
VOICE_STATE
Send only. Starts a new connection to a voice guild.
VOICE_PING
Send only. Checks ping time to a voice guild, do not use.
RESUME
Send only. Resumes an existing connection.
RECONNECT
Receive only. Tells the client to reconnect to a new gateway.
REQUEST_MEMBERS
Send only. Asks for the guild members.
INVALIDATE_SESSION
Receive only. Tells the client to optionally invalidate the session
and IDENTIFY again.
HELLO
Receive only. Tells the client the heartbeat interval.
HEARTBEAT_ACK
Receive only. Confirms receiving of a heartbeat. Not having it implies
a connection issue.
GUILD_SYNC
Send only. Requests a guild sync. This is unfortunately no longer functional.
CALL_CONNECT
Send only. Maybe used for calling? Probably just tracking.
GUILD_SUBSCRIBE
Send only. Subscribes you to guilds/guild members. Might respond with GUILD_MEMBER_LIST_UPDATE.
REQUEST_COMMANDS
Send only. Requests application commands from a guild. Responds with GUILD_APPLICATION_COMMANDS_UPDATE.
gateway
The gateway we are currently connected to.
token
The authentication token for discord.
The authentication token for Discord.
"""

if TYPE_CHECKING:
Expand Down Expand Up @@ -307,11 +273,12 @@ class DiscordWebSocket:
INVALIDATE_SESSION = 9
HELLO = 10
HEARTBEAT_ACK = 11
GUILD_SYNC = 12 # :(
# GUILD_SYNC = 12
CALL_CONNECT = 13
GUILD_SUBSCRIBE = 14
REQUEST_COMMANDS = 24
GUILD_SUBSCRIBE = 14 # Deprecated
# REQUEST_COMMANDS = 24
SEARCH_RECENT_MEMBERS = 35
BULK_GUILD_SUBSCRIBE = 37
# fmt: on

def __init__(self, socket: aiohttp.ClientWebSocketResponse, *, loop: asyncio.AbstractEventLoop) -> None:
Expand Down Expand Up @@ -724,7 +691,7 @@ async def change_presence(
_log.debug('Sending "%s" to change presence.', sent)
await self.send(sent)

async def request_lazy_guild(
async def guild_subscribe(
self,
guild_id: Snowflake,
*,
Expand Down Expand Up @@ -759,6 +726,17 @@ async def request_lazy_guild(
_log.debug('Subscribing to guild %s with payload %s', guild_id, payload['d'])
await self.send_as_json(payload)

async def bulk_guild_subscribe(self, subscriptions: BulkGuildSubscribePayload) -> None:
payload = {
'op': self.BULK_GUILD_SUBSCRIBE,
'd': {
'subscriptions': subscriptions,
},
}

_log.debug('Subscribing to guilds with payload %s', payload['d'])
await self.send_as_json(payload)

async def request_chunks(
self,
guild_ids: List[Snowflake],
Expand Down Expand Up @@ -818,44 +796,6 @@ async def call_connect(self, channel_id: Snowflake):
_log.debug('Requesting call connect for channel %s.', channel_id)
await self.send_as_json(payload)

async def request_commands(
self,
guild_id: Snowflake,
type: int,
*,
nonce: Optional[str] = None,
limit: Optional[int] = None,
applications: Optional[bool] = None,
offset: int = 0,
query: Optional[str] = None,
command_ids: Optional[List[Snowflake]] = None,
application_id: Optional[Snowflake] = None,
) -> None:
payload = {
'op': self.REQUEST_COMMANDS,
'd': {
'guild_id': str(guild_id),
'type': type,
},
}

if nonce is not None:
payload['d']['nonce'] = nonce
if applications is not None:
payload['d']['applications'] = applications
if limit is not None and limit != 25:
payload['d']['limit'] = limit
if offset:
payload['d']['offset'] = offset
if query is not None:
payload['d']['query'] = query
if command_ids is not None:
payload['d']['command_ids'] = command_ids
if application_id is not None:
payload['d']['application_id'] = str(application_id)

await self.send_as_json(payload)

async def search_recent_members(
self, guild_id: Snowflake, query: str = '', *, after: Optional[Snowflake] = None, nonce: Optional[str] = None
) -> None:
Expand Down
Loading

0 comments on commit 110423d

Please sign in to comment.