mirror of
				https://github.com/Rapptz/discord.py.git
				synced 2025-10-30 21:12:58 +00:00 
			
		
		
		
	Better chunking behaviour and add members on PRESENCE_UPDATE.
This should hopefully cover all cases where members are added. There was a bug where an array of chunks received would get entirely processed if only a single chunk was received. This was fixed by explicitly bailing early if we're requesting for chunks.
This commit is contained in:
		| @@ -46,7 +46,7 @@ class ListenerType(enum.Enum): | ||||
|  | ||||
| Listener = namedtuple('Listener', ('type', 'future', 'predicate')) | ||||
| log = logging.getLogger(__name__) | ||||
| ReadyState = namedtuple('ReadyState', ('launch', 'chunks', 'servers')) | ||||
| ReadyState = namedtuple('ReadyState', ('launch', 'servers')) | ||||
|  | ||||
| class ConnectionState: | ||||
|     def __init__(self, dispatch, chunker, max_messages, *, loop): | ||||
| @@ -85,6 +85,8 @@ class ConnectionState: | ||||
|                 if passed: | ||||
|                     future.set_result(result) | ||||
|                     removed.append(i) | ||||
|                     if listener.type == ListenerType.chunk: | ||||
|                         break | ||||
|  | ||||
|         for index in reversed(removed): | ||||
|             del self._listeners[index] | ||||
| @@ -134,16 +136,7 @@ class ConnectionState: | ||||
|             yield self.receive_chunk(server.id) | ||||
|  | ||||
|     @asyncio.coroutine | ||||
|     def _delay_ready(self, large_servers): | ||||
|         if len(large_servers): | ||||
|             # for regular accounts with < 100 guilds you will | ||||
|             # get a regular READY packet without the unavailable | ||||
|             # streaming so if this is non-empty then it's a regular | ||||
|             # account and it needs chunking. | ||||
|             yield from self.chunker(large_servers) | ||||
|             for server in large_servers: | ||||
|                 self._ready_state.chunks.extend(self.chunks_needed(server)) | ||||
|  | ||||
|     def _delay_ready(self): | ||||
|         launch = self._ready_state.launch | ||||
|         while not launch.is_set(): | ||||
|             # this snippet of code is basically waiting 2 seconds | ||||
| @@ -152,9 +145,18 @@ class ConnectionState: | ||||
|             yield from asyncio.sleep(2) | ||||
|  | ||||
|         # get all the chunks | ||||
|         chunks = [f for f in self._ready_state.chunks if not f.done()] | ||||
|         servers = self._ready_state.servers | ||||
|         chunks = [] | ||||
|         for server in servers: | ||||
|             chunks.extend(self.chunks_needed(server)) | ||||
|  | ||||
|         # we only want to request ~75 guilds per chunk request. | ||||
|         splits = [servers[i:i + 75] for i in range(0, len(servers), 75)] | ||||
|         for split in splits: | ||||
|             yield from self.chunker(split) | ||||
|  | ||||
|         # wait for the chunks | ||||
|         if chunks: | ||||
|             yield from self.chunker(self._ready_state.servers) | ||||
|             yield from asyncio.wait(chunks) | ||||
|  | ||||
|         # remove the state | ||||
| @@ -164,21 +166,21 @@ class ConnectionState: | ||||
|         self.dispatch('ready') | ||||
|  | ||||
|     def parse_ready(self, data): | ||||
|         self._ready_state = ReadyState(launch=asyncio.Event(), chunks=[], servers=[]) | ||||
|         self._ready_state = ReadyState(launch=asyncio.Event(), servers=[]) | ||||
|         self.user = User(**data['user']) | ||||
|         guilds = data.get('guilds') | ||||
|  | ||||
|         large_servers = [] | ||||
|         servers = self._ready_state.servers | ||||
|         for guild in guilds: | ||||
|             server = self._add_server_from_data(guild) | ||||
|             if server.large: | ||||
|                 large_servers.append(server) | ||||
|                 servers.append(server) | ||||
|  | ||||
|         for pm in data.get('private_channels'): | ||||
|             self._add_private_channel(PrivateChannel(id=pm['id'], | ||||
|                                      user=User(**pm['recipient']))) | ||||
|  | ||||
|         utils.create_task(self._delay_ready(large_servers), loop=self.loop) | ||||
|         utils.create_task(self._delay_ready(), loop=self.loop) | ||||
|  | ||||
|     def parse_message_create(self, data): | ||||
|         channel = self.get_channel(data.get('channel_id')) | ||||
| @@ -215,7 +217,13 @@ class ConnectionState: | ||||
|         member_id = user['id'] | ||||
|         member = server.get_member(member_id) | ||||
|         if member is None: | ||||
|             return | ||||
|             if 'name' not in user: | ||||
|                 # sometimes we receive 'incomplete' member data post-removal. | ||||
|                 # skip these useless cases. | ||||
|                 return | ||||
|  | ||||
|             member = self._make_member(server, data) | ||||
|             server._add_member(member) | ||||
|  | ||||
|         old_member = copy.copy(member) | ||||
|         member.status = data.get('status') | ||||
| @@ -338,8 +346,6 @@ class ConnectionState: | ||||
|  | ||||
|         # check if it requires chunking | ||||
|         if server.large: | ||||
|             chunks = list(self.chunks_needed(server)) | ||||
|  | ||||
|             if unavailable == False: | ||||
|                 # check if we're waiting for 'useful' READY | ||||
|                 # and if we are, we don't want to dispatch any | ||||
| @@ -349,9 +355,7 @@ class ConnectionState: | ||||
|                 try: | ||||
|                     state = self._ready_state | ||||
|                     state.launch.clear() | ||||
|                     if chunks: | ||||
|                         state.servers.append(server) | ||||
|                         state.chunks.extend(chunks) | ||||
|                     state.servers.append(server) | ||||
|                 except AttributeError: | ||||
|                     # the _ready_state attribute is only there during | ||||
|                     # processing of useful READY. | ||||
| @@ -362,6 +366,7 @@ class ConnectionState: | ||||
|             # since we're not waiting for 'useful' READY we'll just | ||||
|             # do the chunk request here | ||||
|             yield from self.chunker(server) | ||||
|             chunks = list(self.chunks_needed(server)) | ||||
|             if chunks: | ||||
|                 yield from asyncio.wait(chunks) | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user