home · contact · privacy
Add 005 handling, improve ClientDb logging infrastructure.
authorChristian Heller <c.heller@plomlompom.de>
Thu, 14 Aug 2025 07:51:03 +0000 (09:51 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Thu, 14 Aug 2025 07:51:03 +0000 (09:51 +0200)
ircplom/client.py
ircplom/client_tui.py

index 688113a0658ac61fda9bd7de2315041291f78ee1..2f8d988870dd274b0195f6ba92e73f7123334a69 100644 (file)
@@ -206,11 +206,15 @@ class ClientDb:
             del self._dict[key_to_unset]
         return (value_changed, confirm_changed)
 
-    def append(self, key, value: str) -> None:
-        'To list[str] keyed by key, append value.'
-        appendable = self.get_force(key)[0]
-        assert isinstance(appendable, list)
-        appendable.append(value)
+    def append(self, key: str, value: str) -> None:
+        'To list[str] keyed by key, append value; if non-existant, create it.'
+        targeted = self.get_force(key)[0]
+        if isinstance(targeted, list):
+            targeted.append(value)
+        elif targeted is None:
+            self._dict[self._unconf_key(key)] = [value]
+        else:
+            raise Exception
 
     def get_force(self, key: str) -> tuple[Optional[int | str | list[str]],
                                            bool]:
@@ -241,6 +245,7 @@ class Client(ABC, ClientQueueMixin):
             self._db.set('port', PORT_SSL, confirm=True)
         self.client_id = self._db.hostname
         self._caps = _CapsManager(self.send, self._db)
+        self._prev_verb = ''
         super().__init__(client_id=self.client_id, **kwargs)
         self._start_connecting()
 
@@ -299,9 +304,9 @@ class Client(ABC, ClientQueueMixin):
         self._log(msg.raw, scope=LogScope.RAW, out=True)
 
     def _update_db(self, key: str, value: Optional[int | str], confirm: bool
-                   ) -> None:
+                   ) -> tuple[bool, bool]:
         'Wrap ._db.set into something accessible to subclass extension.'
-        self._db.set(key, value, confirm)
+        return self._db.set(key, value, confirm)
 
     def close(self) -> None:
         'Close both recv Loop and socket.'
@@ -320,6 +325,9 @@ class Client(ABC, ClientQueueMixin):
     def handle_msg(self, msg: IrcMessage) -> None:
         'Log msg.raw, then process incoming msg into appropriate client steps.'
         self._log(msg.raw, scope=LogScope.RAW, out=False)
+        if msg.verb != self._prev_verb and self._prev_verb == '005':
+            self._update_db('isupports', None, True)
+        self._prev_verb = msg.verb
         numerics_to_ignore = []
         for min_, max_ in _NUMERIC_RANGES_TO_IGNORE:
             numerics_to_ignore += list(range(min_, max_ + 1))
@@ -328,6 +336,11 @@ class Client(ABC, ClientQueueMixin):
         match msg.verb:
             case '001' | 'NICK':
                 self._update_db('nickname', value=msg.params[0], confirm=True)
+            case '005':
+                if self._db.isupports:
+                    self._db.set('isupports', [], False)
+                for param in msg.params[1:-1]:
+                    self._db.append('isupports', param)
             case '375':
                 self._db.set('motd', [], False)
             case '372':
index 6107dbc854079c7782424f92ae734c49225ba8d3..b21fc671dfc3ee56f9290b0af713b1a1e050bb04 100644 (file)
@@ -177,6 +177,12 @@ class _ClientWindowsManager:
         changes = self._db.set(key, value, confirmed)
         for i, t in enumerate((('', value), ('confirmation of ', confirmed))):
             if changes[i]:
+                announcement = f'changing {t[0]}{key} to:'
+                if isinstance(t[1], list):
+                    self.log(announcement, scope=scope)
+                    for item in t[1]:
+                        self.log(f'  {item}', scope=scope)
+                    continue
                 self.log(f'changing {t[0]}{key} to: [{t[1]}]', scope=scope)
         for win in [w for w in self.windows
                     if isinstance(w, _ChatWindow)]:
@@ -286,6 +292,8 @@ class _ClientKnowingTui(Client):
 
     def _update_db(self, key: str, value: Optional[int | str], confirm: bool
                    ) -> None:
-        super()._update_db(key, value, confirm)
+        value_changed, _ = super()._update_db(key, value, confirm)
+        if value is None and not value_changed:  # local ._db may have fallback
+            value = self._db.get_force(key)[0]   # values Tui._db doesn't
         self._client_tui_trigger('update', scope=LogScope.SERVER,
                                  key=key, value=value, confirmed=confirm)