SERVER = auto()
+class _MsgParam(Enum):
+ ANY = auto()
+ CHANNEL = auto()
+
+
class _MsgParseExpectation(NamedTuple):
verb: str
len_min_params: int = 0
len_max_params: int = 0
- params: tuple[str, ...] = tuple()
+ params: tuple[str | _MsgParam, ...] = tuple()
source: Optional[_MsgSource] = None
_MsgParseExpectation('904', 2, source=_MsgSource.SERVER),
_MsgParseExpectation('AUTHENTICATE', params=('+',), source=_MsgSource.NONE),
_MsgParseExpectation('CAP', 3, 15, source=_MsgSource.SERVER),
- _MsgParseExpectation('ERROR', 1, source=_MsgSource.NONE),
- _MsgParseExpectation('JOIN', 1, source=_MsgSource.USER_ADDRESS),
+ _MsgParseExpectation('ERROR', params=(_MsgParam.ANY,),
+ source=_MsgSource.NONE),
+ _MsgParseExpectation('JOIN', params=(_MsgParam.CHANNEL,),
+ source=_MsgSource.USER_ADDRESS),
_MsgParseExpectation('MODE', 2, source=_MsgSource.USER_ADDRESS),
_MsgParseExpectation('NICK', 1, source=_MsgSource.USER_ADDRESS),
_MsgParseExpectation('NOTICE', 2, source=_MsgSource.USER_ADDRESS),
_MsgParseExpectation('NOTICE', 2, source=_MsgSource.SERVER),
- _MsgParseExpectation('PART', 1, 2, source=_MsgSource.USER_ADDRESS),
- _MsgParseExpectation('PING', 1, source=_MsgSource.NONE),
+ _MsgParseExpectation('PART', params=(_MsgParam.CHANNEL,),
+ source=_MsgSource.USER_ADDRESS),
+ _MsgParseExpectation('PART', params=(_MsgParam.CHANNEL, _MsgParam.ANY),
+ source=_MsgSource.USER_ADDRESS),
+ _MsgParseExpectation('PING', params=(_MsgParam.ANY,),
+ source=_MsgSource.NONE),
_MsgParseExpectation('PRIVMSG', 2, source=_MsgSource.USER_ADDRESS),
_MsgParseExpectation('PRIVMSG', 2, source=_MsgSource.SERVER),
- _MsgParseExpectation('QUIT', 1, source=_MsgSource.USER_ADDRESS),
+ _MsgParseExpectation('QUIT', params=(_MsgParam.ANY,),
+ source=_MsgSource.USER_ADDRESS),
)
def _match_msg(self, msg: _IrcMsg, verb: str):
'Test .source, .verb, .params.'
- to_return: dict[str, Optional[str]] = {'_': None}
- if not msg.verb == verb:
- return False
- for expect in [x for x in _EXPECTATIONS if x.verb == msg.verb]:
+ for expect in [x for x in _EXPECTATIONS if verb == x.verb == msg.verb]:
+ to_return: dict[str, Any] = {'params': []}
if expect.source is _MsgSource.NONE:
if msg.source != '':
continue
if len(toks) != 3:
continue
to_return['nickname'] = toks[0]
- if expect.params and msg.params != expect.params:
- continue
n_len_params = len(msg.params)
- if expect.len_max_params:
+ if expect.params:
+ if n_len_params != len(expect.params):
+ continue
+ for idx, exp_param in enumerate(expect.params):
+ param = msg.params[idx]
+ if isinstance(exp_param, str) and exp_param != param:
+ continue
+ if exp_param is _MsgParam.CHANNEL:
+ if param[0] != '#':
+ continue
+ to_return['ch_name'] = param
+ to_return['channel'] = self._db.chan(param)
+ if exp_param is _MsgParam.ANY:
+ to_return['params'] += [param]
+ elif expect.len_max_params:
if not (expect.len_min_params <= n_len_params
<= expect.len_max_params):
continue
elif self._match_msg(msg, 'ERROR'):
self.close()
elif (ret := self._match_msg(msg, 'JOIN')):
- channel = msg.params[0]
- log_msg = f'{ret["nickname"]} {msg.verb.lower()}s {channel}'
- self._log(log_msg, scope=LogScope.CHAT, target=channel)
+ log_msg = f'{ret["nickname"]} {msg.verb.lower()}s {ret["ch_name"]}'
+ self._log(log_msg, scope=LogScope.CHAT, target=ret['ch_name'])
if ret['nickname'] != self._db.nickname:
- self._db.chan(channel).append_completable(
- 'users', ret['nickname'], stay_complete=True)
+ ret['channel'].append_completable('users', ret['nickname'],
+ stay_complete=True)
elif self._match_msg(msg, 'MODE')\
and msg.params[0] == self._db.nickname:
self._db.user_modes = msg.params[1]
} if 'nickname' in ret else {}
self._log(msg.params[-1], out=False, target=msg.params[0], **kw)
elif (ret := self._match_msg(msg, 'PART')):
- channel = msg.params[0]
- log_msg = f'{ret["nickname"]} {msg.verb.lower()}s {channel}'
- if len(msg.params) == 2:
- log_msg += f': {msg.params[1]}'
- self._log(log_msg, scope=LogScope.CHAT, target=channel)
+ log_msg = f'{ret["nickname"]} {msg.verb.lower()}s {ret["ch_name"]}'
+ if len(ret['params']):
+ log_msg += f': {ret["params"][0]}'
+ self._log(log_msg, scope=LogScope.CHAT, target=ret['ch_name'])
if ret['nickname'] == self._db.nickname:
- self._db.del_chan(channel)
+ self._db.del_chan(ret['ch_name'])
else:
- self._db.chan(channel).remove_completable(
- 'users', ret['nickname'], stay_complete=True)
- elif self._match_msg(msg, 'PING'):
- self.send(IrcMessage(verb='PONG', params=(msg.params[0],)))
+ ret['channel'].remove_completable('users', ret['nickname'],
+ stay_complete=True)
+ elif (ret := self._match_msg(msg, 'PING')):
+ self.send(IrcMessage(verb='PONG', params=tuple(ret['params'])))
elif (ret := self._match_msg(msg, 'QUIT')):
for chan_name in self._db.chan_names:
chan = self._db.chan(chan_name)
if ret['nickname'] in chan.users:
chan.remove_completable('users', ret['nickname'],
stay_complete=True)
- self._log(f'{ret["nickname"]} quits: {msg.params[0]}',
+ self._log(f'{ret["nickname"]} quits: {ret["params"][0]}',
scope=LogScope.CHAT, target=chan_name)
else:
self._log(f'PLEASE IMPLEMENT HANDLER FOR: {msg.raw}')