Skip to content

Commit fcb498d

Browse files
authored
refactor(bot, gateway, http): Remove any unclosed client session messages (#1014)
1 parent a946acd commit fcb498d

File tree

3 files changed

+32
-12
lines changed

3 files changed

+32
-12
lines changed

interactions/api/gateway/client.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,13 +132,15 @@ def __init__(
132132
except RuntimeError:
133133
self._loop = new_event_loop()
134134
self._dispatch: Listener = Listener()
135+
135136
self._ratelimiter = (
136137
WSRateLimit(loop=self._loop) if version_info < (3, 10) else WSRateLimit()
137138
)
138139
self.__heartbeater: _Heartbeat = _Heartbeat(
139140
loop=self._loop if version_info < (3, 10) else None
140141
)
141-
self._http: HTTPClient = HTTPClient(token)
142+
self._http: HTTPClient = token
143+
142144
self._client: Optional["ClientWebSocketResponse"] = None
143145

144146
self.__closed: Event = Event(loop=self._loop) if version_info < (3, 10) else Event()
@@ -224,7 +226,8 @@ async def run(self) -> None:
224226
Handles the client's connection with the Gateway.
225227
"""
226228

227-
# Credit to NAFF for inspiration for the Gateway logic.
229+
if isinstance(self._http, str):
230+
self._http = HTTPClient(self._http)
228231

229232
url = await self._http.get_gateway()
230233
self.ws_url = url
@@ -892,3 +895,11 @@ async def _update_presence(self, presence: ClientPresence) -> None:
892895
await self._send_packet(payload)
893896
log.debug(f"UPDATE_PRESENCE: {presence._json}")
894897
self.__presence = presence
898+
899+
async def close(self) -> None:
900+
"""
901+
Closes the current connection.
902+
"""
903+
if self._client:
904+
await self._client.close()
905+
self._closed = True

interactions/api/http/request.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
__all__ = ("_Request",)
2020
log: Logger = get_logger("http")
21-
_session: ClientSession = ClientSession()
2221

2322

2423
class _Request:
@@ -48,7 +47,6 @@ class _Request:
4847
ratelimits: Dict[str, Limiter] # bucket: Limiter
4948
buckets: Dict[str, str] # endpoint: shared_bucket
5049
_headers: dict
51-
_session: ClientSession
5250
_global_lock: Limiter
5351

5452
def __init__(self, token: str) -> None:
@@ -69,7 +67,7 @@ def __init__(self, token: str) -> None:
6967
f"Python/{version_info[0]}.{version_info[1]} "
7068
f"aiohttp/{http_version}",
7169
}
72-
self._session = _session
70+
self._session = ClientSession()
7371
self._global_lock = (
7472
Limiter(lock=Lock(loop=self._loop)) if version_info < (3, 10) else Limiter(lock=Lock())
7573
)

interactions/client/bot.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class Client:
6767
:ivar Optional[ClientPresence] _presence: The RPC-like presence shown on an application once connected.
6868
:ivar str _token: The token of the application used for authentication when connecting.
6969
:ivar Optional[Dict[str, ModuleType]] _extensions: The "extensions" or cog equivalence registered to the main client.
70-
:ivar Application me: The application representation of the client.
70+
:ivar Application me?: The application representation of the client.
7171
"""
7272

7373
def __init__(
@@ -76,7 +76,7 @@ def __init__(
7676
**kwargs,
7777
) -> None:
7878
self._loop: AbstractEventLoop = get_event_loop()
79-
self._http: HTTPClient = HTTPClient(token=token)
79+
self._http: HTTPClient = token
8080
self._intents: Intents = kwargs.get("intents", Intents.DEFAULT)
8181
self._websocket: WSClient = WSClient(token=token, intents=self._intents)
8282
self._shards: List[Tuple[int]] = kwargs.get("shards", [])
@@ -89,9 +89,9 @@ def __init__(
8989
self.__command_coroutines = []
9090
self.__global_commands = {}
9191
self.__guild_commands = {}
92-
self.__id_autocomplete = {}
93-
self.me = None
9492

93+
self.me: Optional[Application] = None
94+
self.__id_autocomplete = {}
9595
if self._default_scope:
9696
if not isinstance(self._default_scope, list):
9797
self._default_scope = [self._default_scope]
@@ -110,9 +110,6 @@ def __init__(
110110
else:
111111
self._automate_sync = True
112112

113-
data = self._loop.run_until_complete(self._http.get_current_bot_information())
114-
self.me = Application(**data, _client=self._http)
115-
116113
@property
117114
def guilds(self) -> List[Guild]:
118115
"""Returns a list of guilds the bot is in."""
@@ -127,12 +124,22 @@ def latency(self) -> float:
127124

128125
def start(self) -> None:
129126
"""Starts the client session."""
127+
128+
if isinstance(self._http, str):
129+
self._http = HTTPClient(self._http)
130+
131+
data = self._loop.run_until_complete(self._http.get_current_bot_information())
132+
self.me = Application(**data, _client=self._http)
133+
130134
try:
131135
self._loop.run_until_complete(self._ready())
132136
except (CancelledError, Exception) as e:
137+
self._loop.run_until_complete(self._logout())
133138
raise e from e
134139
except KeyboardInterrupt:
135140
log.error("KeyboardInterrupt detected, shutting down the bot.")
141+
finally:
142+
self._loop.run_until_complete(self._logout())
136143

137144
async def __register_id_autocomplete(self) -> None: # TODO: make this use ID and not name
138145
for key in self.__id_autocomplete.keys():
@@ -1475,6 +1482,10 @@ async def modify(
14751482

14761483
return User(**data)
14771484

1485+
async def _logout(self) -> None:
1486+
await self._websocket.close()
1487+
await self._http._req.close()
1488+
14781489

14791490
# TODO: Implement the rest of cog behaviour when possible.
14801491
class Extension:

0 commit comments

Comments
 (0)