IrcMessage, PORT_SSL)
ClientsDb = dict[str, 'Client']
-CHAT_GLOB = '*'
+STREAM_GLOB = '*'
+STREAM_PREFIX_META = ':'
+STREAM_SERVER = f'{STREAM_PREFIX_META}server'
+STREAM_RAW = f'{STREAM_PREFIX_META}raw'
_LOG_PREFIX_PRIVMSG = ''
_LOG_PREFIX_SEND_RAW = '=>|'
'Steps to perform right after connection.'
assert self.conn is not None
self.log.add('connected to server (SSL: '
- f'{"yes" if self.conn.ssl else "no"})', chat=CHAT_GLOB)
+ f'{"yes" if self.conn.ssl else "no"})',
+ stream=STREAM_GLOB)
self._caps.challenge('LS', '302')
self.send(IrcMessage(verb='USER',
params=(getuser(), '0', '*',
self.send(IrcMessage(verb='NICK', params=(self.conn_setup.nickname,)))
@abstractmethod
- def _log(self, msg: str, chat: str = '') -> None:
- '''Write msg into log of chat, whatever shape that may have.
-
- Messages to chat=CHAT_GLOB are meant to appear in all widgets mapped to
- the client, those to chat="" only in the initial connection window.
- '''
-
- def send(self, msg: IrcMessage, chat: str = '', to_log: str = '') -> None:
+ def _log(self, msg: str, stream: str = STREAM_SERVER) -> None:
+ 'Write msg into log of stream, whatever shape that may have.'
+
+ def send(self,
+ msg: IrcMessage,
+ stream: str = STREAM_SERVER,
+ to_log: str = ''
+ ) -> None:
'Send line-separator-delimited message over socket.'
if not self.conn:
self.log.alert('cannot send, connection seems closed')
return
self.conn.send(msg)
if to_log:
- self.log.add(to_log, prefix='', chat=chat)
- self.log.add(msg.raw, prefix=_LOG_PREFIX_SEND_RAW, chat=':raw')
+ self.log.add(to_log, prefix='', stream=stream)
+ self.log.add(msg.raw, prefix=_LOG_PREFIX_SEND_RAW, stream=STREAM_RAW)
def update_login(self, nick_confirmed: bool, nickname: str = '') -> None:
'''Manage conn_setup.nickname, .nick_confirmed.
verb = ('set' if first_run
else f'changed from "{self.conn_setup.nickname}"')
self.conn_setup.nickname = nickname
- self.log.add(f'{prefix} {verb} to "{nickname}"', chat=CHAT_GLOB)
+ self.log.add(f'{prefix} {verb} to "{nickname}"',
+ stream=STREAM_GLOB)
if first_run or nick_confirmed != self.nick_confirmed:
self.nick_confirmed = nick_confirmed
if not first_run:
def close(self) -> None:
'Close both recv Loop and socket.'
- self.log.add(msg='disconnecting from server', chat=CHAT_GLOB)
+ self.log.add(msg='disconnecting from server', stream=STREAM_GLOB)
self._caps.clear()
if self.conn:
self.conn.close()
def handle_msg(self, msg: IrcMessage) -> None:
'Process incoming msg towards appropriate client steps.'
- self.log.add(msg.raw, prefix=_LOG_PREFIX_RECV_RAW, chat=':raw')
+ self.log.add(msg.raw, prefix=_LOG_PREFIX_RECV_RAW, stream=STREAM_RAW)
match msg.verb:
case 'PING':
self.send(IrcMessage(verb='PONG', params=(msg.params[0],)))
self.update_login(nickname=msg.params[0], nick_confirmed=True)
case 'PRIVMSG':
nickname = msg.source.split('!')[0]
- self.log.add(f'<[{nickname}] {msg.params[-1]}', chat=nickname,
+ self.log.add(f'<[{nickname}] {msg.params[-1]}',
+ stream=nickname,
prefix=_LOG_PREFIX_PRIVMSG)
case 'CAP':
for to_log in self._caps.process_msg(msg.params[1:]):
from ircplom.tui_base import (BaseTui, PromptWidget, TuiEvent, Window,
CMD_SHORTCUTS)
from ircplom.irc_conn import IrcMessage
-from ircplom.client import (CHAT_GLOB, IrcConnSetup, Client, ClientIdMixin,
- ClientQueueMixin, NewClientEvent)
+from ircplom.client import (
+ STREAM_GLOB, STREAM_PREFIX_META, STREAM_RAW, STREAM_SERVER,
+ IrcConnSetup, Client, ClientIdMixin, ClientQueueMixin, NewClientEvent)
CMD_SHORTCUTS['disconnect'] = 'window.disconnect'
CMD_SHORTCUTS['nick'] = 'window.nick'
class _ClientWindow(Window, ClientQueueMixin):
- def __init__(self, chat: str = '', **kwargs) -> None:
- self.chat = chat
+ def __init__(self, stream: str, **kwargs) -> None:
+ self.stream = stream
super().__init__(**kwargs)
@property
def _status_title(self) -> str:
- return f'{super()._status_title}|{self.client_id}|{self.chat}'
+ return f'{super()._status_title}|{self.client_id}|{self.stream}'
def _send_msg(self, verb: str, params: tuple[str, ...], **kwargs) -> None:
self._cputs('send', msg=IrcMessage(verb=verb, params=params), **kwargs)
def cmd__privmsg(self, target: str, msg: str) -> None:
'Send chat message msg to target.'
self._send_msg('PRIVMSG', (target, msg),
- chat=target, to_log=f'>[MYSELF] {msg}')
+ stream=target, to_log=f'>[MYSELF] {msg}')
class _PrivmsgPromptWidget(PromptWidget):
prompt: _PrivmsgPromptWidget
def cmd__chat(self, msg: str) -> None:
- 'PRIVMSG to .chat.'
- self.cmd__privmsg(self.chat, msg)
+ 'PRIVMSG to target identified by .stream.'
+ self.cmd__privmsg(self.stream, msg)
class ClientTui(BaseTui):
super().__init__(**kwargs)
self.clients_data: dict[str, dict[str, Any]] = {}
- def _new_client_window(self, client_id: str, chat: str = ''
- ) -> _ClientWindow:
+ def _new_client_window(self, client_id: str, stream: str) -> _ClientWindow:
new_idx = len(self._windows)
- win_class = (_PrivmsgWindow if (chat and chat[0].isalpha())
+ win_class = (_PrivmsgWindow if stream[0:1] != STREAM_PREFIX_META
else _ClientWindow)
win = win_class(idx=new_idx, term=self._term, _q_out=self._q_out,
- client_id=client_id, chat=chat)
+ client_id=client_id, stream=stream)
if isinstance(win, _PrivmsgWindow):
win.prompt.update_prefix(**{k: self.clients_data[client_id][k]
for k in _PROMPT_UPDATE_TRIGGER_KEYS})
return [win for win in self._windows if isinstance(win, _ClientWindow)]
def client_wins(self, client_id: str = '') -> list[_ClientWindow]:
- 'All _ClientWindows matching client_id; if none, create one.'
+ 'All _ClientWindows matching client_id; if none, create basics.'
wins = [w for w in self._all_client_wins if client_id == w.client_id]
if not wins:
- wins = [self._new_client_window(client_id=client_id)]
+ for stream in (STREAM_SERVER, STREAM_RAW):
+ wins += [self._new_client_window(client_id, stream)]
return wins
- def client_win(self, client_id: str, chat: str = '') -> _ClientWindow:
- 'That _ClientWindow matching client_id and chat; if none, create one.'
+ def client_win(self, client_id: str, stream: str) -> _ClientWindow:
+ 'That _ClientWindow matching client_id and stream; if none, create.'
client_wins = self.client_wins(client_id)
- candidates = [win for win in client_wins if win.chat == chat]
+ candidates = [win for win in client_wins if win.stream == stream]
if candidates:
return candidates[0]
- win = self._new_client_window(client_id=client_id, chat=chat)
+ win = self._new_client_window(client_id=client_id, stream=stream)
return win
def cmd__connect(self,
@dataclass
class _ClientLogEvent(TuiEvent, ClientIdMixin):
- chat: str
+ stream: str
msg: str
def affect(self, target: ClientTui) -> None:
- if self.chat == CHAT_GLOB:
+ if self.stream == STREAM_GLOB:
for win in target.client_wins(self.client_id):
win.log.append(self.msg)
else:
- target.client_win(self.client_id, self.chat).log.append(self.msg)
+ target.client_win(self.client_id, self.stream
+ ).log.append(self.msg)
target.redraw_affected()
class _ClientKnowingTui(Client):
- def _log(self, msg: str, chat: str = '') -> None:
- self._cput(_ClientLogEvent, chat=chat, msg=msg)
+ def _log(self, msg: str, stream: str = STREAM_SERVER) -> None:
+ self._cput(_ClientLogEvent, stream=stream, msg=msg)
def update_login(self, nick_confirmed: bool, nickname: str = '') -> None:
super().update_login(nick_confirmed, nickname)