home · contact · privacy
Improve CAPS LS/LIST handling. master
authorChristian Heller <c.heller@plomlompom.de>
Sun, 27 Jul 2025 02:26:36 +0000 (04:26 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Sun, 27 Jul 2025 02:26:36 +0000 (04:26 +0200)
ircplom/irc_conn.py

index 36be5f9c87bcbd584d7d28c700d0e5255268a34e..b24f5558f959d0bd30645bfcb2316135e64688f4 100644 (file)
@@ -203,8 +203,8 @@ class Client(ABC, ClientQueueMixin):
         self._hostname = hostname
         self._socket: Optional[socket] = None
         self._recv_loop: Optional[Loop] = None
         self._hostname = hostname
         self._socket: Optional[socket] = None
         self._recv_loop: Optional[Loop] = None
-        self._caps: dict[str, set[str]] = {
-                'available': set(), 'enabled': set(), 'finished': set()}
+        self._cap_ls_done = False
+        self._caps: dict[str, Optional[bool]] = {}
         self.id_ = uuid4()
         self.assumed_open = False
         self.realname = realname
         self.id_ = uuid4()
         self.assumed_open = False
         self.realname = realname
@@ -234,17 +234,27 @@ class Client(ABC, ClientQueueMixin):
 
         Thread(target=connect, daemon=True, args=(self,)).start()
 
 
         Thread(target=connect, daemon=True, args=(self,)).start()
 
-    def set_caps(self, caps: set[str], final_line: bool, enabled: bool
-                 ) -> None:
-        'Record available or enabled server capabilities.'
-        category = 'enabled' if enabled else 'available'
-        if category in self._caps['finished']:
-            self._caps[category].clear()
-            self._caps['finished'].remove(category)
-        self._caps[category] |= caps
-        if final_line:
-            self._caps['finished'].add(category)
-            self.log(f'# server caps {category}: {self._caps[category]}')
+    def collect_caps(self, params: tuple[str, ...]) -> None:
+        'Record and list available or enabled server capabilities.'
+        collect_enabled = params[0] != 'LS'
+        is_final_line = params[1] != '*'
+        listed_names = params[-1].strip().split()
+        if collect_enabled:
+            for k in [k for k, v in self._caps.items() if v is None]:
+                self._caps[k] = False
+            for name in [name for name in self._caps
+                         if name.split('=')[0] in listed_names]:
+                self._caps[name] = True
+        else:
+            if self._cap_ls_done:
+                self._caps.clear()
+            for cap_name in listed_names:
+                self._caps[cap_name] = None
+            self._cap_ls_done = is_final_line
+        if is_final_line and collect_enabled:
+            self.log('# server capabilities available (* if enabled): '
+                     + ', '.join([(f'(*){k}' if v else k)
+                                  for k, v in self._caps.items()]))
 
     @abstractmethod
     def log(self, msg: str, chat: str = '') -> None:
 
     @abstractmethod
     def log(self, msg: str, chat: str = '') -> None:
@@ -336,8 +346,5 @@ class _RecvEvent(ClientEvent, PayloadMixin):
         elif msg.verb == 'PRIVMSG':
             target.log(msg=str(msg.params), chat=msg.source)
         elif msg.verb == 'CAP':
         elif msg.verb == 'PRIVMSG':
             target.log(msg=str(msg.params), chat=msg.source)
         elif msg.verb == 'CAP':
-            subverb = msg.params[1]
-            if subverb in {'LS', 'LIST'}:
-                target.set_caps(final_line=msg.params[2] != '*',
-                                enabled=subverb == 'LIST',
-                                caps=set(msg.params[-1].strip().split()))
+            if msg.params[1] in {'LS', 'LIST'}:
+                target.collect_caps(msg.params[1:])