self._dict[key] = val
self._on_update(key)
+ def __delitem__(self, key: str) -> None:
+ del self._dict[key]
+ self._on_update(f'-{key}')
+
class _ClientDb(_Db, IrcConnSetup):
connection_state: str
channel = msg.params[0]
log_msg = f'{msg.nick_from_source} {msg.verb.lower()}s {channel}'
match msg.verb:
- case '005' if len(msg.params) > 2:
+ case '005' if len(msg.params) > 2: # RPL_ISUPPORT
for param in msg.params[1:-1]:
toks = param.split('=', maxsplit=1)
- self._db.isupports[toks[0]] = (toks[1] if len(toks) > 1
- else '')
- case '353' if len(msg.params) == 4:
+ if toks[0][0] == '-':
+ del self._db.isupports[toks[0][1:]]
+ else:
+ self._db.isupports[toks[0]] = (
+ toks[1] if len(toks) > 1 else '')
+ case '353' if len(msg.params) == 4: # RPL_NAMREPLY
for user in msg.params[3].split():
self._db.chan(msg.params[2]
).append_completable('users', user)
- case '366' if len(msg.params) == 3:
+ case '366' if len(msg.params) == 3: # RPL_ENDOFNAMES
self._db.chan(msg.params[1]).declare_complete('users')
case '372' if len(msg.params) == 2: # RPL_MOTD
self._db.append_completable('motd', msg.params[1])
# '@'-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]
+ case '903' | '904' if len(msg.params) == 2: # RPL_SASLSUCESS
+ alert = msg.verb == '904' # ERR_SASLFAIL
+ self._log(f'SASL auth {"failed" if alert else "succeeded"}',
+ alert=alert)
+ self._caps.end_negotiation()
case 'AUTHENTICATE' if msg.params == ('+',):
auth = b64encode((self._db.nickname + '\0' +
self._db.nickname + '\0' +
self._db.chan(channel).users.remove(msg.nick_from_source)
case 'PING' if len(msg.params) == 1:
self.send(IrcMessage(verb='PONG', params=(msg.params[0],)))
- case '903' | '904' if len(msg.params) == 2:
- alert = msg.verb == '904'
- self._log(f'SASL auth {"failed" if alert else "succeeded"}',
- alert=alert)
- self._caps.end_negotiation()
case _:
self._log(f'PLEASE IMPLEMENT HANDLER FOR: {msg.raw}')
d = getattr(self, dict_name)
if arg == CLEAR_WORD:
d.clear()
- return True
- old_value = d.get(arg, None)
- d[arg] = value
- return value != old_value
+ elif arg[0] == '-':
+ del d[arg[1:]]
+ else:
+ old_value = d.get(arg, None)
+ d[arg] = value
+ return value != old_value
+ return True
return super().set_and_check_for_change(key, value)
def chan(self, name: str) -> _ChannelDb:
db: _TuiClientDb | _ChannelDb = self._db
scope = LogScope.SERVER
log_kwargs: dict[str, str] = {}
- clearing = False
+ verb = 'changed to:'
what = key
if ' ' in key:
type_char, parent_name, subkey = key.split()
- clearing = subkey == CLEAR_WORD
if type_char == 'c':
db = self._db.chan(parent_name)
scope = LogScope.CHAT
log_kwargs |= {'channel': parent_name}
+ if subkey == CLEAR_WORD:
+ verb = 'cleared'
+ what = parent_name
+ elif type_char == 'c':
key = what = subkey
else:
+ if subkey[0] == '-':
+ verb = 'unset'
+ subkey = subkey[1:]
what = f'{parent_name}:{subkey}'
elif key == 'connection_state':
scope = LogScope.ALL
if not db.set_and_check_for_change(key, value):
return False
- if not clearing:
- announcement = f'changed {what} to:'
- if isinstance(value, tuple):
- self.log(announcement, scope=scope, **log_kwargs)
- for item in value:
- self.log(f' {item}', scope=scope, **log_kwargs)
- else:
- self.log(f'{announcement} [{value}]',
- scope=scope, **log_kwargs)
- for win in [w for w in self.windows
- if isinstance(w, _ChatWindow)]:
+ announcement = f'{what} {verb}'
+ if isinstance(value, tuple) or announcement[-1] != ':':
+ self.log(announcement, scope=scope, **log_kwargs)
+ if isinstance(value, tuple):
+ for item in value:
+ self.log(f' {item}', scope=scope, **log_kwargs)
+ elif announcement[-1] == ':':
+ self.log(f'{announcement} [{value}]', scope=scope, **log_kwargs)
+ for win in [w for w in self.windows if isinstance(w, _ChatWindow)]:
win.set_prompt_prefix()
return bool([w for w in self.windows if w.tainted])
value = tuple(lines)
elif ' ' in key:
type_char, parent_name, arg = key.split()
- if arg == CLEAR_WORD:
+ if arg == CLEAR_WORD or arg[0] == '-':
value = ''
elif type_char == 'c':
value = getattr(self._db.chan(parent_name), arg)