From: Christian Heller Date: Tue, 2 Sep 2025 17:40:12 +0000 (+0200) Subject: Restructure topic setting. X-Git-Url: https://plomlompom.com/repos/balance?a=commitdiff_plain;h=f81c1c213dcdd649a59fecd10b86ab9f03ca7978;p=ircplom Restructure topic setting. --- diff --git a/ircplom/client.py b/ircplom/client.py index ce55b04..b1fd4b8 100644 --- a/ircplom/client.py +++ b/ircplom/client.py @@ -139,6 +139,8 @@ class _UpdatingMixin(AutoAttrMixin): 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() @@ -304,9 +306,72 @@ class _IrcConnection(BaseIrcConnection, _ClientIdMixin): 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, @@ -373,13 +438,25 @@ class _NickUserHost(NickUserHost): )[-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): @@ -691,11 +768,9 @@ class Client(ABC, ClientQueueMixin): 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 @@ -765,8 +840,8 @@ class Client(ABC, ClientQueueMixin): 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] diff --git a/ircplom/client_tui.py b/ircplom/client_tui.py index d7085d8..329958e 100644 --- a/ircplom/client_tui.py +++ b/ircplom/client_tui.py @@ -11,7 +11,7 @@ from ircplom.irc_conn import IrcMessage 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' @@ -191,14 +191,14 @@ class _ChannelWindow(_ChatWindow): 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) @@ -207,11 +207,9 @@ class _UpdatingChannel(_UpdatingNode): 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