From b6525bc0ae88827dbf074c630d5be9adbfa4e7ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D0=B4=D1=80=D0=B5=D0=B9=20=D0=91=D0=BE=D0=B1?= =?UTF-8?q?=D1=8B=D1=80=D0=B5=D0=B2?= Date: Sun, 31 May 2026 01:57:19 +0300 Subject: [PATCH] stable 1.2.5: token field + channel buttons in version card MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ports the channel UI to stable so users who installed the open stable version can paste their subscriber token (save_token) and switch to beta/dev straight from Настройки → Версия и обновления. Adds gh_token_present/save_gh_token helpers and stable/beta/dev quick buttons. Co-Authored-By: Claude Opus 4.8 --- VERSION | 2 +- app.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/VERSION b/VERSION index e8ea05d..c813fe1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2.4 +1.2.5 diff --git a/app.py b/app.py index f522c08..41ff8f4 100644 --- a/app.py +++ b/app.py @@ -661,6 +661,28 @@ def panel_version(): return "unknown" +GH_TOKEN_FILE = "/opt/phobos-panel/.gh_token" + + +def gh_token_present(): + try: + return os.path.exists(GH_TOKEN_FILE) and os.path.getsize(GH_TOKEN_FILE) > 0 + except Exception: + return False + + +def save_gh_token(tok): + tok = (tok or "").strip() + if not tok: + return False + fd = os.open(GH_TOKEN_FILE, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600) + try: + os.write(fd, tok.encode()) + finally: + os.close(fd) + return True + + def run_update(arg): import subprocess try: @@ -1384,9 +1406,16 @@ def labels_page(): def settings_page(): s = load_settings() msg = "" - if request.method == "POST" and request.form.get("action") in ("update", "rollback", "check"): + if request.method == "POST" and request.form.get("action") in ("update", "rollback", "check", "save_token"): _act = request.form.get("action") - if _act == "update": + _tok = request.form.get("gh_token", "").strip() + if _tok: + save_gh_token(_tok) + if _act == "save_token": + _out = tr("Токен подписчика сохранён. Теперь можно переключаться на beta/dev.", + "Subscriber token saved. You can now switch to beta/dev.") if _tok else \ + tr("Поле токена пустое.", "Token field is empty.") + elif _act == "update": _out = run_update(request.form.get("target", "").strip() or "main") elif _act == "check": _out = run_update("--check") @@ -1428,9 +1457,25 @@ def settings_page():

{tr("Версия и обновления","Version & updates")} {hlp("Скачивает свежие файлы PCA-слоя (панель + скрипты) с GitHub и перезапускает панель. Ключи WireGuard, server.env и клиенты НЕ трогаются. Пусто или main = последняя версия; можно указать тег (например v1.1.0). Откат восстанавливает предыдущую версию из автоматического бэкапа.", "Fetches the latest PCA files (panel + scripts) from GitHub and restarts the panel. WireGuard keys, server.env and clients are NOT touched. Empty or main = latest; you can pass a tag (e.g. v1.1.0). Rollback restores the previous version from an automatic backup.")}

{tr("Установленная версия","Installed version")}: {panel_version()}

+

{tr("Каналы","Channels")}: + stable — {tr("стабильная","stable")} · + beta — {tr("тест","testing")} · + dev — {tr("разработка","development")}. + {tr("stable — без токена. Для beta/dev вставь токен подписчика (по подписке Boosty), сохрани — и жми канал.","stable needs no token. For beta/dev paste your subscriber token (Boosty), save it, then click the channel.")}

+
+ + + + {(tr("✓ токен сохранён","✓ token saved") if gh_token_present() else tr("токен не задан — beta/dev недоступны","no token — beta/dev locked"))} +
+
+
+
+
+
- +