From 6407950bd4991c1d9ac14ff4e44b2980a9801ef9 Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 6 May 2026 16:55:36 -0500 Subject: [PATCH] refactor(reticulum_config): update _ensure_reticulum_config method to conditionally create config file --- meshchatx/meshchat.py | 29 ++++++++++++++++++++++++++--- tests/backend/test_lifecycle.py | 1 + 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/meshchatx/meshchat.py b/meshchatx/meshchat.py index 3c07b4d..a3abc92 100644 --- a/meshchatx/meshchat.py +++ b/meshchatx/meshchat.py @@ -660,10 +660,33 @@ class ReticulumMeshChat: raise RuntimeError("Database not initialized") return self.database.restore_database(backup_path) - def _ensure_reticulum_config(self): - """Normalize ``reticulum_config_dir``; RNS creates ``config`` on first startup.""" + def _ensure_reticulum_config(self, materialize: bool = True): + """Normalize ``reticulum_config_dir`` and optionally ensure a ``config`` file exists. + + When ``materialize`` is true (default), write RNS stock defaults if the file + is missing or lacks required sections so first Reticulum startup is reliable. + + API handlers that must distinguish a missing file (e.g. raw config GET) pass + ``materialize=False`` to only normalize the directory path. + """ config_dir = self._normalize_reticulum_config_dir(self.reticulum_config_dir) self.reticulum_config_dir = config_dir + if not materialize: + return + config_path = os.path.join(config_dir, "config") + needs_default = True + if os.path.isfile(config_path): + try: + with open(config_path) as f: + content = f.read() + if "[reticulum]" in content and "[interfaces]" in content: + needs_default = False + except OSError: + pass + if needs_default: + if not os.path.isdir(config_dir): + os.makedirs(config_dir, exist_ok=True) + self._write_rns_reticulum_default_config_file(config_path) def setup_identity(self, identity: RNS.Identity): identity_hash = identity.hash.hex() @@ -6668,7 +6691,7 @@ class ReticulumMeshChat: cannot easily be opened with an external editor). """ try: - self._ensure_reticulum_config() + self._ensure_reticulum_config(materialize=False) config_path = self._reticulum_config_file_path() if not os.path.exists(config_path): return web.json_response( diff --git a/tests/backend/test_lifecycle.py b/tests/backend/test_lifecycle.py index 0c7b897..fbecefd 100644 --- a/tests/backend/test_lifecycle.py +++ b/tests/backend/test_lifecycle.py @@ -57,6 +57,7 @@ def test_database_provider_disposal(): def test_web_audio_bridge_disposal(): """Test that WebAudioBridge correctly manages clients and cleanup.""" mock_tele_mgr = MagicMock() + mock_tele_mgr.is_voicemail_session_active = False mock_config_mgr = MagicMock() bridge = WebAudioBridge(mock_tele_mgr, mock_config_mgr)