From: Christian Heller Date: Tue, 2 Sep 2025 05:14:08 +0000 (+0200) Subject: Move server message expectations into their own file. X-Git-Url: https://plomlompom.com/repos/new_day?a=commitdiff_plain;h=c17f5c265f62617e6c56971a5613a70ad8235492;p=ircplom Move server message expectations into their own file. --- diff --git a/ircplom/client.py b/ircplom/client.py index bc10127..c0c352e 100644 --- a/ircplom/client.py +++ b/ircplom/client.py @@ -6,7 +6,7 @@ from dataclasses import dataclass, InitVar from enum import Enum, auto from getpass import getuser from threading import Thread -from typing import Any, Callable, Generic, NamedTuple, Optional, Self, TypeVar +from typing import Any, Callable, Generic, Optional, Self, TypeVar from uuid import uuid4 # ourselves from ircplom.events import ( @@ -14,6 +14,7 @@ from ircplom.events import ( from ircplom.irc_conn import ( BaseIrcConnection, IrcConnAbortException, IrcMessage, ILLEGAL_NICK_CHARS, ILLEGAL_NICK_FIRSTCHARS, ISUPPORT_DEFAULTS, PORT_SSL) +from ircplom.msg_parse_expectations import MsgTok, MSG_EXPECTATIONS ClientsDb = dict[str, 'Client'] @@ -143,324 +144,6 @@ class ClientQueueMixin(QueueMixin, _ClientIdMixin): _NAMES_DESIRED_SERVER_CAPS = ('sasl',) -class _MsgTok(Enum): - ANY = auto() - CHANNEL = auto() - LIST = auto() - NICKNAME = auto() - NONE = auto() - SERVER = auto() - NICK_USER_HOST = auto() - - -_MsgTokGuide = str | _MsgTok | tuple[str | _MsgTok, str] - - -class _MsgParseExpectation(NamedTuple): - source: _MsgTokGuide - verb: str - params: tuple[_MsgTokGuide, ...] = tuple() - idx_into_list: int = -1 - - -_EXPECTATIONS: list[_MsgParseExpectation] = [] - -# these we ignore except for confirming/collecting the nickname -_EXPECTATIONS += [ - _MsgParseExpectation(_MsgTok.SERVER, - '001', # RPL_WELCOME - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - _MsgTok.ANY)), - _MsgParseExpectation(_MsgTok.SERVER, - '002', # RPL_YOURHOST - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - _MsgTok.ANY)), - _MsgParseExpectation(_MsgTok.SERVER, - '003', # RPL_CREATED - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - _MsgTok.ANY)), - _MsgParseExpectation(_MsgTok.SERVER, - '004', # RPL_MYINFO - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - _MsgTok.ANY, - _MsgTok.ANY, - _MsgTok.ANY, - _MsgTok.ANY, - _MsgTok.ANY)), - _MsgParseExpectation(_MsgTok.SERVER, - '250', # RPL_STATSDLINE / RPL_STATSCONN - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - _MsgTok.ANY)), - _MsgParseExpectation(_MsgTok.SERVER, - '251', # RPL_LUSERCLIENT - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - _MsgTok.ANY)), - _MsgParseExpectation(_MsgTok.SERVER, - '252', # RPL_LUSEROP - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - _MsgTok.ANY, - _MsgTok.ANY)), - _MsgParseExpectation(_MsgTok.SERVER, - '253', # RPL_LUSERUNKNOWN - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - _MsgTok.ANY, - _MsgTok.ANY)), - _MsgParseExpectation(_MsgTok.SERVER, - '254', # RPL_LUSERCHANNELS - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - _MsgTok.ANY, - _MsgTok.ANY)), - _MsgParseExpectation(_MsgTok.SERVER, - '255', # RPL_LUSERME - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - _MsgTok.ANY)), - _MsgParseExpectation(_MsgTok.SERVER, - '265', # RPL_LOCALUSERS - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - _MsgTok.ANY)), - _MsgParseExpectation(_MsgTok.SERVER, - '265', # RPL_LOCALUSERS - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - _MsgTok.ANY, - _MsgTok.ANY, - _MsgTok.ANY)), - _MsgParseExpectation(_MsgTok.SERVER, - '266', # RPL_GLOBALUSERS - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - _MsgTok.ANY)), - _MsgParseExpectation(_MsgTok.SERVER, - '266', # RPL_GLOBALUSERS - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - _MsgTok.ANY, - _MsgTok.ANY, - _MsgTok.ANY)), - _MsgParseExpectation(_MsgTok.SERVER, - '375', # RPL_MOTDSTART already implied by 1st 372 - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - _MsgTok.ANY)), -] - -# various login stuff -_EXPECTATIONS += [ - _MsgParseExpectation(_MsgTok.SERVER, - '005', # RPL_ISUPPORT - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - (_MsgTok.ANY, ':isupport'), - _MsgTok.ANY), # comment - idx_into_list=1), - _MsgParseExpectation(_MsgTok.SERVER, - '372', # RPL_MOTD - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - (_MsgTok.ANY, ':line'))), - _MsgParseExpectation(_MsgTok.SERVER, - '376', # RPL_ENDOFMOTD - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - _MsgTok.ANY)), # comment - _MsgParseExpectation(_MsgTok.SERVER, - '396', # RPL_VISIBLEHOST - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - (_MsgTok.SERVER, 'set_me_attr:host'), - _MsgTok.ANY)), # comment -] - -# SASL -_EXPECTATIONS += [ - _MsgParseExpectation(_MsgTok.SERVER, - '900', # RPL_LOGGEDIN - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - (_MsgTok.NICK_USER_HOST, 'set_me_attr:nickuserhost'), - (_MsgTok.ANY, 'set_db_attr:sasl_account'), - _MsgTok.ANY)), # comment - _MsgParseExpectation(_MsgTok.SERVER, - '903', # RPL_SASLSUCCESS - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - (_MsgTok.ANY, 'set_db_attr:sasl_auth_state'))), - _MsgParseExpectation(_MsgTok.SERVER, - '904', # ERR_SASLFAIL - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - (_MsgTok.ANY, 'set_db_attr:sasl_auth_state'))), - _MsgParseExpectation(_MsgTok.NONE, - 'AUTHENTICATE', - ('+',)), -] - -# capability negotation -_EXPECTATIONS += [ - _MsgParseExpectation(_MsgTok.SERVER, - 'CAP', - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - ('NEW', ':subverb'), - (_MsgTok.LIST, ':items'))), - _MsgParseExpectation(_MsgTok.SERVER, - 'CAP', - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - ('DEL', ':subverb'), - (_MsgTok.LIST, ':items'))), - _MsgParseExpectation(_MsgTok.SERVER, - 'CAP', - ('*', - ('ACK', ':subverb'), - (_MsgTok.LIST, ':items'))), - _MsgParseExpectation(_MsgTok.SERVER, - 'CAP', - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - ('ACK', ':subverb'), - (_MsgTok.LIST, ':items'))), - _MsgParseExpectation(_MsgTok.SERVER, - 'CAP', - ('*', - ('NAK', ':subverb'), - (_MsgTok.LIST, ':items'))), - _MsgParseExpectation(_MsgTok.SERVER, - 'CAP', - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - ('NAK', ':subverb'), - (_MsgTok.LIST, ':items'))), - _MsgParseExpectation(_MsgTok.SERVER, - 'CAP', - ('*', - ('LS', ':subverb'), - (_MsgTok.LIST, ':items'))), - _MsgParseExpectation(_MsgTok.SERVER, - 'CAP', - ('*', - ('LS', ':subverb'), - ('*', ':tbc'), - (_MsgTok.LIST, ':items'))), - _MsgParseExpectation(_MsgTok.SERVER, - 'CAP', - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - ('LS', ':subverb'), - (_MsgTok.LIST, ':items'))), - _MsgParseExpectation(_MsgTok.SERVER, - 'CAP', - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - ('LS', ':subverb'), - ('*', ':tbc'), - (_MsgTok.LIST, ':items'))), - - _MsgParseExpectation(_MsgTok.SERVER, - 'CAP', - ('*', - ('LIST', ':subverb'), - (_MsgTok.LIST, ':items'))), - _MsgParseExpectation(_MsgTok.SERVER, - 'CAP', - ('*', - ('LIST', ':subverb'), - ('*', ':tbc'), - (_MsgTok.LIST, ':items'))), - _MsgParseExpectation(_MsgTok.SERVER, - 'CAP', - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - ('LIST', ':subverb'), - (_MsgTok.LIST, ':items'))), - _MsgParseExpectation(_MsgTok.SERVER, - 'CAP', - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - ('LIST', ':subverb'), - ('*', ':tbc'), - (_MsgTok.LIST, ':items'))), -] - -# nickname management -_EXPECTATIONS += [ - _MsgParseExpectation(_MsgTok.SERVER, - '432', # ERR_ERRONEOUSNICKNAME - ('*', - _MsgTok.NICKNAME, # no need to re-use the bad one - _MsgTok.ANY)), # comment - _MsgParseExpectation(_MsgTok.SERVER, - '432', # ERR_ERRONEOUSNICKNAME - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - _MsgTok.NICKNAME, # no need to re-use the bad one - _MsgTok.ANY)), # comment - _MsgParseExpectation(_MsgTok.SERVER, - '433', # ERR_NICKNAMEINUSE - (_MsgTok.NICKNAME, # we rather go for incrementation - (_MsgTok.NICKNAME, ':used'), - _MsgTok.ANY)), # comment - _MsgParseExpectation((_MsgTok.NICK_USER_HOST, ':named'), - 'NICK', - ((_MsgTok.NICKNAME, ':nick'),)), -] - -# joining/leaving -_EXPECTATIONS += [ - _MsgParseExpectation(_MsgTok.SERVER, - '353', # RPL_NAMREPLY - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - '=', - (_MsgTok.CHANNEL, ':channel'), - (_MsgTok.LIST, ':names'))), - _MsgParseExpectation(_MsgTok.SERVER, - '366', # RPL_ENDOFNAMES - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - (_MsgTok.CHANNEL, ':channel'), - _MsgTok.ANY)), # comment - _MsgParseExpectation((_MsgTok.NICK_USER_HOST, ':joiner'), - 'JOIN', - ((_MsgTok.CHANNEL, ':channel'),)), - _MsgParseExpectation((_MsgTok.NICK_USER_HOST, ':parter'), - 'PART', - ((_MsgTok.CHANNEL, ':channel'),)), -] - -# messaging -_EXPECTATIONS += [ - _MsgParseExpectation(_MsgTok.SERVER, - '401', # ERR_NOSUCKNICK - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - (_MsgTok.NICKNAME, ':target'), - _MsgTok.ANY)), # comment - _MsgParseExpectation(_MsgTok.SERVER, - 'NOTICE', - ('*', - (_MsgTok.ANY, ':message'))), - _MsgParseExpectation(_MsgTok.SERVER, - 'NOTICE', - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - (_MsgTok.ANY, ':message'))), - _MsgParseExpectation((_MsgTok.NICK_USER_HOST, 'set_user:sender'), - 'NOTICE', - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - (_MsgTok.ANY, ':message'))), - _MsgParseExpectation((_MsgTok.NICK_USER_HOST, 'set_user:sender'), - 'NOTICE', - ((_MsgTok.CHANNEL, ':channel'), - (_MsgTok.ANY, ':message'))), - _MsgParseExpectation((_MsgTok.NICK_USER_HOST, 'set_user:sender'), - 'PRIVMSG', - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - (_MsgTok.ANY, ':message'))), - _MsgParseExpectation((_MsgTok.NICK_USER_HOST, 'set_user:sender'), - 'PRIVMSG', - ((_MsgTok.CHANNEL, ':channel'), - (_MsgTok.ANY, ':message'))), -] - -# misc. -_EXPECTATIONS += [ - _MsgParseExpectation(_MsgTok.NONE, - 'ERROR', - ((_MsgTok.ANY, 'set_db_attr:connection_state'),)), - _MsgParseExpectation((_MsgTok.NICK_USER_HOST, 'set_me_attr:nickuserhost'), - 'MODE', - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - (_MsgTok.ANY, 'set_db_attr:user_modes'))), - _MsgParseExpectation(_MsgTok.NICKNAME, - 'MODE', - ((_MsgTok.NICKNAME, 'set_me_attr:nick'), - (_MsgTok.ANY, 'set_db_attr:user_modes'))), - _MsgParseExpectation(_MsgTok.NONE, - 'PING', - ((_MsgTok.ANY, ':reply'),)), - _MsgParseExpectation((_MsgTok.NICK_USER_HOST, ':quitter'), - 'QUIT', - ((_MsgTok.ANY, ':message'),)), -] - - def _nick_incremented(nickname: str) -> str: 'Return nickname with number suffix incremented, or "0" if none.' name, digits = ([(nickname, '')] @@ -944,7 +627,7 @@ class Client(ABC, ClientQueueMixin): tok_type = (str | _NickUserHost | tuple[str, ...] | dict[str, str | _Channel]) - def param_match(ex_tok: str | _MsgTok, msg_tok: str | list[str] + def param_match(ex_tok: str | MsgTok, msg_tok: str | list[str] ) -> Optional[tok_type | tuple[tok_type, ...]]: if isinstance(msg_tok, list): to_return = [] @@ -956,28 +639,28 @@ class Client(ABC, ClientQueueMixin): return tuple(to_return) if isinstance(ex_tok, str): return msg_tok if msg_tok == ex_tok else None - if ex_tok is _MsgTok.NONE: + if ex_tok is MsgTok.NONE: return msg_tok if msg_tok == '' else None - if ex_tok is _MsgTok.SERVER: + if ex_tok is MsgTok.SERVER: return msg_tok if ('.' in msg_tok and not set('@!') & set(msg_tok)) else None - if ex_tok is _MsgTok.CHANNEL: + if ex_tok is MsgTok.CHANNEL: return {'id': msg_tok, 'db': self._db.channels[msg_tok] } if self._db.is_chan_name(msg_tok) else None - if ex_tok is _MsgTok.NICKNAME: + if ex_tok is MsgTok.NICKNAME: return (msg_tok if msg_tok[0] not in self._db.illegal_nick_firstchars else None) - if ex_tok is _MsgTok.NICK_USER_HOST: + if ex_tok is MsgTok.NICK_USER_HOST: try: return _NickUserHost.from_str(msg_tok) except AssertionError: return None - if ex_tok is _MsgTok.LIST: + if ex_tok is MsgTok.LIST: return tuple(msg_tok.split()) return msg_tok - for ex in [ex for ex in _EXPECTATIONS if ex.verb == msg.verb]: + for ex in [ex for ex in MSG_EXPECTATIONS if ex.verb == msg.verb]: tasks: dict[str, list[str]] = {} to_return: dict[str, Any] = {'verb': ex.verb, '_tasks': tasks} ex_tok_fields = tuple([ex.source] + list(ex.params)) diff --git a/ircplom/msg_parse_expectations.py b/ircplom/msg_parse_expectations.py new file mode 100644 index 0000000..0f2e26a --- /dev/null +++ b/ircplom/msg_parse_expectations.py @@ -0,0 +1,322 @@ +'Structured expectations and processing hints for server messages.' +from enum import Enum, auto +from typing import NamedTuple + + +class MsgTok(Enum): + 'Server message token classifications.' + ANY = auto() + CHANNEL = auto() + LIST = auto() + NICKNAME = auto() + NONE = auto() + SERVER = auto() + NICK_USER_HOST = auto() + + +_MsgTokGuide = str | MsgTok | tuple[str | MsgTok, str] + + +class _MsgParseExpectation(NamedTuple): + source: _MsgTokGuide + verb: str + params: tuple[_MsgTokGuide, ...] = tuple() + idx_into_list: int = -1 + + +MSG_EXPECTATIONS: list[_MsgParseExpectation] = [] + +# these we ignore except for confirming/collecting the nickname +MSG_EXPECTATIONS += [ + _MsgParseExpectation(MsgTok.SERVER, + '001', # RPL_WELCOME + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + MsgTok.ANY)), + _MsgParseExpectation(MsgTok.SERVER, + '002', # RPL_YOURHOST + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + MsgTok.ANY)), + _MsgParseExpectation(MsgTok.SERVER, + '003', # RPL_CREATED + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + MsgTok.ANY)), + _MsgParseExpectation(MsgTok.SERVER, + '004', # RPL_MYINFO + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + MsgTok.ANY, + MsgTok.ANY, + MsgTok.ANY, + MsgTok.ANY, + MsgTok.ANY)), + _MsgParseExpectation(MsgTok.SERVER, + '250', # RPL_STATSDLINE / RPL_STATSCONN + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + MsgTok.ANY)), + _MsgParseExpectation(MsgTok.SERVER, + '251', # RPL_LUSERCLIENT + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + MsgTok.ANY)), + _MsgParseExpectation(MsgTok.SERVER, + '252', # RPL_LUSEROP + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + MsgTok.ANY, + MsgTok.ANY)), + _MsgParseExpectation(MsgTok.SERVER, + '253', # RPL_LUSERUNKNOWN + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + MsgTok.ANY, + MsgTok.ANY)), + _MsgParseExpectation(MsgTok.SERVER, + '254', # RPL_LUSERCHANNELS + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + MsgTok.ANY, + MsgTok.ANY)), + _MsgParseExpectation(MsgTok.SERVER, + '255', # RPL_LUSERME + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + MsgTok.ANY)), + _MsgParseExpectation(MsgTok.SERVER, + '265', # RPL_LOCALUSERS + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + MsgTok.ANY)), + _MsgParseExpectation(MsgTok.SERVER, + '265', # RPL_LOCALUSERS + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + MsgTok.ANY, + MsgTok.ANY, + MsgTok.ANY)), + _MsgParseExpectation(MsgTok.SERVER, + '266', # RPL_GLOBALUSERS + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + MsgTok.ANY)), + _MsgParseExpectation(MsgTok.SERVER, + '266', # RPL_GLOBALUSERS + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + MsgTok.ANY, + MsgTok.ANY, + MsgTok.ANY)), + _MsgParseExpectation(MsgTok.SERVER, + '375', # RPL_MOTDSTART already implied by 1st 372 + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + MsgTok.ANY)), +] + +# various login stuff +MSG_EXPECTATIONS += [ + _MsgParseExpectation(MsgTok.SERVER, + '005', # RPL_ISUPPORT + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + (MsgTok.ANY, ':isupport'), + MsgTok.ANY), # comment + idx_into_list=1), + _MsgParseExpectation(MsgTok.SERVER, + '372', # RPL_MOTD + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + (MsgTok.ANY, ':line'))), + _MsgParseExpectation(MsgTok.SERVER, + '376', # RPL_ENDOFMOTD + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + MsgTok.ANY)), # comment + _MsgParseExpectation(MsgTok.SERVER, + '396', # RPL_VISIBLEHOST + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + (MsgTok.SERVER, 'set_me_attr:host'), + MsgTok.ANY)), # comment +] + +# SASL +MSG_EXPECTATIONS += [ + _MsgParseExpectation(MsgTok.SERVER, + '900', # RPL_LOGGEDIN + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + (MsgTok.NICK_USER_HOST, 'set_me_attr:nickuserhost'), + (MsgTok.ANY, 'set_db_attr:sasl_account'), + MsgTok.ANY)), # comment + _MsgParseExpectation(MsgTok.SERVER, + '903', # RPL_SASLSUCCESS + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + (MsgTok.ANY, 'set_db_attr:sasl_auth_state'))), + _MsgParseExpectation(MsgTok.SERVER, + '904', # ERR_SASLFAIL + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + (MsgTok.ANY, 'set_db_attr:sasl_auth_state'))), + _MsgParseExpectation(MsgTok.NONE, + 'AUTHENTICATE', + ('+',)), +] + +# capability negotation +MSG_EXPECTATIONS += [ + _MsgParseExpectation(MsgTok.SERVER, + 'CAP', + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + ('NEW', ':subverb'), + (MsgTok.LIST, ':items'))), + _MsgParseExpectation(MsgTok.SERVER, + 'CAP', + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + ('DEL', ':subverb'), + (MsgTok.LIST, ':items'))), + _MsgParseExpectation(MsgTok.SERVER, + 'CAP', + ('*', + ('ACK', ':subverb'), + (MsgTok.LIST, ':items'))), + _MsgParseExpectation(MsgTok.SERVER, + 'CAP', + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + ('ACK', ':subverb'), + (MsgTok.LIST, ':items'))), + _MsgParseExpectation(MsgTok.SERVER, + 'CAP', + ('*', + ('NAK', ':subverb'), + (MsgTok.LIST, ':items'))), + _MsgParseExpectation(MsgTok.SERVER, + 'CAP', + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + ('NAK', ':subverb'), + (MsgTok.LIST, ':items'))), + _MsgParseExpectation(MsgTok.SERVER, + 'CAP', + ('*', + ('LS', ':subverb'), + (MsgTok.LIST, ':items'))), + _MsgParseExpectation(MsgTok.SERVER, + 'CAP', + ('*', + ('LS', ':subverb'), + ('*', ':tbc'), + (MsgTok.LIST, ':items'))), + _MsgParseExpectation(MsgTok.SERVER, + 'CAP', + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + ('LS', ':subverb'), + (MsgTok.LIST, ':items'))), + _MsgParseExpectation(MsgTok.SERVER, + 'CAP', + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + ('LS', ':subverb'), + ('*', ':tbc'), + (MsgTok.LIST, ':items'))), + + _MsgParseExpectation(MsgTok.SERVER, + 'CAP', + ('*', + ('LIST', ':subverb'), + (MsgTok.LIST, ':items'))), + _MsgParseExpectation(MsgTok.SERVER, + 'CAP', + ('*', + ('LIST', ':subverb'), + ('*', ':tbc'), + (MsgTok.LIST, ':items'))), + _MsgParseExpectation(MsgTok.SERVER, + 'CAP', + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + ('LIST', ':subverb'), + (MsgTok.LIST, ':items'))), + _MsgParseExpectation(MsgTok.SERVER, + 'CAP', + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + ('LIST', ':subverb'), + ('*', ':tbc'), + (MsgTok.LIST, ':items'))), +] + +# nickname management +MSG_EXPECTATIONS += [ + _MsgParseExpectation(MsgTok.SERVER, + '432', # ERR_ERRONEOUSNICKNAME + ('*', + MsgTok.NICKNAME, # no need to re-use the bad one + MsgTok.ANY)), # comment + _MsgParseExpectation(MsgTok.SERVER, + '432', # ERR_ERRONEOUSNICKNAME + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + MsgTok.NICKNAME, # no need to re-use the bad one + MsgTok.ANY)), # comment + _MsgParseExpectation(MsgTok.SERVER, + '433', # ERR_NICKNAMEINUSE + (MsgTok.NICKNAME, # we rather go for incrementation + (MsgTok.NICKNAME, ':used'), + MsgTok.ANY)), # comment + _MsgParseExpectation((MsgTok.NICK_USER_HOST, ':named'), + 'NICK', + ((MsgTok.NICKNAME, ':nick'),)), +] + +# joining/leaving +MSG_EXPECTATIONS += [ + _MsgParseExpectation(MsgTok.SERVER, + '353', # RPL_NAMREPLY + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + '=', + (MsgTok.CHANNEL, ':channel'), + (MsgTok.LIST, ':names'))), + _MsgParseExpectation(MsgTok.SERVER, + '366', # RPL_ENDOFNAMES + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + (MsgTok.CHANNEL, ':channel'), + MsgTok.ANY)), # comment + _MsgParseExpectation((MsgTok.NICK_USER_HOST, ':joiner'), + 'JOIN', + ((MsgTok.CHANNEL, ':channel'),)), + _MsgParseExpectation((MsgTok.NICK_USER_HOST, ':parter'), + 'PART', + ((MsgTok.CHANNEL, ':channel'),)), +] + +# messaging +MSG_EXPECTATIONS += [ + _MsgParseExpectation(MsgTok.SERVER, + '401', # ERR_NOSUCKNICK + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + (MsgTok.NICKNAME, ':target'), + MsgTok.ANY)), # comment + _MsgParseExpectation(MsgTok.SERVER, + 'NOTICE', + ('*', + (MsgTok.ANY, ':message'))), + _MsgParseExpectation(MsgTok.SERVER, + 'NOTICE', + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + (MsgTok.ANY, ':message'))), + _MsgParseExpectation((MsgTok.NICK_USER_HOST, 'set_user:sender'), + 'NOTICE', + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + (MsgTok.ANY, ':message'))), + _MsgParseExpectation((MsgTok.NICK_USER_HOST, 'set_user:sender'), + 'NOTICE', + ((MsgTok.CHANNEL, ':channel'), + (MsgTok.ANY, ':message'))), + _MsgParseExpectation((MsgTok.NICK_USER_HOST, 'set_user:sender'), + 'PRIVMSG', + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + (MsgTok.ANY, ':message'))), + _MsgParseExpectation((MsgTok.NICK_USER_HOST, 'set_user:sender'), + 'PRIVMSG', + ((MsgTok.CHANNEL, ':channel'), + (MsgTok.ANY, ':message'))), +] + +# misc. +MSG_EXPECTATIONS += [ + _MsgParseExpectation(MsgTok.NONE, + 'ERROR', + ((MsgTok.ANY, 'set_db_attr:connection_state'),)), + _MsgParseExpectation((MsgTok.NICK_USER_HOST, 'set_me_attr:nickuserhost'), + 'MODE', + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + (MsgTok.ANY, 'set_db_attr:user_modes'))), + _MsgParseExpectation(MsgTok.NICKNAME, + 'MODE', + ((MsgTok.NICKNAME, 'set_me_attr:nick'), + (MsgTok.ANY, 'set_db_attr:user_modes'))), + _MsgParseExpectation(MsgTok.NONE, + 'PING', + ((MsgTok.ANY, ':reply'),)), + _MsgParseExpectation((MsgTok.NICK_USER_HOST, ':quitter'), + 'QUIT', + ((MsgTok.ANY, ':message'),)), +]