'All we need to know to set up a new Client connection.'
hostname: str = ''
port: int = 0
- nickname: str = ''
+ nick_wanted: str = ''
realname: str = ''
password: str = ''
# channel_modes: str
-class _ClientDb(_Db, IrcConnSetup):
- caps: _UpdatingDict
+class SharedClientDbFields(IrcConnSetup):
+ 'API for fields shared directly in name and type with TUI.'
connection_state: str
client_host: str
- isupports: _UpdatingDict
- nickname_confirmed: bool
- user_modes: str
+ nickname: str
sasl_auth_state: str
+ user_modes: str
+
+
+class _ClientDb(_Db, SharedClientDbFields):
+ caps: _UpdatingDict
+ isupports: _UpdatingDict
_completable_motd: _CompletableStringsList
_channels: dict[str, _ChannelDb]
@property
def nick_incremented(self) -> str:
- 'Return .nickname with number suffix incremented, or "0" if none yet.'
- name, digits = ([(self.nickname, '')]
- + [(self.nickname[:i], self.nickname[i:])
- for i in range(len(self.nickname), 0, -1)
- if self.nickname[i:].isdigit()]
+ 'Return .nick_wanted with number suffix incremented, or "0" if none.'
+ name, digits = ([(self.nick_wanted, '')]
+ + [(self.nick_wanted[:i], self.nick_wanted[i:])
+ for i in range(len(self.nick_wanted), 0, -1)
+ if self.nick_wanted[i:].isdigit()]
)[-1]
return name + str(0 if not digits else (int(digits) + 1))
self._caps.start_negotation()
self.send(IrcMessage(verb='USER',
params=(getuser(), '0', '*', self._db.realname)))
- self.send(IrcMessage(verb='NICK', params=(self._db.nickname,)))
+ self.send(IrcMessage(verb='NICK', params=(self._db.nick_wanted,)))
@abstractmethod
def _log(self, msg: str, scope=LogScope.SERVER, **kwargs) -> None:
self.conn.close()
self.conn = None
self._db.isupports.clear()
- self._db.nickname_confirmed = False
+ self._db.nickname = ''
self._db.sasl_auth_state = ''
def on_handled_loop_exception(self, e: IrcConnAbortException) -> 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], confirm=True)
+ self.set_nick(msg.params[0], confirmed=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
+ alert = 'nickname refused for bad format'
if msg.params[0] == '*':
- self._log(alert=True,
- msg='nickname refused for bad format, giving up')
+ alert += ', giving up'
self.close()
else:
- self._db.nickname = msg.params[0]
- self._db.nickname_confirmed = True
+ self.set_nick(msg.params[0], confirmed=True)
+ self._log(alert, alert=True)
elif msg.match('433', 3): # ERR_NICKNAMEINUSE
self._log('nickname already in use, trying increment', alert=True)
self.set_nick(self._db.nick_incremented)
elif msg.match('MODE', 2) and msg.params[0] == self._db.nickname:
self._db.user_modes = msg.params[1]
elif msg.match('NICK'):
- self.set_nick(msg.params[0], confirm=True)
+ self.set_nick(msg.params[0], confirmed=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],
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
+ def set_nick(self, nickname: str, confirmed=False) -> None:
+ 'Set ClientDb\'s .nick wanted, send NICK if != .nickname.'
+ if confirmed:
+ self._db.nickname = nickname
+ self._db.nick_wanted = nickname
+ if self.conn and self._db.nick_wanted != self._db.nickname:
+ self.send(IrcMessage(verb='NICK', params=(self._db.nick_wanted,)))
@dataclass
from ircplom.tui_base import (BaseTui, PromptWidget, TuiEvent, Window,
CMD_SHORTCUTS)
from ircplom.irc_conn import IrcMessage
-from ircplom.client import (Client, ClientQueueMixin, Db, IrcConnSetup,
- LogScope, NewClientEvent, ServerCapability)
+from ircplom.client import (
+ Client, ClientQueueMixin, Db, IrcConnSetup, LogScope, NewClientEvent,
+ ServerCapability, SharedClientDbFields)
CMD_SHORTCUTS['disconnect'] = 'window.disconnect'
CMD_SHORTCUTS['join'] = 'window.join'
def cmd__nick(self, new_nick: str) -> None:
'Attempt nickname change.'
- self._client_trigger('set_nick', new_nickname=new_nick)
+ self._client_trigger('set_nick', nickname=new_nick)
def cmd__join(self, channel: str) -> None:
'Attempt joining a channel.'
class _ChatPrompt(PromptWidget):
_nickname: str = ''
- _nick_confirmed: bool = False
@property
def prefix(self) -> str:
- return (' ' if self._nick_confirmed else '?') + f'[{self._nickname}] '
+ return f'[{self._nickname}] '
- def set_prefix_data(self, nick: str, confirmed: bool) -> None:
+ def set_prefix_data(self, nick: str) -> None:
'Update prompt prefix with nickname data.'
- if confirmed != self._nick_confirmed:
- self._tainted = True
- self._nick_confirmed = confirmed
if nick != self._nickname:
self._tainted = True
self._nickname = nick
return super().set_and_check_for_change(update)
-class _TuiClientDb(_Db, IrcConnSetup):
+class _TuiClientDb(_Db, SharedClientDbFields):
caps: dict[str, str]
- client_host: str
- connection_state: str
isupports: dict[str, str]
motd: tuple[str]
- nickname_confirmed: bool
- sasl_auth_state: str
- user_modes: str
_channels: dict[str, _ChannelDb]
def set_and_check_for_change(self, update: _Update) -> bool:
kwargs['win_cls'] = (_ChannelWindow if chatname[0] == '#'
else _ChatWindow)
kwargs['chatname'] = chatname
- kwargs['get_nick_data'] = lambda: (self._db.nickname,
- self._db.nickname_confirmed)
+ kwargs['get_nick_data'] = lambda: (self._db.nickname,)
win = self._tui_new_window(**kwargs)
self.windows += [win]
return win