|
|
@@ -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) |
|
|
|