From: Christian Heller Date: Mon, 24 Nov 2025 01:33:25 +0000 (+0100) Subject: On MsgParsseExpectation bonus tasks allow multiple arguments. X-Git-Url: https://plomlompom.com/repos/task?a=commitdiff_plain;h=3ce8a610178c8375ff12a845d606af7e5a913938;p=ircplom On MsgParsseExpectation bonus tasks allow multiple arguments. --- diff --git a/src/ircplom/client.py b/src/ircplom/client.py index 1c2444f..4e36d4a 100644 --- a/src/ircplom/client.py +++ b/src/ircplom/client.py @@ -485,6 +485,19 @@ class _ClientDb(Clearable, UpdatingAttrsMixin, SharedClientDbFields): key, data = _tuple_key_val_from_eq_str(item) self.isupport[key] = data + def set_nick_incl_wanted(self, user: _User, nick: str) -> None: + 'Set new_nick to user, and .nick_wanted if ourselves.' + self.users[user.id_].nick = nick + if user.id_ == 'me': + self.nick_wanted = nick + + def part_user_maybe_us(self, parter: _User, channel: str, msg='') -> None: + 'Call parter.part, and if ourselves also remove channel.' + parter.part(channel, msg) + if parter is self.users['me']: + del self.channels[channel] + self.users.purge() + def messaging(self, src: str | NickUserHost) -> ChatMessage: 'Start input chain for chat message data.' return _ChatMessage(sender=src, db=self) @@ -826,8 +839,8 @@ class Client(ABC, ClientQueueMixin): for ret_name in [k for k in ret if ret[k] == n_u_h]: ret[ret_name] = self.db.users[id_] for verb in ('setattr', 'do', 'doafter'): - for task, tok_names in [t for t in ret['_tasks'].items() - if t[0].verb == verb]: + for task, args in [t for t in ret['_tasks'].items() + if t[0].verb == verb]: path = list(task.path) node: Any = (ret[path.pop(0)] if task.path and path[0].isupper() else self) @@ -836,11 +849,13 @@ class Client(ABC, ClientQueueMixin): node = (node[key] if isinstance(node, Dict) else (node(key) if callable(node) else getattr(node, key))) - for tok_name in tok_names: + for arg in args: if task.verb == 'setattr': - setattr(node, tok_name, ret[tok_name]) - elif tok_name: - node(ret[tok_name]) + setattr(node, arg, ret[arg]) + elif ',' in arg: + node(*(ret[split] for split in arg.split(','))) + elif arg: + node(ret[arg]) else: node() if ret['_verb'] == '401': # ERR_NOSUCHNICK @@ -861,21 +876,6 @@ class Client(ABC, ClientQueueMixin): self.send('AUTHENTICATE', _SASL_PLAIN) else: self.caps.end_negotiation() - elif ret['_verb'] == 'MODE' and 'mode_on_nick' in ret: - self.db.channels[ret['channel']].mode_on_nick( - ret['nick'], ret['mode_on_nick']) - elif ret['_verb'] == 'NICK': - user_id = self.db.users.id_for_nickuserhost(ret['named'], - updating=True) - assert user_id is not None - self.db.users[user_id].nick = ret['nick'] - if user_id == 'me': - self.db.nick_wanted = ret['nick'] - elif ret['_verb'] == 'PART': - ret['parter'].part(ret['channel'], ret.get('message', '')) - if ret['parter'] is self.db.users['me']: - del self.db.channels[ret['channel']] - self.db.users.purge() ClientsDb = dict[str, Client] diff --git a/src/ircplom/msg_parse_expectations.py b/src/ircplom/msg_parse_expectations.py index 93ce1de..de8c036 100644 --- a/src/ircplom/msg_parse_expectations.py +++ b/src/ircplom/msg_parse_expectations.py @@ -36,17 +36,17 @@ class _Command(NamedTuple): class _Code(NamedTuple): - tok_name: str = '' commands: tuple[_Command, ...] = tuple() + arg: str = '' skip_nuh: bool = False def __bool__(self) -> bool: - return bool(self.tok_name) or bool(self.commands) + return bool(self.commands) or bool(self.arg) @classmethod def from_(cls, input_: str) -> Self: - 'Split by ":" into commands (further split by ","), tok_name.' - commands_str, tok_name = input_.split(':', maxsplit=1) + 'Split by ":" into commands (further split by ","), argument.' + commands_str, arg = input_.split(':', maxsplit=1) skip_nuh = False commands: list[_Command] = [] for command_str in commands_str.split(','): @@ -54,7 +54,7 @@ class _Code(NamedTuple): skip_nuh = True elif command_str: commands += [_Command.from_(command_str)] - return cls(tok_name, tuple(commands), skip_nuh) + return cls(tuple(commands), arg, skip_nuh) class _TokenExpectation(NamedTuple): @@ -92,7 +92,7 @@ class _MsgParseExpectation: for code in (tuple(exp_field.code for exp_field in self._fields) + tuple(_Code.from_(item) for item in bonus_tasks)): for cmd in code.commands: - tasks[cmd] = tasks.get(cmd, []) + [code.tok_name] + tasks[cmd] = tasks.get(cmd, []) + [code.arg] self._harvest_invariables = {'_verb': self.verb, '_tasks': tasks} @property @@ -141,12 +141,12 @@ class _MsgParseExpectation: if not validators.get(exp_tok.type_, lambda _: True)(msg_tok): return None # validator found for this type, but failed it if isinstance(exp_tok.type_, str) and exp_tok.type_ != msg_tok: - return None # validator for specific string + return None # "specific string"-validator failed if exp_tok.type_ is _MsgToken.NICK_USER_HOST\ and not exp_tok.code.skip_nuh: nickuserhosts += [parsed(exp_tok.type_, msg_tok)] - if exp_tok.code.tok_name: - d[exp_tok.code.tok_name] = parsed(exp_tok.type_, msg_tok) + if exp_tok.code.arg: + d[exp_tok.code.arg] = parsed(exp_tok.type_, msg_tok) return d | {'_nickuserhosts': tuple(nickuserhosts)} if (msg_fields := divide_msg(msg)): @@ -445,8 +445,9 @@ MSG_EXPECTATIONS: list[_MsgParseExpectation] = [ _MsgParseExpectation( 'NICK', - (_MsgToken.NICK_USER_HOST, ':named'), - ((_MsgToken.NICKNAME, ':nick'),)), + (_MsgToken.NICK_USER_HOST, ':user'), + ((_MsgToken.NICKNAME, ':nick'),), + bonus_tasks=('do_db.set_nick_incl_wanted:user,nick',)), # joining/leaving @@ -498,12 +499,14 @@ MSG_EXPECTATIONS: list[_MsgParseExpectation] = [ _MsgParseExpectation( 'PART', (_MsgToken.NICK_USER_HOST, ':parter'), - ((_MsgToken.CHANNEL, ':channel'),)), + ((_MsgToken.CHANNEL, ':channel'),), + bonus_tasks=('do_db.part_user_maybe_us:parter,channel',)), _MsgParseExpectation( 'PART', (_MsgToken.NICK_USER_HOST, ':parter'), ((_MsgToken.CHANNEL, ':channel'), - (_MsgToken.ANY, ':message'))), + (_MsgToken.ANY, ':message')), + bonus_tasks=('do_db.part_user_maybe_us:parter,channel,message',)), # messaging @@ -589,9 +592,10 @@ MSG_EXPECTATIONS: list[_MsgParseExpectation] = [ _MsgParseExpectation( 'MODE', _MsgToken.SERVER, - ((_MsgToken.CHANNEL, ':channel'), - (_MsgToken.ANY, ':mode_on_nick'), - (_MsgToken.NICKNAME, ':nick'))), + ((_MsgToken.CHANNEL, ':CHANNEL'), + (_MsgToken.ANY, ':mode'), + (_MsgToken.NICKNAME, ':nick')), + bonus_tasks=('do_db.channels.CHANNEL.mode_on_nick:nick,mode',)), _MsgParseExpectation( 'TOPIC',