home · contact · privacy
Move CAPS handling into new system.
authorChristian Heller <c.heller@plomlompom.de>
Wed, 20 Aug 2025 22:06:46 +0000 (00:06 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Wed, 20 Aug 2025 22:06:46 +0000 (00:06 +0200)
ircplom/client.py

index 7d180f8e50863166832557685f623c0a83e21429..2d5bd3d8c3abb26a2b2b92d442e9080e3a7ea87d 100644 (file)
@@ -49,20 +49,18 @@ class _MsgTok(Enum):
     USER_ADDRESS = auto()
 
 
-_MsgTokGuide = str | _MsgTok | tuple[_MsgTok, str]
+_MsgTokGuide = str | _MsgTok | tuple[str | _MsgTok, str]
 
 
 class _MsgParseExpectation(NamedTuple):
     source: _MsgTokGuide
     verb: str
     params: tuple[_MsgTokGuide, ...] = tuple()
-    len_min_params: int = 0
-    len_max_params: int = 0
     idx_into_list: int = -1
 
 
 _EXPECTATIONS: tuple[_MsgParseExpectation, ...] = (
-    # _MsgParseExpectation(_MsgTok.SERVER, '005', tuple(), 3, 15),
+
     _MsgParseExpectation(_MsgTok.SERVER,
                          '005',
                          (_MsgTok.NICKNAME,
@@ -138,7 +136,48 @@ _EXPECTATIONS: tuple[_MsgParseExpectation, ...] = (
                          'AUTHENTICATE',
                          ('+',)),
 
-    _MsgParseExpectation(_MsgTok.SERVER, 'CAP', tuple(), 3, 15),
+    _MsgParseExpectation(_MsgTok.SERVER,
+                         'CAP',
+                         (_MsgTok.NICKNAME,
+                          ('NEW', 'verb'),
+                          (_MsgTok.LIST, 'items'))),
+    _MsgParseExpectation(_MsgTok.SERVER,
+                         'CAP',
+                         (_MsgTok.NICKNAME,
+                          ('DEL', 'verb'),
+                          (_MsgTok.LIST, 'items'))),
+    _MsgParseExpectation(_MsgTok.SERVER,
+                         'CAP',
+                         (_MsgTok.NICKNAME,
+                          ('ACK', 'verb'),
+                          (_MsgTok.LIST, 'items'))),
+    _MsgParseExpectation(_MsgTok.SERVER,
+                         'CAP',
+                         (_MsgTok.NICKNAME,
+                          ('NAK', 'verb'),
+                          (_MsgTok.LIST, 'items'))),
+    _MsgParseExpectation(_MsgTok.SERVER,
+                         'CAP',
+                         ('*',
+                          ('LS', 'verb'),
+                          ('*', 'tbc'),
+                          (_MsgTok.LIST, 'items'))),
+    _MsgParseExpectation(_MsgTok.SERVER,
+                         'CAP',
+                         (_MsgTok.NICKNAME,
+                          ('LS', 'verb'),
+                          (_MsgTok.LIST, 'items'))),
+    _MsgParseExpectation(_MsgTok.SERVER,
+                         'CAP',
+                         (_MsgTok.NICKNAME,
+                          ('*', 'tbc'),
+                          ('LIST', 'verb'),
+                          (_MsgTok.LIST, 'items'))),
+    _MsgParseExpectation(_MsgTok.SERVER,
+                         'CAP',
+                         (_MsgTok.NICKNAME,
+                          ('LIST', 'verb'),
+                          (_MsgTok.LIST, 'items'))),
 
     _MsgParseExpectation(_MsgTok.NONE,
                          'ERROR',
@@ -342,10 +381,9 @@ class _CapsManager:
         self.clear()
         self._send('LS', '302')
 
-    def process_msg(self, params: tuple[str, ...]) -> bool:
-        'Parse CAP params to negot. steps, DB inputs; return if successful.'
-        verb = params[0]
-        items = params[-1].strip().split()
+    def process_msg(self, verb: str, items: tuple[str, ...], incomplete: bool
+                    ) -> bool:
+        'Parse CAP message to negot. steps, DB inputs; return if successful.'
         for item in items:
             if verb == 'NEW':
                 self._ls.append(item, stay_complete=True)
@@ -363,7 +401,7 @@ class _CapsManager:
             target = getattr(self, f'_{verb.lower()}')
             for item in items:
                 target.append(item)
-            if params[1] != '*':
+            if not incomplete:
                 target.is_complete = True
                 if target == self._list:
                     acks = self._list_expectations['ACK']
@@ -706,14 +744,6 @@ class Client(ABC, ClientQueueMixin):
             return msg_tok
 
         for ex in [ex for ex in _EXPECTATIONS if verb == ex.verb == msg.verb]:
-            if not ex.params:
-                len_p = len(msg.params)
-                if len_p < ex.len_min_params:
-                    continue
-                if ex.len_max_params and len_p > ex.len_max_params:
-                    continue
-                if (not ex.len_max_params) and len_p != ex.len_min_params:
-                    continue
             to_return: dict[str, Any] = {'': ''}  # non-emtpy so boolish True
             ex_tok_fields = tuple([ex.source] + list(ex.params))
             msg_params: list[str | list[str]]
@@ -807,8 +837,8 @@ class Client(ABC, ClientQueueMixin):
                               ).encode('utf-8')).decode('utf-8')
             self.send(IrcMessage('AUTHENTICATE', (auth,)))
 
-        elif self._match_msg(msg, 'CAP'):
-            if (self._caps.process_msg(msg.params[1:])
+        elif (ret := self._match_msg(msg, 'CAP')):
+            if (self._caps.process_msg(ret['verb'], ret['items'], 'tbc' in ret)
                     and self._db.caps.has('sasl')
                     and 'PLAIN' in self._db.caps['sasl'].data.split(',')):
                 if self._db.password: