def __init__(self, sender: Callable[[IrcMessage], None], db: 'ClientDb',
) -> None:
self._db = db
- self._db.set('caps_LS', [])
- self._db.set('caps_LIST', [])
self._send = sender
self._sent_challenges: list[str] = []
self.sasl_wait = False
def clear(self) -> None:
'Reset all negotiation knowledge to zero.'
self._reset_negotation_steps()
- self._db.set('caps_LS', [], confirm=False)
- self._db.set('caps_LIST', [], confirm=False)
@property
def asdict(self) -> Optional[dict[str, _ServerCapability]]:
match params[0]:
case 'NEW':
for param in params[-1].split():
- self._db.append('caps_LS', param)
+ self._db.append('caps_LS', param, keep_confirmed=True)
case 'DEL':
for param in params[-1].split():
del self._db.caps_LS[param]
self._db.append('caps_LIST', name)
case 'LS' | 'LIST':
key = f'caps_{params[0]}'
- if getattr(self._db, key) is not None:
- self._db.set(key, [], confirm=False)
for item in params[-1].strip().split():
self._db.append(key, item)
if params[1] != '*':
def __init__(self) -> None:
self._dict: dict[str, int | str | list[str]] = {}
+ self._confirmeds: list[str] = []
def __getattr__(self, key: str) -> Any:
- if key[:1] != '_' and key in self._dict:
+ if key in self._dict and key in self._confirmeds:
return self._dict[key]
return None
- def _unconf_key(self, key) -> str:
- return f'_{key}'
-
def set(self,
key: str,
value: Optional[int | str | list[str]],
) -> tuple[bool, bool]:
'Ensures setting, returns if changed value or confirmation.'
old_value, was_confirmed = self.get_force(key)
- assert (old_value is not None) or (value is not None)
- confirm_changed = confirm != was_confirmed
- key_to_set = key if confirm else self._unconf_key(key)
- key_to_unset = self._unconf_key(key) if confirm else key
value_changed = (value is not None) and value != old_value
- if value is not None:
- self._dict[key_to_set] = value
- if confirm_changed and old_value is not None:
- if value is None:
- self._dict[key_to_set] = old_value
- del self._dict[key_to_unset]
+ if value is None:
+ if old_value is None:
+ if confirm:
+ raise Exception
+ del self._dict[key]
+ elif value_changed:
+ self._dict[key] = value
+ confirm_changed = confirm != was_confirmed
+ if confirm_changed:
+ if confirm:
+ self._confirmeds += [key]
+ else:
+ self._confirmeds.remove(key)
return (value_changed, confirm_changed)
- def append(self, key: str, value: str) -> None:
+ def append(self, key: str, value: str, keep_confirmed=False) -> None:
'To list[str] keyed by key, append value; if non-existant, create it.'
- targeted = self.get_force(key)[0]
+ if not keep_confirmed and key in self._confirmeds:
+ self._confirmeds.remove(key)
+ del self._dict[key]
+ targeted = self._dict.get(key, None)
if isinstance(targeted, list):
targeted.append(value)
elif targeted is None:
- self._dict[self._unconf_key(key)] = [value]
+ self._dict[key] = [value]
else:
raise Exception
def get_force(self, key: str) -> tuple[Optional[int | str | list[str]],
bool]:
- 'Get even if only stored unconfirmed, tell if confirmed was found..'
- conf = key in self._dict
- find = self._dict.get(key if conf else self._unconf_key(key), None)
- return (find, conf)
+ 'Get even if only stored unconfirmed, tell if confirmed..'
+ return (self._dict.get(key, None), key in self._confirmeds)
@property
def conn_setup(self) -> IrcConnSetup:
'Constructed out of stored entries *including* unconfirmed ones.'
kwargs: dict[str, Any] = {}
for field_name in IrcConnSetup._fields:
- kwargs[field_name] = self.get_force(field_name)[0]
+ kwargs[field_name] = self._dict.get(field_name, None)
return IrcConnSetup(**kwargs)
self._log(to_log, scope=log_target)
self._log(msg.raw, scope=LogScope.RAW, out=True)
- def _update_db(self, key: str, value: Optional[int | str], confirm: bool
+ def _update_db(self,
+ key: str,
+ value: Optional[int | str | list[str]],
+ confirm: bool
) -> tuple[bool, bool]:
'Wrap ._db.set into something accessible to subclass extension.'
return self._db.set(key, value, confirm)
case '001' | 'NICK':
self._update_db('nickname', value=msg.params[0], confirm=True)
case '005':
- if self._db.isupports:
- self._db.set('isupports', [], False)
for param in msg.params[1:-1]:
self._db.append('isupports', param)
case '375':
with open(f'{self.client_id}.log', 'a', encoding='utf8') as f:
f.write(('>' if kwargs['out'] else '<') + f' {msg}\n')
- def _update_db(self, key: str, value: Optional[int | str], confirm: bool
- ) -> None:
- value_changed, _ = super()._update_db(key, value, confirm)
+ def _update_db(self,
+ key: str,
+ value: Optional[int | str | list[str]],
+ confirm: bool
+ ) -> tuple[bool, bool]:
+ value_changed, conf_changed = super()._update_db(key, value, confirm)
if value is None and not value_changed: # local ._db may have fallback
value = self._db.get_force(key)[0] # values Tui._db doesn't
self._client_tui_trigger('update', scope=LogScope.SERVER,
key=key, value=value, confirmed=confirm)
+ return (value_changed, conf_changed)