Added sys/notice timeout config

master
Mark Qvist 2026-05-19 14:50:31 +02:00
parent da201fb3b6
commit 68c26a697b
4 changed files with 100 additions and 14 deletions

View File

@ -154,6 +154,7 @@ class NomadNetworkApp:
self.rrc_history_per_room_cap = 500
self.rrc_filter_loaded_history = True
self.rrc_ephemeral_notices = 600
if not os.path.isdir(self.storagepath):
os.makedirs(self.storagepath)
@ -918,6 +919,11 @@ class NomadNetworkApp:
try: value = self.config["rrc"].as_bool(option)
except Exception: value = True
self.rrc_filter_loaded_history = value
if option == "ephemeral_notices":
try: value = self.config["rrc"].as_float(option)
except Exception: value = 0
self.rrc_ephemeral_notices = value*60
if "node" in self.config:
if not "enable_node" in self.config["node"]:
@ -1248,6 +1254,13 @@ history_per_room_cap = 500
# loaded.
filter_loaded_history = yes
# You can choose whether notices and sys
# messages persist indefinitely, or are
# removed from the message history after
# the specified time in minutes. Set to 0
# to disable and keep forever.
ephemeral_notices = 10
[node]
# Whether to enable node hosting

View File

@ -201,6 +201,9 @@ class RRCHub:
STATUS_CONNECTED = 2
STATUS_FAILED = 3
CLEAN_HISTORY_INTERVAL = 5
SYS_NOTICE_TIMEOUT = 600
def __init__(self, manager, hub_hash, dest_name=None, name=None):
self.manager = manager
self.hub_hash = hub_hash
@ -242,6 +245,8 @@ class RRCHub:
self._reconnect_attempts = 0
self._reconnect_timer = None
self._pending_pings = {}
self._last_history_clean = 0
self.clean_last_removed = 0
self.available_rooms = {}
self._silent_list_pending = 0
@ -631,6 +636,11 @@ class RRCHub:
except Exception: return True
return v
def _ephemeral_notices_history(self):
try: v = getattr(self.manager.app, "rrc_ephemeral_notices", self.SYS_NOTICE_TIMEOUT)
except Exception: return self.SYS_NOTICE_TIMEOUT
return v
def _entry_for(self, msg):
return {
H_KIND: msg.kind,
@ -723,6 +733,32 @@ class RRCHub:
with self._lock:
self.messages[room] = msgs
def _clean_history(self):
now = time.time()
cleaned = False
remove_after = self._ephemeral_notices_history()
if now > self._last_history_clean + self.CLEAN_HISTORY_INTERVAL:
RNS.log(f"Cleaning loaded message history", RNS.LOG_DEBUG)
with self._lock:
try:
for r in self.messages:
old = set()
for m in self.messages[r]:
age = now-m.ts/1000.0
should_filter = False
if m.kind == "system": should_filter = True
elif m.kind == "notice": should_filter = True
if should_filter and age > remove_after: old.add(m)
for m in old:
self.messages[r].remove(m)
cleaned = True
except Exception as e: RNS.trace_exception(e)
self._last_history_clean = time.time()
if cleaned: self.clean_last_removed = time.time()
def _record_message(self, msg, local=False):
cap = self._per_room_cap()
with self._lock:
@ -736,6 +772,7 @@ class RRCHub:
if msg.mention:
self.mention_rooms.add(msg.room)
self._append_history(msg.room, msg)
self._clean_history()
self.manager._notify_messages(self, msg)
def _record_system(self, room, text):
@ -749,6 +786,7 @@ class RRCHub:
if cap is not None and len(buf) > cap:
del buf[:len(buf)-cap]
self._append_history(room, msg)
self._clean_history()
self.manager._notify_messages(self, msg)
def _record_notice(self, msg):
@ -772,6 +810,7 @@ class RRCHub:
self.unread_rooms.add(target_room)
if target_room:
self._append_history(target_room, msg)
self._clean_history()
self.manager._notify_messages(self, msg)
def get_messages(self, room):

View File

@ -29,13 +29,6 @@ _LINK_RE = re.compile(
r"|(?P<room>(?<!\w)#[A-Za-z0-9][A-Za-z0-9_\-]{0,62})"
)
def _link_attrs():
return {
"room": urwid.AttrSpec("light cyan,underline", "default", colors=256),
@ -43,10 +36,8 @@ def _link_attrs():
"page": urwid.AttrSpec("light blue,underline", "default", colors=256),
}
_LINK_ATTRS = _link_attrs()
def _scan_links(text):
for m in _LINK_RE.finditer(text):
if m.group("lxmf"):
@ -366,6 +357,7 @@ class RoomWidget(urwid.WidgetWrap):
self.app = nomadnet.NomadNetworkApp.get_shared_instance()
self.messagelist = None
self.last_history_clean = 0
self.peer_info_widget = urwid.AttrMap(urwid.Text(""), "msg_header_sent")
self._update_peer_info()
@ -489,11 +481,33 @@ class RoomWidget(urwid.WidgetWrap):
try:
widget = _message_widget(self.app, self.hub, msg, link_delegate=self.link_delegate)
wrapped = urwid.AttrMap(widget, None)
body = self.messagelist._listbox.body
body = self.messagelist.get_body()
was_at_bottom = getattr(self, "_empty_placeholder", False) or getattr(self.messagelist, "bottom_is_visible", True)
if getattr(self, "_empty_placeholder", False):
del body[:]
self._empty_placeholder = False
if self.hub.clean_last_removed > self.last_history_clean:
try:
hub_msgs = self.hub.get_messages(self.room) if (self.hub is not None and self.room is not None) else []
self.last_history_clean = time.time()
c = self.messagelist.body_len()
old = set()
for i in range(0, c):
msg = None
w = self.messagelist.get_item(i)
if hasattr(w, "_original_widget"): o = w._original_widget
else: o = None
if hasattr(o, "msg"): msg = o.msg
elif hasattr(w, "msg"): msg = w.msg
if msg and not msg in hub_msgs: old.add(i)
for i in reversed(list(old)): self.messagelist.delete_position(i)
except Exception as e:
RNS.log("Error while cleaning room history", RNS.LOG_ERROR)
RNS.trace_exception(e)
body.append(wrapped)
cap = getattr(self.app, "rrc_history_per_room_cap", 0)
if cap and cap > 0:
@ -865,17 +879,23 @@ def _message_widget(app, hub, m, link_delegate=None):
evt_icon = g["arrow_l"] if m.text.endswith(" left") else g["arrow_r"]
spans, has_links = _body_markup(m.text or "", body_attr="irc_system", own_nick=own_nick)
markup = [_ts_prefix(m.ts), ("irc_system", evt_icon+" ")] + spans
return _wrap_text(markup, link_delegate if has_links else None)
final_widget = _wrap_text(markup, link_delegate if has_links else None)
final_widget.msg = m
return final_widget
if m.kind == "notice":
spans, has_links = _body_markup(m.text or "", body_attr="irc_notice", own_nick=own_nick)
markup = [_ts_prefix(m.ts), ("irc_notice", g["info"]+" ")] + spans
return _wrap_text(markup, link_delegate if has_links else None)
final_widget = _wrap_text(markup, link_delegate if has_links else None)
final_widget.msg = m
return final_widget
if m.kind == "error":
spans, has_links = _body_markup(m.text or "", body_attr="irc_error", own_nick=own_nick)
markup = [_ts_prefix(m.ts), ("irc_error", g["warning"]+" ")] + spans
return _wrap_text(markup, link_delegate if has_links else None)
final_widget = _wrap_text(markup, link_delegate if has_links else None)
final_widget.msg = m
return final_widget
own = False
try:
@ -895,7 +915,9 @@ def _message_widget(app, hub, m, link_delegate=None):
body = m.text or ""
spans, has_links = _body_markup(body, body_attr="body_text", own_nick=None if own else own_nick)
markup = [_ts_prefix(m.ts), (nick_attr, "<"+sender+">"), ("body_text", " ")] + spans
return _wrap_text(markup, link_delegate if has_links else None)
final_widget = _wrap_text(markup, link_delegate if has_links else None)
final_widget.msg = m
return final_widget
def _wrap_text(markup, link_delegate):

View File

@ -781,6 +781,18 @@ This section hold configuration directives related to the RRC client behaviour.
Maximum number of messages retained per room in the in-memory scrollback buffer, and the number of messages restored from on-disk history at startup. The on-disk log itself is appended to indefinitely; this cap only controls how much backlog is visible. Set to 0 to keep every message in memory.
<
>>>
`!filter_loaded_history = yes`!
>>>>
Whether to filter notices and system message when initially loading room history.
<
>>>
`!ephemeral_notices = 10`!
>>>>
If enabled, notices and system messages will disappear from the history after a while. 0 disables, otherwise sets the timeout in minutes.
<
>> Text UI Section
This section hold configuration directives related to the look and feel of the text-based user interface of the program. It is delimited by the `![textui]`! header in the configuration file. Available directives, along with their default values, are as follows: