diff --git a/irclog.py b/irclog.py index 69cb056..8234c98 100644 --- a/irclog.py +++ b/irclog.py @@ -314,13 +314,18 @@ class IRCClientProtocol(asyncio.Protocol): # Queue message for storage sendGeneral = True if line.command in ('QUIT', 'NICK') and line.source: - try: - user = self.server.users[line.hostmask.nickname] - except KeyError: - pass - else: + if line.hostmask.nickname == self.server.nickname: + # Self-quit sendGeneral = False - self.messageQueue.put_nowait((time_, b'< ' + message, user.channels)) + self.messageQueue.put_nowait((time_, b'< ' + message, list(self.channels) + ['general'])) + else: + try: + user = self.server.users[line.hostmask.nickname] + except KeyError: + pass + else: + sendGeneral = False + self.messageQueue.put_nowait((time_, b'< ' + message, user.channels)) if sendGeneral: self.messageQueue.put_nowait((time_, b'< ' + message, None)) @@ -376,13 +381,17 @@ class IRCClientProtocol(asyncio.Protocol): return self._send_join_part(b'JOIN', self.channels) + # General fatal ERROR + elif line.command == 'ERROR': + self.logger.error(f'Server sent ERROR: {message!r}') + self.transport.close() + async def quit(self): - # It appears to be hard to impossible to send a clean quit, wait for it to be actually sent, and only then close the transport. - # This is because asyncio.sslproto.SSLTransport doesn't support explicit draining nor waiting for an empty write queue nor write_eof. - # So instead, just close the transport and wait until connection_lost is triggered (which also puts a message in the logs). + # The server acknowledges a QUIT by sending an ERROR and closing the connection. The latter triggers connection_lost, so just wait for the closure event. self.logger.info('Quitting') - self.transport.close() + self.send(b'QUIT :Bye') await self.connectionClosedEvent.wait() + self.transport.close() def connection_lost(self, exc): time_ = time.time() @@ -673,7 +682,7 @@ async def main(): messageQueue = asyncio.Queue() # tuple(time: float, message: bytes or None, channels: list[str] or None) # message = None indicates a connection loss - # channels = None indicates that IRCClientProtocol did not identify which channels are affected; it is only not None for QUIT or NICK messages. + # channels = None indicates that IRCClientProtocol did not identify which channels are affected; it is a set or list of channel names for QUIT or NICK messages and the connection closed message. irc = IRCClient(messageQueue, config) webserver = WebServer(config)