aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar MarkKoz <[email protected]>2020-02-13 10:18:09 -0800
committerGravatar MarkKoz <[email protected]>2020-02-13 10:18:09 -0800
commitb19e6aaabdbcfefc5d22d1f72e670421fe8a8d97 (patch)
treecbf9dcff81b95ec04c094a5662b214374fb2cb26
parentAPI: accept additional session kwargs for recreate() (diff)
Bot: avoid DeprecationWarning for aiohttp.AsyncResolver (fix #748)
AsyncResolver has to be created inside a coroutine so it's moved inside start(). Consequently, the APIClient session is also recreated inside start() now. When using clear(), the default connector is used for the session it recreates because clear() is not a coroutine. This should only affect requests made to the Discord API via the Client when not using it to run a bot; starting the bot will re-create the session with the custom connector. * Close connector and resolver when bot closes
-rw-r--r--bot/bot.py45
1 files changed, 30 insertions, 15 deletions
diff --git a/bot/bot.py b/bot/bot.py
index 8f808272f..95fbae17f 100644
--- a/bot/bot.py
+++ b/bot/bot.py
@@ -14,18 +14,13 @@ class Bot(commands.Bot):
"""A subclass of `discord.ext.commands.Bot` with an aiohttp session and an API client."""
def __init__(self, *args, **kwargs):
- # Use asyncio for DNS resolution instead of threads so threads aren't spammed.
- # Use AF_INET as its socket family to prevent HTTPS related problems both locally
- # and in production.
- self.connector = aiohttp.TCPConnector(
- resolver=aiohttp.AsyncResolver(),
- family=socket.AF_INET,
- )
-
- super().__init__(*args, connector=self.connector, **kwargs)
+ super().__init__(*args, **kwargs)
self.http_session: Optional[aiohttp.ClientSession] = None
- self.api_client = api.APIClient(loop=self.loop, connector=self.connector)
+ self.api_client = api.APIClient(loop=self.loop)
+
+ self._connector = None
+ self._resolver = None
log.addHandler(api.APILoggingHandler(self.api_client))
@@ -35,19 +30,39 @@ class Bot(commands.Bot):
log.info(f"Cog loaded: {cog.qualified_name}")
def clear(self) -> None:
- """Clears the internal state of the bot and resets the API client."""
+ """Clears the internal state of the bot and sets the HTTPClient connector to None."""
+ self.http.connector = None # Use the default connector.
super().clear()
- self.api_client.recreate()
async def close(self) -> None:
- """Close the aiohttp session after closing the Discord connection."""
+ """Close the Discord connection and the aiohttp session, connector, and resolver."""
await super().close()
await self.http_session.close()
await self.api_client.close()
+ if self._connector:
+ await self._connector.close()
+
+ if self._resolver:
+ await self._resolver.close()
+
async def start(self, *args, **kwargs) -> None:
- """Open an aiohttp session before logging in and connecting to Discord."""
- self.http_session = aiohttp.ClientSession(connector=self.connector)
+ """Set up aiohttp sessions before logging in and connecting to Discord."""
+ # Use asyncio for DNS resolution instead of threads so threads aren't spammed.
+ # Use AF_INET as its socket family to prevent HTTPS related problems both locally
+ # and in production.
+ self._resolver = aiohttp.AsyncResolver()
+ self._connector = aiohttp.TCPConnector(
+ resolver=self._resolver,
+ family=socket.AF_INET,
+ )
+
+ # Client.login() will call HTTPClient.static_login() which will create a session using
+ # this connector attribute.
+ self.http.connector = self._connector
+
+ self.http_session = aiohttp.ClientSession(connector=self._connector)
+ self.api_client.recreate(connector=self._connector)
await super().start(*args, **kwargs)