ClientsDb = dict[str, 'Client']
_NAMES_DESIRED_SERVER_CAPS = ('sasl',)
-# NB: in below numerics accounting, tuples define inclusive ranges
-_NUMERICS_TO_CONFIRM_NICKNAME = (
- (1, 5),
- (251, 255),
- (265, 266),
- 353,
- 366,
- 372,
- (375, 376),
- 396,
- 401,
- 900,
- 903,
- 904
-)
-_NUMERICS_TO_IGNORE = (
- (1, 4), # nothing in this login info we're interested in
- (250, 255), # same
- (265, 266), # same
- 375, # RPL_MOTDSTART already implied to us by first appearance of 372
-)
-
class _MsgTok(Enum):
ANY = auto()
idx_into_list: int = -1
-_EXPECTATIONS: tuple[_MsgParseExpectation, ...] = (
+_EXPECTATIONS: list[_MsgParseExpectation] = []
+# these we ignore except for confirming/collecting the nickname
+_EXPECTATIONS += [
_MsgParseExpectation(_MsgTok.SERVER,
- '005',
- (_MsgTok.NICKNAME,
- (_MsgTok.ANY, 'isupports'),
- _MsgTok.ANY),
- idx_into_list=1),
-
+ '001',
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ _MsgTok.ANY)),
_MsgParseExpectation(_MsgTok.SERVER,
- '353',
- (_MsgTok.NICKNAME,
- '=',
- (_MsgTok.CHANNEL, 'channel'),
- (_MsgTok.LIST, 'names'))),
+ '002',
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ _MsgTok.ANY)),
_MsgParseExpectation(_MsgTok.SERVER,
- '366',
- (_MsgTok.NICKNAME,
- (_MsgTok.CHANNEL, 'channel'),
+ '003',
+ ((_MsgTok.NICKNAME, 'my_nickname'),
_MsgTok.ANY)),
-
_MsgParseExpectation(_MsgTok.SERVER,
- '372',
- (_MsgTok.NICKNAME,
- (_MsgTok.ANY, 'line'))),
+ '004',
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ _MsgTok.ANY,
+ _MsgTok.ANY,
+ _MsgTok.ANY,
+ _MsgTok.ANY,
+ _MsgTok.ANY)),
_MsgParseExpectation(_MsgTok.SERVER,
- '376',
- (_MsgTok.NICKNAME,
+ '250',
+ ((_MsgTok.NICKNAME, 'my_nickname'),
_MsgTok.ANY)),
-
- _MsgParseExpectation(_MsgTok.SERVER, '396',
- (_MsgTok.NICKNAME,
- (_MsgTok.ANY, 'host_maybe_w_user'),
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '251',
+ ((_MsgTok.NICKNAME, 'my_nickname'),
_MsgTok.ANY)),
-
_MsgParseExpectation(_MsgTok.SERVER,
- '401',
- (_MsgTok.NICKNAME,
- (_MsgTok.NICKNAME, 'target'),
+ '252',
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ _MsgTok.ANY,
_MsgTok.ANY)),
-
_MsgParseExpectation(_MsgTok.SERVER,
- '432',
- ('*',
- _MsgTok.NICKNAME,
+ '253',
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ _MsgTok.ANY,
_MsgTok.ANY)),
_MsgParseExpectation(_MsgTok.SERVER,
- '432',
- ((_MsgTok.NICKNAME, 'fallback'),
- _MsgTok.NICKNAME,
+ '254',
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ _MsgTok.ANY,
+ _MsgTok.ANY)),
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '255',
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ _MsgTok.ANY)),
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '265',
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ _MsgTok.ANY)),
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '265',
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ _MsgTok.ANY,
+ _MsgTok.ANY,
+ _MsgTok.ANY)),
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '266',
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ _MsgTok.ANY)),
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '266',
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ _MsgTok.ANY,
+ _MsgTok.ANY,
_MsgTok.ANY)),
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '375', # RPL_MOTDSTART already implied by 1st 372
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ _MsgTok.ANY)),
+]
+# various login stuff
+_EXPECTATIONS += [
_MsgParseExpectation(_MsgTok.SERVER,
- '433',
- (_MsgTok.NICKNAME,
- _MsgTok.NICKNAME,
+ '005', # RPL_ISUPPORT
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ (_MsgTok.ANY, 'isupports'),
+ _MsgTok.ANY),
+ idx_into_list=1),
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '372', # RPL_MOTD
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ (_MsgTok.ANY, 'line'))),
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '376', # RPL_ENDOFMOTD
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ _MsgTok.ANY)),
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '396', # RPL_VISIBLEHOST
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ (_MsgTok.ANY, 'host_maybe_w_user'),
_MsgTok.ANY)),
+]
+# SASL
+_EXPECTATIONS += [
_MsgParseExpectation(_MsgTok.SERVER,
- '900',
- (_MsgTok.NICKNAME,
+ '900', # RPL_LOGGEDIN
+ ((_MsgTok.NICKNAME, 'my_nickname'),
(_MsgTok.USER_ADDRESS, 'full_address'),
(_MsgTok.ANY, 'account'),
_MsgTok.ANY)),
_MsgParseExpectation(_MsgTok.SERVER,
- '903',
- (_MsgTok.NICKNAME,
+ '903', # RPL_SASLSUCCESS
+ ((_MsgTok.NICKNAME, 'my_nickname'),
(_MsgTok.ANY, 'result'))),
_MsgParseExpectation(_MsgTok.SERVER,
- '904',
- (_MsgTok.NICKNAME,
+ '904', # ERR_SASLFAIL
+ ((_MsgTok.NICKNAME, 'my_nickname'),
(_MsgTok.ANY, 'result'))),
-
_MsgParseExpectation(_MsgTok.NONE,
'AUTHENTICATE',
('+',)),
+]
+# capability negotation
+_EXPECTATIONS += [
_MsgParseExpectation(_MsgTok.SERVER,
'CAP',
- (_MsgTok.NICKNAME,
- ('NEW', 'verb'),
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ ('NEW', 'subverb'),
(_MsgTok.LIST, 'items'))),
_MsgParseExpectation(_MsgTok.SERVER,
'CAP',
- (_MsgTok.NICKNAME,
- ('DEL', 'verb'),
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ ('DEL', 'subverb'),
(_MsgTok.LIST, 'items'))),
_MsgParseExpectation(_MsgTok.SERVER,
'CAP',
- (_MsgTok.NICKNAME,
- ('ACK', 'verb'),
+ ('*',
+ ('ACK', 'subverb'),
(_MsgTok.LIST, 'items'))),
_MsgParseExpectation(_MsgTok.SERVER,
'CAP',
- (_MsgTok.NICKNAME,
- ('NAK', 'verb'),
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ ('ACK', 'subverb'),
(_MsgTok.LIST, 'items'))),
_MsgParseExpectation(_MsgTok.SERVER,
'CAP',
('*',
- ('LS', 'verb'),
- ('*', 'tbc'),
+ ('NAK', 'subverb'),
(_MsgTok.LIST, 'items'))),
_MsgParseExpectation(_MsgTok.SERVER,
'CAP',
- (_MsgTok.NICKNAME,
- ('LS', 'verb'),
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ ('NAK', 'subverb'),
(_MsgTok.LIST, 'items'))),
_MsgParseExpectation(_MsgTok.SERVER,
'CAP',
- (_MsgTok.NICKNAME,
+ ('*',
+ ('LS', 'subverb'),
+ (_MsgTok.LIST, 'items'))),
+ _MsgParseExpectation(_MsgTok.SERVER,
+ 'CAP',
+ ('*',
+ ('LS', 'subverb'),
('*', 'tbc'),
- ('LIST', 'verb'),
(_MsgTok.LIST, 'items'))),
_MsgParseExpectation(_MsgTok.SERVER,
'CAP',
- (_MsgTok.NICKNAME,
- ('LIST', 'verb'),
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ ('LS', 'subverb'),
+ (_MsgTok.LIST, 'items'))),
+ _MsgParseExpectation(_MsgTok.SERVER,
+ 'CAP',
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ ('LS', 'subverb'),
+ ('*', 'tbc'),
(_MsgTok.LIST, 'items'))),
- _MsgParseExpectation(_MsgTok.NONE,
- 'ERROR',
- ((_MsgTok.ANY, 'reason'),)),
-
- _MsgParseExpectation((_MsgTok.USER_ADDRESS, 'joiner'),
- 'JOIN',
- ((_MsgTok.CHANNEL, 'channel'),)),
+ _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, 'my_nickname'),
+ ('LIST', 'subverb'),
+ (_MsgTok.LIST, 'items'))),
+ _MsgParseExpectation(_MsgTok.SERVER,
+ 'CAP',
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ ('LIST', 'subverb'),
+ ('*', 'tbc'),
+ (_MsgTok.LIST, 'items'))),
+]
- _MsgParseExpectation(_MsgTok.NICKNAME,
- 'MODE',
- (_MsgTok.NICKNAME,
- (_MsgTok.ANY, 'mode'))),
- _MsgParseExpectation(_MsgTok.USER_ADDRESS,
- 'MODE',
+# nickname management
+_EXPECTATIONS += [
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '432', # ERR_ERRONEOUSNICKNAME
+ ('*',
+ _MsgTok.NICKNAME,
+ _MsgTok.ANY)),
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '432', # ERR_ERRONEOUSNICKNAME
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ _MsgTok.NICKNAME,
+ _MsgTok.ANY)),
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '433', # ERR_NICKNAMEINUSE
(_MsgTok.NICKNAME,
- (_MsgTok.ANY, 'mode'))),
-
+ _MsgTok.NICKNAME,
+ _MsgTok.ANY)),
_MsgParseExpectation((_MsgTok.USER_ADDRESS, 'named'),
'NICK',
((_MsgTok.NICKNAME, 'nickname'),)),
+]
+# joining/leaving
+_EXPECTATIONS += [
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '353', # RPL_NAMREPLY
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ '=',
+ (_MsgTok.CHANNEL, 'channel'),
+ (_MsgTok.LIST, 'names'))),
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '366', # RPL_ENDOFNAMES
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ (_MsgTok.CHANNEL, 'channel'),
+ _MsgTok.ANY)),
+ _MsgParseExpectation((_MsgTok.USER_ADDRESS, 'joiner'),
+ 'JOIN',
+ ((_MsgTok.CHANNEL, 'channel'),)),
+ _MsgParseExpectation((_MsgTok.USER_ADDRESS, 'parter'),
+ 'PART',
+ ((_MsgTok.CHANNEL, 'channel'),)),
+ _MsgParseExpectation((_MsgTok.USER_ADDRESS, 'parter'),
+ 'PART',
+ ((_MsgTok.CHANNEL, 'channel'),
+ (_MsgTok.ANY, 'reason'))),
+]
+
+# messaging
+_EXPECTATIONS += [
+ _MsgParseExpectation(_MsgTok.SERVER,
+ '401', # ERR_NOSUCKNICK
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ (_MsgTok.NICKNAME, 'target'),
+ _MsgTok.ANY)),
_MsgParseExpectation(_MsgTok.SERVER,
'NOTICE',
('*',
(_MsgTok.ANY, 'message'))),
_MsgParseExpectation(_MsgTok.SERVER,
'NOTICE',
- ((_MsgTok.NICKNAME, 'nickname'),
+ ((_MsgTok.NICKNAME, 'my_nickname'),
(_MsgTok.ANY, 'message'))),
_MsgParseExpectation((_MsgTok.USER_ADDRESS, 'sender'),
'NOTICE',
- ((_MsgTok.NICKNAME, 'nickname'),
+ ((_MsgTok.NICKNAME, 'my_nickname'),
(_MsgTok.ANY, 'message'))),
_MsgParseExpectation((_MsgTok.USER_ADDRESS, 'sender'),
'NOTICE',
((_MsgTok.CHANNEL, 'channel'),
(_MsgTok.ANY, 'message'))),
-
- _MsgParseExpectation((_MsgTok.USER_ADDRESS, 'parter'),
- 'PART',
- ((_MsgTok.CHANNEL, 'channel'),)),
- _MsgParseExpectation((_MsgTok.USER_ADDRESS, 'parter'),
- 'PART',
- ((_MsgTok.CHANNEL, 'channel'),
- (_MsgTok.ANY, 'reason'))),
-
- _MsgParseExpectation(_MsgTok.NONE,
- 'PING',
- ((_MsgTok.ANY, 'reply'),)),
-
_MsgParseExpectation((_MsgTok.USER_ADDRESS, 'sender'),
'PRIVMSG',
- ((_MsgTok.NICKNAME, 'nickname'),
+ ((_MsgTok.NICKNAME, 'my_nickname'),
(_MsgTok.ANY, 'message'))),
_MsgParseExpectation((_MsgTok.USER_ADDRESS, 'sender'),
'PRIVMSG',
((_MsgTok.CHANNEL, 'channel'),
(_MsgTok.ANY, 'message'))),
+]
+# misc.
+_EXPECTATIONS += [
+ _MsgParseExpectation(_MsgTok.NONE,
+ 'ERROR',
+ ((_MsgTok.ANY, 'reason'),)),
+ _MsgParseExpectation(_MsgTok.NICKNAME,
+ 'MODE',
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ (_MsgTok.ANY, 'mode'))),
+ _MsgParseExpectation(_MsgTok.USER_ADDRESS,
+ 'MODE',
+ ((_MsgTok.NICKNAME, 'my_nickname'),
+ (_MsgTok.ANY, 'mode'))),
+ _MsgParseExpectation(_MsgTok.NONE,
+ 'PING',
+ ((_MsgTok.ANY, 'reply'),)),
_MsgParseExpectation((_MsgTok.USER_ADDRESS, 'quitter'),
'QUIT',
((_MsgTok.ANY, 'message'),)),
-)
+]
class LogScope(Enum):
SAME = auto()
-class _Numerics:
-
- def __init__(self, numerics: tuple[int | tuple[int, int], ...]) -> None:
- as_ints = []
- for item in numerics:
- as_ints += ([item] if isinstance(item, int)
- else list(range(item[0], item[1] + 1)))
- self._numerics = tuple(as_ints)
-
- def contain(self, msg_verb: str) -> bool:
- 'Is int(msg_verb) within the listed numbers?'
- return msg_verb.isdigit() and int(msg_verb) in self._numerics
-
-
-_NumericsToIgnore = _Numerics(_NUMERICS_TO_IGNORE)
-_NumericsToConfirmNickname = _Numerics(_NUMERICS_TO_CONFIRM_NICKNAME)
-
-
@dataclass
class ClientIdMixin:
'Collects a Client\'s ID at .client_id.'
self._log(f'connection broken: {e}', alert=True)
self.close()
- def _match_msg(self, msg: IrcMessage, verb: str):
+ def _match_msg(self, msg: IrcMessage) -> dict[str, Any]:
'Test .source, .verb, .params.'
tok_type = str | tuple[str, ...] | dict[str, str | _ChannelDb]
return tuple(msg_tok.split())
return msg_tok
- for ex in [ex for ex in _EXPECTATIONS if verb == ex.verb == msg.verb]:
- to_return: dict[str, Any] = {'': ''} # non-emtpy so boolish True
+ for ex in [ex for ex in _EXPECTATIONS if ex.verb == msg.verb]:
+ to_return: dict[str, Any] = {'verb': ex.verb}
ex_tok_fields = tuple([ex.source] + list(ex.params))
msg_params: list[str | list[str]]
if ex.idx_into_list < 0:
msg_tok_fields = tuple([msg.source] + msg_params)
if ex.params and len(ex_tok_fields) != len(msg_tok_fields):
continue
- passing = False
+ passing = True
for idx, ex_tok in enumerate(ex_tok_fields):
ex_tok, key = ((ex_tok[0], ex_tok[1])
if isinstance(ex_tok, tuple) else (ex_tok, ''))
to_return[key] = param_match(ex_tok, msg_tok_fields[idx])
if to_return[key] is None:
+ passing = False
break
- passing = True
if passing:
return to_return
- return False
+ return {}
def handle_msg(self, msg: IrcMessage) -> None:
'Log msg.raw, then process incoming msg into appropriate client steps.'
self._log(msg.raw, scope=LogScope.RAW, out=False)
- if _NumericsToConfirmNickname.contain(msg.verb):
- self.set_nick(msg.params[0], confirmed=True)
- if _NumericsToIgnore.contain(msg.verb):
- return
-
- if (ret := self._match_msg(msg, '005')): # RPL_ISUPPORT
+ ret = self._match_msg(msg)
+ if 'my_nickname' in ret:
+ self.set_nick(ret['my_nickname'], confirmed=True)
+ if 'verb' not in ret:
+ self._log(f'PLEASE IMPLEMENT HANDLER FOR: {msg.raw}')
+ elif ret['verb'] == '005': # RPL_ISUPPORT
for item in ret['isupports']:
toks = item.split('=', maxsplit=1)
if toks[0][0] == '-':
else:
self._db.isupports[toks[0]] = (toks[1] if len(toks) > 1
else '')
-
- elif (ret := self._match_msg(msg, '353')): # RPL_NAMREPLY
+ elif ret['verb'] == '353': # RPL_NAMREPLY
for name in ret['names']:
ret['channel']['db'].append_completable('users',
name.lstrip('~&@%+'))
- elif (ret := self._match_msg(msg, '366')): # RPL_ENDOFNAMES
+ elif ret['verb'] == '366': # RPL_ENDOFNAMES
ret['channel']['db'].declare_complete('users')
-
- elif (ret := self._match_msg(msg, '372')): # RPL_MOTD
+ elif ret['verb'] == '372': # RPL_MOTD
self._db.append_completable('motd', ret['line'])
- elif self._match_msg(msg, '376'): # RPL_ENDOFMOTD
+ elif ret['verb'] == '376': # RPL_ENDOFMOTD
self._db.declare_complete('motd')
-
- elif (ret := self._match_msg(msg, '396')): # RPL_VISIBLEHOST
+ elif ret['verb'] == '396': # RPL_VISIBLEHOST
# '@'-split because <https://defs.ircdocs.horse/defs/numerics>
# claims: "<hostname> can also be in the form <user@hostname>"
self._db.client_host = ret['host_maybe_w_user'].split('@')[-1]
-
- elif (ret := self._match_msg(msg, '401')): # ERR_NOSUCHNICK
+ elif ret['verb'] == '401': # ERR_NOSUCHNICK
self._log(f'{ret["target"]} not online', scope=LogScope.CHAT,
target=ret['target'], alert=True)
-
- elif (ret := self._match_msg(msg, '432')): # ERR_ERRONEOUSNICKNAME
+ elif ret['verb'] == '432': # ERR_ERRONEOUSNICKNAME
alert = 'nickname refused for bad format'
- if 'fallback' in ret:
- self.set_nick(ret['fallback'], confirmed=True)
- else:
+ if 'my_nickname' not in ret:
alert += ', giving up'
self.close()
self._log(alert, alert=True)
-
- elif self._match_msg(msg, '433'): # ERR_NICKNAMEINUSE
+ elif ret['verb'] == '433': # ERR_NICKNAMEINUSE
self._log('nickname already in use, trying increment', alert=True)
self.set_nick(self._db.nick_incremented)
-
- elif (ret := self._match_msg(msg, '900')): # RPL_LOGGEDIN
+ elif ret['verb'] == '900': # RPL_LOGGEDIN
self.set_nick(ret['full_address'][0], True)
self._db.username, self._db.client_host = ret['full_address'][1:]
self._db.sasl_account = ret['account']
- elif ((ret := self._match_msg(msg, '903')) # RPL_SASLSUCCESS
- or (ret := self._match_msg(msg, '904'))): # ERR_SASLFAIL
+ elif ret['verb'] in {'903', '904'}: # RPL_SASLSUCCESS, ERR_SASLFAIL
self._db.sasl_auth_state = ret['result']
self._caps.end_negotiation()
-
- elif self._match_msg(msg, 'AUTHENTICATE'):
+ elif ret['verb'] == 'AUTHENTICATE':
auth = b64encode((self._db.nick_wanted + '\0'
+ self._db.nick_wanted + '\0'
+ self._db.password
).encode('utf-8')).decode('utf-8')
self.send(IrcMessage('AUTHENTICATE', (auth,)))
-
- elif (ret := self._match_msg(msg, 'CAP')):
- if (self._caps.process_msg(ret['verb'], ret['items'], 'tbc' in ret)
+ elif ret['verb'] == 'CAP':
+ if (self._caps.process_msg(verb=ret['subverb'], items=ret['items'],
+ incomplete='tbc' in ret)
and self._db.caps.has('sasl')
and 'PLAIN' in self._db.caps['sasl'].data.split(',')):
if self._db.password:
self.send(IrcMessage('AUTHENTICATE', ('PLAIN',)))
else:
self._caps.end_negotiation()
-
- elif (ret := self._match_msg(msg, 'ERROR')):
+ elif ret['verb'] == 'ERROR':
self._db.connection_state = ret['reason']
self.close()
-
- elif (ret := self._match_msg(msg, 'JOIN')):
+ elif ret['verb'] == 'JOIN':
self._log(f'{ret["joiner"][0]} {msg.verb.lower()}s '
+ f'{ret["channel"]["id"]}',
scope=LogScope.CHAT, target=ret['channel']['id'])
if ret['joiner'][0] != self._db.nickname:
ret['channel']['db'].append_completable('users',
ret['joiner'][0], True)
-
- elif (ret := self._match_msg(msg, 'MODE')):
+ elif ret['verb'] == 'MODE':
self._db.user_modes = ret['mode']
-
- elif (ret := self._match_msg(msg, 'NICK')):
+ elif ret['verb'] == 'NICK':
if ret['named'][0] == self._db.nickname:
self.set_nick(ret['nickname'], confirmed=True)
else:
ch.append_completable('users', ret['nickname'], True)
self._log(f'{ret["named"][0]} becomes {ret["nickname"]}',
scope=LogScope.CHAT, target=id_)
-
- elif (ret := self._match_msg(msg, 'NOTICE'))\
- or (ret := self._match_msg(msg, 'PRIVMSG')):
- if 'nickname' in ret:
- self.set_nick(ret['nickname'], confirmed=True)
+ elif ret['verb'] in {'NOTICE', 'PRIVMSG'}:
kw: dict[str, bool | str | LogScope] = {
'as_notice': msg.verb == 'NOTICE'}
if 'sender' in ret: # not just server message
kw |= {'sender': ret['sender'][0], 'scope': LogScope.CHAT,
- 'target': (ret['sender'][0] if 'nickname' in ret
+ 'target': (ret['sender'][0] if 'my_nickname' in ret
else ret['channel']['id'])}
self._log(ret['message'], out=False, **kw)
-
- elif (ret := self._match_msg(msg, 'PART')):
+ elif ret['verb'] == 'PART':
reason = f': {ret["reason"]}' if 'reason' in ret else ''
self._log(f'{ret["parter"][0]} {msg.verb.lower()}s '
+ f'{ret["channel"]["id"]}{reason}',
else:
ret['channel']['db'].remove_completable('users',
ret['parter'][0], True)
-
- elif (ret := self._match_msg(msg, 'PING')):
+ elif ret['verb'] == 'PING':
self.send(IrcMessage(verb='PONG', params=(ret['reply'],)))
-
- elif (ret := self._match_msg(msg, 'QUIT')):
+ elif ret['verb'] == 'QUIT':
for id_, chan in self._db.chans_of_user(ret['quitter'][0]).items():
chan.remove_completable('users', ret['quitter'][0], True)
self._log(f'{ret["quitter"][0]} quits: {ret["message"]}',
LogScope.CHAT, target=id_)
- else:
- self._log(f'PLEASE IMPLEMENT HANDLER FOR: {msg.raw}')
-
def set_nick(self, nickname: str, confirmed=False) -> None:
'Set ClientDb\'s .nick wanted, send NICK if != .nickname.'
if confirmed: