_MsgParseExpectation((_MsgTok.NICK_USER_HOST, ':parter'),
'PART',
((_MsgTok.CHANNEL, ':channel'),)),
- _MsgParseExpectation((_MsgTok.NICK_USER_HOST, ':parter'),
- 'PART',
- ((_MsgTok.CHANNEL, ':channel'),
- (_MsgTok.ANY, ':reason'))),
]
# messaging
self._caps.end_negotiation()
elif ret['verb'] == 'ERROR':
self.close()
- elif ret['verb'] == 'JOIN':
- self._log(f'{ret["joiner"]} {msg.verb.lower()}s '
- + f'{ret["channel"]["id"]}',
- scope=LogScope.CHAT, target=ret['channel']['id'])
- if ret['joiner'].nick != self._db.nickname:
- ret['channel']['db'].append_completable(
- 'users', ret['joiner'].nick, True)
+ elif ret['verb'] == 'JOIN' and ret['joiner'].nick != self._db.nickname:
+ ret['channel']['db'].append_completable(
+ 'users', ret['joiner'].nick, True)
elif ret['verb'] == 'NICK':
if ret['named'].nick == self._db.nickname:
self._db.nickname = ret['nickname']
else ret['channel']['id'])}
self._log(ret['message'], out=False, **kw)
elif ret['verb'] == 'PART':
- reason = f': {ret["reason"]}' if 'reason' in ret else ''
- self._log(f'{ret["parter"]} {msg.verb.lower()}s '
- + f'{ret["channel"]["id"]}{reason}',
- scope=LogScope.CHAT, target=ret['channel']['id'])
if ret['parter'].nick == self._db.nickname:
self._db.del_chan(ret['channel']['id'])
else:
d[update.arg] = update.value
return update.value != old_value
- def set_and_check_for_change(self, update: _Update) -> bool:
+ def set_and_check_for_change(self, update: _Update
+ ) -> bool | dict[str, tuple[str, ...]]:
'Apply update, return if that actually made a difference.'
self._typecheck(update.path, update.value)
old_value = getattr(self, update.path)
class _ChannelDb(_Db):
users: tuple[str, ...]
- def set_and_check_for_change(self, update: _Update) -> bool:
+ def set_and_check_for_change(self, update: _Update
+ ) -> bool | dict[str, tuple[str, ...]]:
if isinstance(getattr(self, update.path), dict):
return self._set_and_check_for_dict(update)
+ if update.path == 'users':
+ assert isinstance(update.value, tuple)
+ d = {'joins': tuple(user for user in update.value
+ if user not in self.users),
+ 'parts': tuple(user for user in self.users
+ if user not in update.value)}
+ return d if super().set_and_check_for_change(update) else False
return super().set_and_check_for_change(update)
motd: tuple[str]
_channels: dict[str, _ChannelDb]
- def set_and_check_for_change(self, update: _Update) -> bool:
+ def set_and_check_for_change(self, update: _Update
+ ) -> bool | dict[str, tuple[str, ...]]:
if update.is_chan:
chan_name = update.path
if update.value is None and not update.arg:
verb = 'cleared' if update.value is None else 'changed to:'
what = f'{update.path}:{update.arg}' if update.arg else update.path
log_kwargs = {'target': update.path} if update.is_chan else {}
- if not self.db.set_and_check_for_change(update):
+ result = self.db.set_and_check_for_change(update)
+ if result is False:
return False
- announcement = f'{what} {verb}'
- if isinstance(update.value, tuple) or announcement[-1] != ':':
- self.log(announcement, scope=scope, **log_kwargs)
- if isinstance(update.value, tuple):
- for item in update.value:
- self.log(f' {item}', scope=scope, **log_kwargs)
- elif announcement[-1] == ':':
- self.log(f'{announcement} [{update.display}]',
- scope=scope, **log_kwargs)
+ if isinstance(result, dict):
+ for verb, names in result.items():
+ for name in names:
+ self.log(f'{name} {verb}', scope=scope, **log_kwargs)
+ else:
+ announcement = f'{what} {verb}'
+ if isinstance(update.value, tuple) or announcement[-1] != ':':
+ self.log(announcement, scope=scope, **log_kwargs)
+ if isinstance(update.value, tuple):
+ for item in update.value:
+ self.log(f' {item}', scope=scope, **log_kwargs)
+ elif announcement[-1] == ':':
+ self.log(f'{announcement} [{update.display}]',
+ 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])