Browse Source

WHOX support to fetch account info on joining channels

master
JustAnotherArchivist 3 years ago
parent
commit
6c589d67ff
1 changed files with 34 additions and 0 deletions
  1. +34
    -0
      irclog.py

+ 34
- 0
irclog.py View File

@@ -205,6 +205,9 @@ class IRCClientProtocol(asyncio.Protocol):
self.server = ircstates.Server(self.config['irc']['host'])
self.capReqsPending = set() # Capabilities requested from the server but not yet ACKd or NAKd
self.caps = set() # Capabilities acknowledged by the server
self.whoxQueue = collections.deque() # Names of channels that were joined successfully but for which no WHO (WHOX) query was sent yet
self.whoxChannel = None # Name of channel for which a WHO query is currently running
self.whoxReply = [] # List of (nickname, account) tuples from the currently running WHO query

@staticmethod
def nick_command(nick: str):
@@ -320,10 +323,12 @@ class IRCClientProtocol(asyncio.Protocol):
self.logger.debug(f'Message received at {time_}: {message!r}')

# Queue message for storage
# Note: WHOX is queued further down
self.messageQueue.put_nowait((time_, b'< ' + message, None, None))
for command, channel, logMessage in self.render_message(line):
self.messageQueue.put_nowait((time_, logMessage, command, channel))

maybeTriggerWhox = False
# PING/PONG
if line.command == 'PING':
self.send(irctokens.build('PONG', line.params).format().encode('utf-8'))
@@ -396,11 +401,33 @@ class IRCClientProtocol(asyncio.Protocol):
self.channels.remove(channel)
break

# WHOX on successful JOIN if supported to fetch account information
elif line.command == 'JOIN' and self.server.isupport.whox and line.source and self.server.casefold(line.hostmask.nickname) == self.server.casefold(self.server.nickname):
self.whoxQueue.extend(line.params[0].split(','))
maybeTriggerWhox = True

# WHOX response
elif line.command == ircstates.numerics.RPL_WHOSPCRPL and line.params[1] == '042':
self.whoxReply.append((line.params[2], line.params[3] if line.params[3] != '0' else None))

# End of WHOX response
elif line.command == ircstates.numerics.RPL_ENDOFWHO:
self.messageQueue.put_nowait((time_, self.render_whox(), 'WHOX', self.whoxChannel))
self.whoxChannel = None
self.whoxReply = []
maybeTriggerWhox = True

# General fatal ERROR
elif line.command == 'ERROR':
self.logger.error(f'Server sent ERROR: {message!r}')
self.transport.close()

# Send next WHOX if appropriate
if maybeTriggerWhox and self.whoxChannel is None and self.whoxQueue:
self.whoxChannel = self.whoxQueue.popleft()
self.whoxReply = []
self.send(b'WHO ' + self.whoxChannel.encode('utf-8') + b' c%nat,042')

def get_mode_char(self, channelUser):
if channelUser is None:
return ''
@@ -471,6 +498,13 @@ class IRCClientProtocol(asyncio.Protocol):
users = self.server.channels[self.server.casefold(channel)].users
yield 'NAMES', channel, f'Currently in {channel}: {", ".join(self.render_nick_with_mode(u, u.nickname) for u in users.values())}'

def render_whox(self):
users = []
for nickname, account in self.whoxReply:
accountStr = f' ({account})' if account is not None else ''
users.append(f'{self.render_nick_with_mode(self.server.channels[self.server.casefold(self.whoxChannel)].users.get(self.server.casefold(nickname)), nickname)}{accountStr}')
return f'Currently in {self.whoxChannel}: {", ".join(users)}'

async def quit(self):
# 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')


Loading…
Cancel
Save