Browse Source

Raise the original error instead of a proxy in member list errors

pull/10109/head
dolfies 3 years ago
parent
commit
73f337d709
  1. 8
      discord/guild.py
  2. 42
      discord/state.py

8
discord/guild.py

@ -3576,6 +3576,8 @@ class Guild(Hashable):
ClientException ClientException
This guild cannot be chunked or chunking failed. This guild cannot be chunked or chunking failed.
Guild is no longer available. Guild is no longer available.
InvalidData
Did not receive a response from the gateway.
Returns Returns
-------- --------
@ -3588,8 +3590,6 @@ class Guild(Hashable):
raise ClientException('This guild is no longer available') raise ClientException('This guild is no longer available')
members = await self._state.chunk_guild(self, channels=[channel] if channel else []) members = await self._state.chunk_guild(self, channels=[channel] if channel else [])
if members is None:
raise ClientException('Chunking failed')
return members return members
async def fetch_members( async def fetch_members(
@ -3633,6 +3633,8 @@ class Guild(Hashable):
ClientException ClientException
Fetching members failed. Fetching members failed.
Guild is no longer available. Guild is no longer available.
InvalidData
Did not receive a response from the gateway.
Returns Returns
-------- --------
@ -3645,8 +3647,6 @@ class Guild(Hashable):
members = await self._state.scrape_guild( members = await self._state.scrape_guild(
self, cache=cache, force_scraping=force_scraping, delay=delay, channels=channels self, cache=cache, force_scraping=force_scraping, delay=delay, channels=channels
) )
if members is None:
raise ClientException('Fetching members failed')
return members return members
async def query_members( async def query_members(

42
discord/state.py

@ -48,7 +48,7 @@ import weakref
import inspect import inspect
from math import ceil from math import ceil
from .errors import NotFound from .errors import ClientException, InvalidData, NotFound
from .guild import CommandCounts, Guild from .guild import CommandCounts, Guild
from .activity import BaseActivity from .activity import BaseActivity
from .user import User, ClientUser from .user import User, ClientUser
@ -175,7 +175,8 @@ class MemberSidebar:
self.channels = [str(channel.id) for channel in (channels or self.get_channels(1 if chunk else 5))] self.channels = [str(channel.id) for channel in (channels or self.get_channels(1 if chunk else 5))]
self.ranges = self.get_ranges() self.ranges = self.get_ranges()
self.subscribing: bool = False self.subscribing: bool = False
self.buffer: Optional[List[Member]] = [] self.buffer: List[Member] = []
self.exception: Optional[Exception] = None
self.waiters: List[asyncio.Future[Optional[List[Member]]]] = [] self.waiters: List[asyncio.Future[Optional[List[Member]]]] = []
def __bool__(self) -> bool: def __bool__(self) -> bool:
@ -281,7 +282,7 @@ class MemberSidebar:
for member in members: for member in members:
guild._add_member(member) guild._add_member(member)
async def wait(self) -> Optional[List[Member]]: async def wait(self) -> List[Member]:
future = self.loop.create_future() future = self.loop.create_future()
self.waiters.append(future) self.waiters.append(future)
try: try:
@ -289,7 +290,7 @@ class MemberSidebar:
finally: finally:
self.waiters.remove(future) self.waiters.remove(future)
def get_future(self) -> asyncio.Future[Optional[List[Member]]]: def get_future(self) -> asyncio.Future[List[Member]]:
future = self.loop.create_future() future = self.loop.create_future()
self.waiters.append(future) self.waiters.append(future)
return future return future
@ -297,6 +298,9 @@ class MemberSidebar:
def done(self) -> None: def done(self) -> None:
for future in self.waiters: for future in self.waiters:
if not future.done(): if not future.done():
if self.exception:
future.set_exception(self.exception)
else:
future.set_result(self.buffer) future.set_result(self.buffer)
try: try:
@ -310,11 +314,11 @@ class MemberSidebar:
async def wrapper(self): async def wrapper(self):
try: try:
await self.scrape() await self.scrape()
except RuntimeError as exc:
_log.warning('Member list scraping failed for %s (%s).', self.guild.id, exc)
self.buffer = None
except asyncio.CancelledError: except asyncio.CancelledError:
pass pass
except Exception as exc:
_log.warning('Member list scraping failed for %s (%s).', self.guild.id, exc)
self.exception = exc
finally: finally:
self.done() self.done()
@ -337,7 +341,7 @@ class MemberSidebar:
break break
if not requests: if not requests:
raise RuntimeError('failed to choose channels or ranges') raise ClientException('Failed to automatically choose channels; please specify them manually')
def predicate(data): def predicate(data):
return int(data['guild_id']) == guild.id and any(op['op'] == 'SYNC' for op in data['ops']) return int(data['guild_id']) == guild.id and any(op['op'] == 'SYNC' for op in data['ops'])
@ -352,7 +356,7 @@ class MemberSidebar:
self.subscribing = False self.subscribing = False
break break
else: else:
raise RuntimeError('timeout: no response from gateway') raise InvalidData('Did not receive a response from Discord')
await asyncio.sleep(delay) await asyncio.sleep(delay)
@ -790,6 +794,8 @@ class ConnectionState:
await asyncio.wait_for(future, timeout=10) await asyncio.wait_for(future, timeout=10)
except asyncio.TimeoutError: except asyncio.TimeoutError:
_log.warning('Timed out waiting for chunks for guild_id %s.', guild.id) _log.warning('Timed out waiting for chunks for guild_id %s.', guild.id)
except (ClientException, InvalidData):
pass
except asyncio.CancelledError: except asyncio.CancelledError:
pass pass
else: else:
@ -891,7 +897,7 @@ class ConnectionState:
self.session_type = data.get('session_type', 'normal') self.session_type = data.get('session_type', 'normal')
self.connections = {c['id']: Connection(state=self, data=c) for c in data.get('connected_accounts', [])} self.connections = {c['id']: Connection(state=self, data=c) for c in data.get('connected_accounts', [])}
if 'required_action' in data: # Locked more than likely if 'required_action' in data:
self.parse_user_required_action_update(data) self.parse_user_required_action_update(data)
if 'sessions' in data: if 'sessions' in data:
@ -1720,7 +1726,7 @@ class ConnectionState:
force_scraping: bool = ..., force_scraping: bool = ...,
channels: List[abcSnowflake] = ..., channels: List[abcSnowflake] = ...,
delay: Union[int, float] = ..., delay: Union[int, float] = ...,
) -> Optional[List[Member]]: ) -> List[Member]:
... ...
@overload @overload
@ -1733,7 +1739,7 @@ class ConnectionState:
force_scraping: bool = ..., force_scraping: bool = ...,
channels: List[abcSnowflake] = ..., channels: List[abcSnowflake] = ...,
delay: Union[int, float] = ..., delay: Union[int, float] = ...,
) -> asyncio.Future[Optional[List[Member]]]: ) -> asyncio.Future[List[Member]]:
... ...
async def scrape_guild( async def scrape_guild(
@ -1745,7 +1751,7 @@ class ConnectionState:
force_scraping: bool = False, force_scraping: bool = False,
channels: List[abcSnowflake] = MISSING, channels: List[abcSnowflake] = MISSING,
delay: Union[int, float] = MISSING, delay: Union[int, float] = MISSING,
) -> Union[Optional[List[Member]], asyncio.Future[Optional[List[Member]]]]: ) -> Union[List[Member], asyncio.Future[List[Member]]]:
if not guild.me: if not guild.me:
await guild.query_members(user_ids=[self.self_id], cache=True) # type: ignore # self_id is always present here await guild.query_members(user_ids=[self.self_id], cache=True) # type: ignore # self_id is always present here
@ -1773,18 +1779,18 @@ class ConnectionState:
if wait: if wait:
return await request.wait() return await request.wait()
return request.get_future() # type: ignore # Honestly, I'm confused too return request.get_future()
@overload @overload
async def chunk_guild( async def chunk_guild(
self, guild: Guild, *, wait: Literal[True] = ..., channels: List[abcSnowflake] = ... self, guild: Guild, *, wait: Literal[True] = ..., channels: List[abcSnowflake] = ...
) -> Optional[List[Member]]: ) -> List[Member]:
... ...
@overload @overload
async def chunk_guild( async def chunk_guild(
self, guild: Guild, *, wait: Literal[False] = ..., channels: List[abcSnowflake] = ... self, guild: Guild, *, wait: Literal[False] = ..., channels: List[abcSnowflake] = ...
) -> asyncio.Future[Optional[List[Member]]]: ) -> asyncio.Future[List[Member]]:
... ...
async def chunk_guild( async def chunk_guild(
@ -1793,7 +1799,7 @@ class ConnectionState:
*, *,
wait: bool = True, wait: bool = True,
channels: List[abcSnowflake] = MISSING, channels: List[abcSnowflake] = MISSING,
) -> Union[asyncio.Future[Optional[List[Member]]], Optional[List[Member]]]: ) -> Union[asyncio.Future[List[Member]], List[Member]]:
if not guild.me: if not guild.me:
await guild.query_members(user_ids=[self.self_id], cache=True) # type: ignore # self_id is always present here await guild.query_members(user_ids=[self.self_id], cache=True) # type: ignore # self_id is always present here
@ -1816,6 +1822,8 @@ class ConnectionState:
await asyncio.wait_for(self.chunk_guild(guild), timeout=10) await asyncio.wait_for(self.chunk_guild(guild), timeout=10)
except asyncio.TimeoutError: except asyncio.TimeoutError:
_log.info('Somehow timed out waiting for chunks for guild %s.', guild.id) _log.info('Somehow timed out waiting for chunks for guild %s.', guild.id)
except (ClientException, InvalidData):
pass
self._queued_guilds.pop(guild.id) self._queued_guilds.pop(guild.id)

Loading…
Cancel
Save