From 7d78f1ab630568f18cda60e7d94e6c1e0c080ece Mon Sep 17 00:00:00 2001 From: yunyaozhou Date: Tue, 21 Jul 2026 02:24:41 +0800 Subject: [PATCH] fix: print config hint when logs token is missing --once --logs now exits 2 with a clear pointer to SHUSUB2_LOGS_TOKEN / ~/.config/shusub2/logs-token instead of a raw HTTP 401 traceback; the TUI logs page reuses the same hint. Co-Authored-By: Claude Fable 5 --- sub2api_quota_tui.py | 15 +++++++++++---- tests/test_payload.py | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/sub2api_quota_tui.py b/sub2api_quota_tui.py index 2c0c562..2a7349b 100644 --- a/sub2api_quota_tui.py +++ b/sub2api_quota_tui.py @@ -906,10 +906,7 @@ def run_textual( def refresh_data(self) -> None: status = self.query_one("#status", Static) if not str(logs_token or "").strip(): - status.update( - "logs token not configured: set SHUSUB2_LOGS_TOKEN or write the Sub2API admin API key to " - f"{logs_token_config_file_path()}" - ) + status.update(logs_token_hint()) return status.update("refreshing logs...") try: @@ -972,6 +969,13 @@ def run_textual( return 0 +def logs_token_hint() -> str: + return ( + "logs token not configured: set SHUSUB2_LOGS_TOKEN or write the Sub2API admin API key to " + f"{logs_token_config_file_path()}" + ) + + def build_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser(description="Sub2API quota and daily usage TUI") parser.add_argument("--api-url", default=default_api_url()) @@ -1034,6 +1038,9 @@ def main(argv: list[str] | None = None) -> int: if version_message: print(version_message) if args.logs: + if not str(args.logs_token or "").strip(): + print(logs_token_hint(), file=sys.stderr) + return 2 print_logs_once(fetch_logs_payload(args.logs_url, args.logs_token, args.timeout, logs_limit), args.filter) return 0 status_payload, status_error = fetch_optional_payload(status_url, args.timeout) diff --git a/tests/test_payload.py b/tests/test_payload.py index 2ce1dd4..7ce2306 100644 --- a/tests/test_payload.py +++ b/tests/test_payload.py @@ -469,6 +469,26 @@ class Sub2APILogsTests(unittest.TestCase): else: os.environ["SHUSUB2_LOGS_TOKEN_FILE"] = old_value + def test_once_logs_without_token_prints_hint_and_exits_2(self) -> None: + mod = load_module() + old_token = os.environ.pop("SHUSUB2_LOGS_TOKEN", None) + old_file = os.environ.get("SHUSUB2_LOGS_TOKEN_FILE") + os.environ["SHUSUB2_LOGS_TOKEN_FILE"] = "/nonexistent/shusub2/logs-token" + err = io.StringIO() + try: + with contextlib.redirect_stderr(err): + rc = mod.main(["--once", "--logs", "--no-version-check"]) + finally: + if old_token is not None: + os.environ["SHUSUB2_LOGS_TOKEN"] = old_token + if old_file is None: + os.environ.pop("SHUSUB2_LOGS_TOKEN_FILE", None) + else: + os.environ["SHUSUB2_LOGS_TOKEN_FILE"] = old_file + + self.assertEqual(rc, 2) + self.assertIn("logs token not configured", err.getvalue()) + def test_default_logs_url_defaults_to_sub2apicn(self) -> None: mod = load_module() old_url = os.environ.pop("SHUSUB2_LOGS_URL", None)