home · contact · privacy
Also implement full MsgTokGuides for 396, 401, 432, 433, 900.
authorChristian Heller <c.heller@plomlompom.de>
Wed, 20 Aug 2025 20:05:21 +0000 (22:05 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Wed, 20 Aug 2025 20:05:21 +0000 (22:05 +0200)
ircplom/client.py

index dd448f13fc409515b0467d54fe126b5668d13847..cd10e6a1aedb88be7ca65ddae25bda1c235ea09c 100644 (file)
@@ -84,12 +84,40 @@ _EXPECTATIONS: tuple[_MsgParseExpectation, ...] = (
                         (_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,
@@ -719,29 +747,32 @@ class Client(ABC, ClientQueueMixin):
         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']
@@ -791,7 +822,7 @@ class Client(ABC, ClientQueueMixin):
 
         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'}
@@ -802,12 +833,12 @@ class Client(ABC, ClientQueueMixin):
             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)