return scopes.get(key, scopes[''])
def recursive_set_and_report_change(
- self, update: _Update) -> Optional[tuple[LogScope, Any]]:
+ self, update: _Update) -> tuple[tuple[LogScope, Any], ...]:
'Apply update, return if that actually made a difference.'
update.force_log = update.force_log or (not self._is_set(update.key))
node = self._get(update.key)
def _focused_set_and_report_change(
self, old_value: '_UpdatingNode', update: _Update
- ) -> Optional[tuple[LogScope, Any]]:
+ ) -> tuple[tuple[LogScope, Any], ...]:
scope = self._scope(update.key)
do_report = update.force_log
if update.value is None:
elif old_value != update.value:
self._set(update.key, update.value)
do_report |= True
- return (scope, update.value) if do_report else None
+ return ((scope, update.value),) if do_report else tuple()
def _get(self, key: str) -> Any:
return getattr(self, key)
def _focused_set_and_report_change(
self, old_value: '_UpdatingNode', update: _Update
- ) -> Optional[tuple[LogScope, Any]]:
+ ) -> tuple[tuple[LogScope, Any], ...]:
scope = self._scope(update.key)
if update.key == 'topic':
if super()._focused_set_and_report_change(old_value, update):
- return (scope,
- f'RAW:{self.topic.who} set topic: {self.topic.what}')
- return None
+ return ((scope,
+ f'RAW:{self.topic.who} set topic: {self.topic.what}'),)
+ return tuple()
assert update.key == 'user_ids'
assert isinstance(update.value, set)
d = ({'NUHS:joining': tuple(sorted(id_ for id_ in update.value
if self.user_ids
else {'NICKS:residents': tuple(sorted(update.value))})
if super()._focused_set_and_report_change(old_value, update):
- return scope, d
- return None
+ return ((scope, d),)
+ return tuple()
class _UpdatingUser(_UpdatingNode, User):
- log_scopes = {'nick': LogScope.USER, 'exit_msg': LogScope.USER}
+ log_scopes = {'exit_msg': LogScope.USER}
prev_nick = '?'
def _focused_set_and_report_change(
self, old_value: '_UpdatingNode', update: _Update
- ) -> Optional[tuple[LogScope, Any]]:
+ ) -> tuple[tuple[LogScope, Any], ...]:
assert isinstance(update.value, str)
if (result := super()._focused_set_and_report_change(old_value,
update)):
if update.key not in {'nick', 'exit_msg'}:
return result
- scope = self._scope(update.key)
msg = 'RAW:'
if update.key == 'nick':
- return scope, msg + f'{self.prev} renames {update.value}'
+ return result + (
+ (LogScope.USER,
+ msg + f'{self.prev} renames {update.value}'),)
if update.key == 'exit_msg' and update.value:
msg += f'{self} '
msg += 'quits' if update.value[0] == 'Q' else 'parts'
if len(update.value) > 1:
msg += ': ' + update.value[1:]
- return scope, msg
- return None
+ return ((self._scope(update.key), msg),)
+ return tuple()
@property
def prev(self) -> str:
def update_db(self, update: _Update) -> bool:
'Apply update to .db, and if changing anything, log and trigger.'
result = self.db.recursive_set_and_report_change(update)
- if result is None:
+ if not result:
return False
- scope, value = result
- log_path = ':'.join(update.path)
- log_kwargs: dict[str, Any] = {'scope': scope}
- if scope in {LogScope.CHAT, LogScope.USER}:
- log_kwargs |= {'target': update.path[1]}
- if value is None:
- self.log(f'{log_path} cleared', **log_kwargs)
- elif isinstance(value, dict):
- for verb, item in [(k, v) for k, v in value.items() if v]:
- toks = verb.split(':', maxsplit=1)
- verb = toks[-1]
- transform = toks[0] if len(toks) > 1 else ''
- if transform in {'NICKS', 'NUHS'}:
- nuhs = (self.db.users[id_] for id_ in item)
- item = ', '.join([
- (str(nuh) if transform == 'nuhs' else nuh.nick)
- for nuh in nuhs])
- self.log(f'{verb}: {item}', **log_kwargs)
- elif isinstance(value, str) and value.startswith('RAW:'):
- self.log(value.split(':', maxsplit=1)[1], **log_kwargs)
- else:
- announcement = f'{log_path} set to:'
- if isinstance(value, tuple):
- self.log(announcement, **log_kwargs)
- for item in value:
- self.log(f' {item}', **log_kwargs)
+ for t in result:
+ scope, value = t
+ log_path = ':'.join(update.path)
+ log_kwargs: dict[str, Any] = {'scope': scope}
+ if scope in {LogScope.CHAT, LogScope.USER}:
+ log_kwargs |= {'target': update.path[1]}
+ if value is None:
+ self.log(f'{log_path} cleared', **log_kwargs)
+ elif isinstance(value, dict):
+ for verb, item in [(k, v) for k, v in value.items() if v]:
+ toks = verb.split(':', maxsplit=1)
+ verb = toks[-1]
+ transform = toks[0] if len(toks) > 1 else ''
+ if transform in {'NICKS', 'NUHS'}:
+ nuhs = (self.db.users[id_] for id_ in item)
+ item = ', '.join([
+ (str(nuh) if transform == 'nuhs' else nuh.nick)
+ for nuh in nuhs])
+ self.log(f'{verb}: {item}', **log_kwargs)
+ elif isinstance(value, str) and value.startswith('RAW:'):
+ self.log(value.split(':', maxsplit=1)[1], **log_kwargs)
else:
- self.log(f'{announcement} [{value}]', **log_kwargs)
+ announcement = f'{log_path} set to:'
+ if isinstance(value, tuple):
+ self.log(announcement, **log_kwargs)
+ for item in value:
+ self.log(f' {item}', **log_kwargs)
+ else:
+ self.log(f'{announcement} [{value}]', **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])
# ETC.
+# on /connect init databases, log in new windows
> /connect foo.bar.baz foo:bar baz
1,2 $ isupport cleared
1,2 $ isupport:CHANTYPES set to: [#&]
1,2 $ caps cleared
1,2 $ users cleared
1,2 $ channels cleared
+
+# connect with values set by /connect
1,2 $ hostname set to: [foo.bar.baz]
1,2 $ port set to: [-1]
1,2 $ nick_wanted set to: [foo]
1,2 $ realname set to: [baz]
1,2 $ password set to: [bar]
1,2 $ port set to: [6697]
-
1,2 $ connection_state set to: [connecting]
+1,2 $ users:me:nick set to: [?]
1,2 $ ?!?@? renames ?
1,2 $ users:me:user set to: [plom]
1,2 $ connection_state set to: [connected]
2 > AUTHENTICATE :Zm9vAGZvbwBiYXI=
2 < :foo.bar.baz 900 foo foo!plom@baz.bar.foo foo :You are now logged in as foo
+1,2 $ users:me:nick set to: [foo]
1,2 $ ?!plom@? renames foo
1,2 $ users:me:host set to: [baz.bar.foo]
2 < :foo.bar.baz 333 foo #test bar!~bar@bar.bar 1234567890
4 $ bar!~bar@bar.bar set topic: foo bar baz
2 < :foo.bar.baz 353 foo @ #test :foo @bar
+1,2 $ users:1:nick set to: [?]
, $ ?!?@? renames ?
+1,2 $ users:1:nick set to: [bar]
, $ ?!?@? renames bar
2 < :foo.bar.baz 366 foo #test :End of /NAMES list.
4 $ residents: bar, foo
2 < :bar!~bar@bar.bar TOPIC #test :abc def ghi
4 $ bar!~bar@bar.bar set topic: abc def ghi
2 < :baz!~baz@baz.baz JOIN :#test
+1,2 $ users:2:nick set to: [?]
, $ ?!?@? renames ?
+1,2 $ users:2:nick set to: [baz]
, $ ?!?@? renames baz
1,2 $ users:2:user set to: [~baz]
1,2 $ users:2:host set to: [baz.baz]
4 $ joining: baz
2 < :baz!~baz@baz.baz NICK :bazbaz
+1,2 $ users:2:nick set to: [bazbaz]
4 $ baz!~baz@baz.baz renames bazbaz
2 < :bazbaz!~baz@baz.baz PART :#test
4 $ bazbaz!~baz@baz.baz parts
1,2 $ users:2 cleared
+1,2 $ users:2:nick set to: [?]
, $ ?!?@? renames ?
2 < :bazbaz!~baz@baz.baz JOIN :#test
+1,2 $ users:3:nick set to: [?]
, $ ?!?@? renames ?
+1,2 $ users:3:nick set to: [bazbaz]
, $ ?!?@? renames bazbaz
1,2 $ users:3:user set to: [~baz]
1,2 $ users:3:host set to: [baz.baz]
4 $ bazbaz!~baz@baz.baz quits: Client Quit
1,2 $ users:2 cleared
1,2 $ users:3 cleared
+1,2 $ users:3:nick set to: [?]
, $ ?!?@? renames ?
2 < :foo!~plom@baz.bar.foo PART :#test
1,2,3,4 $ foo!~plom@baz.bar.foo parts
1,2,3,4 $ connection_state set to: [connecting]
# except for two positions marked with NB comment, exactly same as on 1st time
+1,2 $ users:me:nick set to: [?]
1,2,3,4 $ ?!?@? renames ?
1,2 $ users:me:user set to: [plom]
1,2,3,4 $ connection_state set to: [connected]
2 < AUTHENTICATE +
2 > AUTHENTICATE :Zm9vAGZvbwBiYXI=
2 < :foo.bar.baz 900 foo foo!plom@baz.bar.foo foo :You are now logged in as foo
+1,2 $ users:me:nick set to: [foo]
1,2,3,4 $ ?!plom@? renames foo
1,2 $ users:me:host set to: [baz.bar.foo]
1,2 $ sasl_account set to: [foo]
2 < :foo!~plom@baz.bar.foo JOIN #test
1,2 $ users:me:user set to: [~plom]
2 < :foo.bar.baz 353 foo @ #test :foo @bar
+1,2 $ users:4:nick set to: [?]
, $ ?!?@? renames ?
+1,2 $ users:4:nick set to: [bar]
, $ ?!?@? renames bar
2 < :foo.bar.baz 366 foo #test :End of /NAMES list.
4 $ residents: bar, foo