home · contact · privacy
Add /part, parse PART and JOIN server messages, improve channel log targeting, add... master
authorChristian Heller <c.heller@plomlompom.de>
Tue, 12 Aug 2025 20:58:33 +0000 (22:58 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Tue, 12 Aug 2025 20:58:33 +0000 (22:58 +0200)
ircplom/client.py
ircplom/client_tui.py
ircplom/irc_conn.py

index 7526f9fe4fe96b59ee50eab945c3cc28c8920ed9..d05c181c842cf4e1dff89166f9f78ec93cb45378 100644 (file)
@@ -269,8 +269,7 @@ class Client(ABC, ClientQueueMixin):
                 self.update_login(nickname=msg.params[0], nick_confirmed=True)
             case 'PRIVMSG':
                 self._log(msg.params[-1], scope=LogScope.CHAT, out=False,
-                          sender=msg.source.split('!')[0],
-                          channel=msg.params[0])
+                          sender=msg.nick_from_source, channel=msg.params[0])
             case 'CAP':
                 if (result := self._caps.process_msg(msg.params[1:])):
                     if isinstance(result, str):
@@ -295,6 +294,10 @@ class Client(ABC, ClientQueueMixin):
                 self._log(f'SASL auth {"failed" if alert else "succeeded"}',
                           alert=alert)
                 self._caps.challenge('END')
+            case 'JOIN' | 'PART':
+                user, channel = msg.nick_from_source, msg.params[-1]
+                self._log(f'{user} {msg.verb.lower()}s {channel}',
+                          scope=LogScope.CHAT, channel=channel)
 
 
 @dataclass
index efb34c04141283dd6c54959fcaa8687a761a3950..409f2de028c6fd63889e764e5cc33f78856c5963 100644 (file)
@@ -14,6 +14,7 @@ from ircplom.client import (IrcConnSetup, Client, ClientQueueMixin, LogScope,
 CMD_SHORTCUTS['disconnect'] = 'window.disconnect'
 CMD_SHORTCUTS['join'] = 'window.join'
 CMD_SHORTCUTS['nick'] = 'window.nick'
+CMD_SHORTCUTS['part'] = 'window.part'
 CMD_SHORTCUTS['privmsg'] = 'window.privmsg'
 CMD_SHORTCUTS['reconnect'] = 'window.reconnect'
 
@@ -52,6 +53,10 @@ class _ClientWindow(Window, ClientQueueMixin):
         'Attempt joining a channel.'
         self._send_msg('JOIN', (channel,))
 
+    def cmd__part(self, channel: str) -> None:
+        'Attempt joining a channel.'
+        self._send_msg('PART', (channel,))
+
     def cmd__privmsg(self, target: str, msg: str) -> None:
         'Send chat message msg to target.'
         self._send_msg('PRIVMSG', (target, msg), log_target=target, to_log=msg)
@@ -139,11 +144,12 @@ class _ClientWindowsManager:
         prefix = ''
         if 'out' in kwargs:
             prefix += _LOG_PREFIX_OUT if kwargs['out'] else _LOG_PREFIX_IN
+            if scope == LogScope.CHAT:
+                nickname = (self.nickname if kwargs['out']
+                            else kwargs['sender'])
+                prefix += f' [{nickname}]'
         else:
             prefix += _LOG_PREFIX_SERVER
-        if scope == LogScope.CHAT:
-            nickname = self.nickname if kwargs['out'] else kwargs['sender']
-            prefix += f' [{nickname}]'
         self._tui_log(msg, scope=scope, prefix=prefix, **kwargs)
 
     def update(self, **kwargs) -> bool:
@@ -181,8 +187,8 @@ class ClientTui(BaseTui):
             if target == LogScope.SERVER:
                 return [m.window(LogScope.SERVER), m.window(LogScope.RAW)]
             if target == LogScope.CHAT:
-                chatname = (kwargs['target'] if kwargs['out']
-                            else kwargs.get('channel', kwargs['sender']))
+                chatname = (kwargs['target'] if kwargs.get('out', False)
+                            else kwargs.get('sender', kwargs['channel']))
                 return [m.window(LogScope.CHAT, chatname=chatname)]
             return [m.window(target)]
         return super()._log_target_wins(**kwargs)
index 5e09c1aa7133357111a699f879d366316421c096..197c733362b8cc312c011a48ec5f180ad43aac62 100644 (file)
@@ -98,6 +98,11 @@ class IrcMessage:
         msg._raw = raw_msg
         return msg
 
+    @property
+    def nick_from_source(self) -> str:
+        'Parse .source into user nickname.'
+        return self.source.split('!')[0]
+
     @property
     def raw(self) -> str:
         'Return raw message code – create from known fields if necessary.'