and (n_msg_params == len_params
or len_is_min and n_msg_params > len_params))
- def nick_conforms(self, db: '_ClientDb') -> bool:
- 'Test .nick_from_source == db.nickname.'
- return self.nick_from_source == db.nickname
-
- def confirm_nick(self, db: '_ClientDb') -> None:
- 'Assume .params[0] confirms nickname.'
- db.nickname = self.params[0]
- db.nickname_confirmed = True
-
@property
def nick_from_source(self) -> str:
'Parse .source into user nickname.'
'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):
- msg.confirm_nick(self._db)
+ self.set_nick(msg.params[0], confirm=True)
if _NumericsToIgnore.contain(msg.verb):
return
if msg.match('005', 2, True): # RPL_ISUPPORT
# claims: "<hostname> can also be in the form <user@hostname>"
self._db.client_host = msg.params[1].split('@')[-1]
elif msg.match('432', 3): # ERR_ERRONEOUSNICKNAME
- self._log('nickname refused for bad format, giving up', alert=True)
- self.close()
+ if msg.params[0] == '*':
+ self._log(alert=True,
+ msg='nickname refused for bad format, giving up')
+ self.close()
+ else:
+ self._db.nickname = msg.params[0]
+ self._db.nickname_confirmed = True
elif msg.match('433', 3): # ERR_NICKNAMEINUSE
- new_nick = self._db.nick_incremented
- self._log('nickname already in use, trying {new_nick}', alert=True)
- self.send(IrcMessage(verb='NICK', params=(new_nick,)))
+ self._log('nickname already in use, trying increment', alert=True)
+ self.set_nick(self._db.nick_incremented)
elif msg.match('903', 2) or msg.match('904', 2): # RPL_SUCESS, or …
self._db.sasl_auth_state = 'WIN' if msg.verb == '903' else 'FAIL'
self._caps.end_negotiation() # … ERR_SASLFAIL
self.close()
elif msg.match('MODE', 2) and msg.params[0] == self._db.nickname:
self._db.user_modes = msg.params[1]
- elif msg.match('NICK') and msg.nick_conforms(self._db):
- msg.confirm_nick(self._db)
+ elif msg.match('NICK'):
+ self.set_nick(msg.params[0], confirm=True)
elif msg.match('NOTICE', 2) or msg.match('PRIVMSG', 2):
scope = LogScope.CHAT if '!' in msg.source else LogScope.SERVER
self._log(msg.params[-1], scope=scope, channel=msg.params[0],
self._log(log_msg, scope=LogScope.CHAT, channel=channel)
if msg.verb == 'JOIN':
self._db.chan(channel).users.append(msg.nick_from_source)
- elif msg.nick_conforms(self._db):
+ elif msg.nick_from_source == self._db.nickname:
self._db.del_chan(channel)
else:
self._db.chan(channel).users.remove(msg.nick_from_source)
else:
self._log(f'PLEASE IMPLEMENT HANDLER FOR: {msg.raw}')
+ def set_nick(self, new_nickname: str, confirm=False) -> None:
+ 'Set ClientDb\'s .nickname, .…_confirmed, and sends NICK if connected.'
+ if new_nickname != self._db.nickname:
+ if self.conn:
+ self.send(IrcMessage(verb='NICK', params=(new_nickname,)))
+ self._db.nickname = new_nickname
+ self._db.nickname_confirmed = confirm
+
@dataclass
class NewClientEvent(AffectiveEvent):