return None
if isinstance(self, _CompletableStringsList):
return self.completed
+ if isinstance(self, _Topic):
+ return self.into_parent()
for cls in [cls for cls in self.__class__.__mro__
if AutoAttrMixin not in cls.__mro__]:
obj = cls()
client_id=self.client_id).kw(e=e)
+_TopicWho = TypeVar('_TopicWho', bound=NickUserHost)
+
+
+class Topic[_TopicWho]:
+ 'Encapsulates content and setter of channel topic.'
+ _what = ''
+ _who: Optional[_TopicWho] = None
+
+ def __eq__(self, other) -> bool:
+ return isinstance(self, Topic) and isinstance(other, Topic)\
+ and self.what == other.what\
+ and self.who == other.who
+
+ def _set_what(self, what: str) -> None:
+ pass
+
+ def _set_who(self, who: _TopicWho) -> None:
+ pass
+
+ @property
+ def what(self) -> str:
+ 'Content of channel topic.'
+ return self._what[:]
+
+ @what.setter
+ def what(self, what: str) -> None:
+ self._set_what(what)
+
+ @property
+ def who(self) -> Optional[_TopicWho]:
+ 'Setter of channel topic.'
+ return self._who
+
+ @who.setter
+ def who(self, who: _TopicWho) -> None:
+ self._set_who(who)
+
+
+class _Topic(Topic['_NickUserHost']):
+
+ def __init__(self) -> None:
+ self.completed: tuple[str, Optional['_NickUserHost']] = ('', None)
+
+ def _set_what(self, what: str) -> None:
+ self._what = what
+ self._who = None
+
+ def _set_who(self, who: '_NickUserHost') -> None:
+ self._who = who.copy()
+ self.complete()
+
+ def complete(self) -> None:
+ 'Declare data collection finished, return full or empty content.'
+ self.completed = (('', None) if self._who is None
+ else (self._what, self._who.copy()))
+
+ def into_parent(self) -> Topic:
+ 'Transform into as presentable as impotent parent class variant.'
+ obj = Topic[NickUserHost]()
+ obj._what, obj._who = self.completed
+ return obj
+
+
class _Channel:
user_ids: _CompletableStringsList
- topic: tuple[str, str] = ('', '')
+ topic: _Topic
def __init__(self,
get_id_for_nick: Callable,
)[-1]
return name + str(0 if not digits else (int(digits) + 1))
+ def copy(self) -> Self:
+ 'Create indepedentent copy.'
+ return self.from_str(str(self))
+
class _UpdatingServerCapability(_UpdatingMixin, ServerCapability):
pass
+class _UpdatingTopic(_UpdatingMixin, _Topic):
+
+ def complete(self) -> None:
+ super().complete()
+ self._on_update()
+
+
class _UpdatingChannel(_UpdatingMixin, _Channel):
user_ids: _UpdatingCompletableStringsList
+ topic: _UpdatingTopic
class _UpdatingNickUserHost(_UpdatingMixin, _NickUserHost):
key, data = _Dict.key_val_from_eq_str(item)
self._db.isupport[key] = data
elif ret['verb'] == '332': # RPL_TOPIC
- self._db.channels[ret['channel']].topic = (ret['topic'], '')
+ self._db.channels[ret['channel']].topic.what = ret['topic']
elif ret['verb'] == '333': # RPL_TOPICWHOTIME
- self._db.channels[ret['channel']].topic = (
- self._db.channels[ret['channel']].topic[0],
- str(ret['author']))
+ self._db.channels[ret['channel']].topic.who = ret['author']
elif ret['verb'] == '353': # RPL_NAMREPLY
self._db.channels[ret['channel']].add_from_namreply(ret['names'])
elif ret['verb'] == '366': # RPL_ENDOFNAMES
self._log(f'{ret["quitter"]} quits: {ret["message"]}',
LogScope.CHAT, target=ch_name)
elif ret['verb'] == 'TOPIC':
- self._db.channels[ret['channel']].topic = (ret['topic'],
- str(ret['author']))
+ self._db.channels[ret['channel']].topic.what = ret['topic']
+ self._db.channels[ret['channel']].topic.who = ret['author']
ClientsDb = dict[str, Client]
from ircplom.client import (
AutoAttrMixin, Client, ClientQueueMixin, Dict, DictItem, IrcConnSetup,
LogScope, NewClientEvent, NickUserHost, ServerCapability,
- SharedClientDbFields)
+ SharedClientDbFields, Topic)
CMD_SHORTCUTS['disconnect'] = 'window.disconnect'
CMD_SHORTCUTS['join'] = 'window.join'
class _UpdatingChannel(_UpdatingNode):
user_ids: tuple[str, ...] = tuple()
- topic: tuple[str, str] = ('', '')
+ topic: Topic[NickUserHost] = Topic()
log_scopes = {tuple(): LogScope.CHAT}
def set_and_check_for_change(self, update: _Update
) -> Optional[tuple[LogScope, Any]]:
- assert isinstance(update.value, tuple)
- msg: str | dict[str, tuple[str, ...]] = {}
+ msg: str | dict[str, tuple[str, ...]]
if update.path == ('user_ids',):
+ assert isinstance(update.value, tuple)
msg = {}
if not self.user_ids:
msg['nicks:residents'] = tuple(update.value)
if id_ not in self.user_ids)
msg['nuhs:parting'] = tuple(id_ for id_ in self.user_ids
if id_ not in update.value)
- elif update.path == ('topic',):
- if '' in update.value:
- return None
- msg = f'raw:topic set by {update.value[1]} to: {update.value[0]}'
if super().set_and_check_for_change(update):
+ if update.path == ('topic',):
+ msg = f'raw:{self.topic.who} set topic to: {self.topic.what}'
return (self._scope(update.path), msg)
return None