(_MsgTok.NICKNAME,
_MsgTok.ANY)),
- _MsgParseExpectation(_MsgTok.SERVER, '396', tuple(), 3),
- _MsgParseExpectation(_MsgTok.SERVER, '401', tuple(), 3),
- _MsgParseExpectation(_MsgTok.SERVER, '432', tuple(), 3),
- _MsgParseExpectation(_MsgTok.SERVER, '433', tuple(), 3),
- _MsgParseExpectation(_MsgTok.SERVER, '900', tuple(), 4),
+ _MsgParseExpectation(_MsgTok.SERVER, '396',
+ (_MsgTok.NICKNAME,
+ (_MsgTok.ANY, 'host_maybe_w_user'),
+ _MsgTok.ANY)),
+
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '401',
+ (_MsgTok.NICKNAME,
+ (_MsgTok.NICKNAME, 'target'),
+ _MsgTok.ANY)),
+
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '432',
+ ('*',
+ _MsgTok.NICKNAME,
+ _MsgTok.ANY)),
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '432',
+ ((_MsgTok.NICKNAME, 'fallback'),
+ _MsgTok.NICKNAME,
+ _MsgTok.ANY)),
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '433',
+ (_MsgTok.NICKNAME,
+ _MsgTok.NICKNAME,
+ _MsgTok.ANY)),
+
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '900',
+ (_MsgTok.NICKNAME,
+ (_MsgTok.USER_ADDRESS, 'full_address'),
+ (_MsgTok.ANY, 'account'),
+ _MsgTok.ANY)),
_MsgParseExpectation(_MsgTok.SERVER,
'903',
(_MsgTok.NICKNAME,
elif self._match_msg(msg, '376'): # RPL_ENDOFMOTD
self._db.declare_complete('motd')
- elif self._match_msg(msg, '396'): # RPL_VISIBLEHOST
+ elif (ret := self._match_msg(msg, '396')): # RPL_VISIBLEHOST
# '@'-split because <https://defs.ircdocs.horse/defs/numerics>
# claims: "<hostname> can also be in the form <user@hostname>"
- self._db.client_host = msg.params[1].split('@')[-1]
- elif self._match_msg(msg, '401'): # ERR_NOSUCHNICK
- self._log(f'{msg.params[1]} not online', scope=LogScope.CHAT,
- target=msg.params[1], alert=True)
- elif self._match_msg(msg, '432'): # ERR_ERRONEOUSNICKNAME
+ self._db.client_host = ret['host_maybe_w_user'].split('@')[-1]
+
+ elif (ret := self._match_msg(msg, '401')): # ERR_NOSUCHNICK
+ self._log(f'{ret["target"]} not online', scope=LogScope.CHAT,
+ target=ret['target'], alert=True)
+
+ elif (ret := self._match_msg(msg, '432')): # ERR_ERRONEOUSNICKNAME
alert = 'nickname refused for bad format'
- if msg.params[0] == '*':
+ if 'fallback' in ret:
+ self.set_nick(ret['fallback'], confirmed=True)
+ else:
alert += ', giving up'
self.close()
- else:
- self.set_nick(msg.params[0], confirmed=True)
self._log(alert, alert=True)
+
elif self._match_msg(msg, '433'): # ERR_NICKNAMEINUSE
self._log('nickname already in use, trying increment', alert=True)
self.set_nick(self._db.nick_incremented)
- elif self._match_msg(msg, '900'): # RPL_LOGGEDIN
- self._db.nickname, remainder = msg.params[1].split('!', maxsplit=1)
- self._db.username, self._db.client_host = remainder.split('@')
- self._db.sasl_account = msg.params[2]
+ elif (ret := self._match_msg(msg, '900')): # RPL_LOGGEDIN
+ self.set_nick(ret['full_address'][0], True)
+ self._db.username, self._db.client_host = ret['full_address'][1:]
+ self._db.sasl_account = ret['account']
elif ((ret := self._match_msg(msg, '903')) # RPL_SASLSUCCESS
or (ret := self._match_msg(msg, '904'))): # ERR_SASLFAIL
self._db.sasl_auth_state = ret['result']
elif (ret := self._match_msg(msg, 'NOTICE'))\
or (ret := self._match_msg(msg, 'PRIVMSG')):
- if 'nickname' in ret and ret['nickname'] != self._db.nickname:
+ if 'nickname' in ret:
self.set_nick(ret['nickname'], confirmed=True)
kw: dict[str, bool | str | LogScope] = {
'as_notice': msg.verb == 'NOTICE'}
self._log(ret['message'], out=False, **kw)
elif (ret := self._match_msg(msg, 'PART')):
- reason = f': ret["reason"]' if 'reason' in ret else ''
+ reason = f': {ret["reason"]}' if 'reason' in ret else ''
self._log(f'{ret["parter"][0]} {msg.verb.lower()}s '
+ f'{ret["channel"]["id"]}{reason}',
scope=LogScope.CHAT, target=ret['channel']['id'])
if ret['parter'][0] == self._db.nickname:
- self._db.del_chan(ret['ch_name'])
+ self._db.del_chan(ret['channel']['id'])
else:
ret['channel']['db'].remove_completable('users',
ret['parter'][0], True)