Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed3071a971 | ||
|
|
db4cab7a38 | ||
|
|
9f402be886 | ||
|
|
8971565e6e | ||
|
|
b6525bc0ae | ||
|
|
d072c8227f | ||
|
|
7b941dc532 | ||
|
|
8c1654ecaa |
13
README.md
13
README.md
@@ -77,15 +77,20 @@ bash <(curl -fsSL https://raw.githubusercontent.com/andrey271192/PCA_Phobos/main
|
||||
| `OBF_PORTS` | `2083,5443,993` | Порты обфускатора |
|
||||
| `TG_TOKEN`/`TG_CHAT` | пусто | Telegram-уведомления |
|
||||
| `ALLOW_PLAIN_WG` | пусто | `=1` открыть порт 51820 для iOS WireGuard (без обфускации) |
|
||||
| `CHANNEL` | `stable` | канал: `stable` (ветка main) или `beta` |
|
||||
| `CHANNEL` | `stable` | канал: `stable` (открытый) · `beta`/`dev` (под ключом `PHOBOS_KEY`) |
|
||||
|
||||
После установки панель напечатает адрес, логин, пароль и **API key** — сохрани их.
|
||||
|
||||
> **Канал:** по умолчанию ставится **стабильная** версия (ветка `main`). Бета — по желанию:
|
||||
> **Каналы:**
|
||||
> - **stable** — стабильная (ветка `main`), ставится **без ключа**, по умолчанию.
|
||||
> - **beta** — кандидат в релиз (тест), **под ключом** подписчика.
|
||||
> - **dev** — активная разработка (нестабильно), **под ключом** подписчика.
|
||||
>
|
||||
> Ключ `PHOBOS_KEY` выдаётся по подписке [Boosty](https://boosty.to/andrey27). Закрытый канал:
|
||||
> ```bash
|
||||
> CHANNEL=beta bash <(curl -fsSL https://raw.githubusercontent.com/andrey271192/PCA_Phobos/main/install.sh)
|
||||
> PHOBOS_KEY=ваш_ключ CHANNEL=dev bash <(curl -fsSL https://raw.githubusercontent.com/andrey271192/PCA_Phobos/main/install.sh)
|
||||
> ```
|
||||
> Переключение после установки: `phobos-update beta` / `phobos-update main`.
|
||||
> Переключение после установки: `phobos-update stable` (без ключа) · `PHOBOS_KEY=... phobos-update beta|dev` · статус: `phobos-update --check`.
|
||||
|
||||
### Вторичный сервер (для failover / балансировки)
|
||||
|
||||
|
||||
51
app.py
51
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():
|
||||
<div class="card">
|
||||
<h2>{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.")}</h2>
|
||||
<p>{tr("Установленная версия","Installed version")}: <b style="color:#a5b4fc">{panel_version()}</b></p>
|
||||
<p style="font-size:.85em;color:#94a3b8;margin:4px 0 8px">{tr("Каналы","Channels")}:
|
||||
<b style="color:#22c55e">stable</b> — {tr("стабильная","stable")} ·
|
||||
<b style="color:#eab308">beta</b> — {tr("тест","testing")} ·
|
||||
<b style="color:#f97316">dev</b> — {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.")}</p>
|
||||
<form method="post" class="form-row" style="margin-bottom:8px">
|
||||
<input type="hidden" name="action" value="save_token">
|
||||
<input type="password" name="gh_token" placeholder="{tr('токен подписчика (для beta/dev)','subscriber token (for beta/dev)')}" style="width:240px" autocomplete="off">
|
||||
<button class="btn btn-sm" style="background:#475569" type="submit">{tr("Сохранить токен","Save token")}</button>
|
||||
<span style="font-size:.82em;color:{'#22c55e' if gh_token_present() else '#f59e0b'}">{(tr("✓ токен сохранён","✓ token saved") if gh_token_present() else tr("токен не задан — beta/dev недоступны","no token — beta/dev locked"))}</span>
|
||||
</form>
|
||||
<div class="form-row" style="gap:6px;margin-bottom:8px">
|
||||
<form method="post" style="display:inline"><input type="hidden" name="action" value="update"><input type="hidden" name="target" value="stable"><button class="btn btn-sm" style="background:#16a34a" type="submit" onclick="return confirm('{tr("Перейти на стабильную?","Switch to stable?")}')">stable</button></form>
|
||||
<form method="post" style="display:inline"><input type="hidden" name="action" value="update"><input type="hidden" name="target" value="beta"><button class="btn btn-sm" style="background:#ca8a04" type="submit" onclick="return confirm('{tr("Перейти на beta?","Switch to beta?")}')">beta</button></form>
|
||||
<form method="post" style="display:inline"><input type="hidden" name="action" value="update"><input type="hidden" name="target" value="dev"><button class="btn btn-sm" style="background:#ea580c" type="submit" onclick="return confirm('{tr("Перейти на dev (нестабильно)?","Switch to dev (unstable)?")}')">dev</button></form>
|
||||
</div>
|
||||
<form method="post" class="form-row">
|
||||
<input type="hidden" name="action" value="update">
|
||||
<input type="text" name="target" placeholder="main / beta / v1.2.3" style="width:150px">
|
||||
<input type="text" name="target" placeholder="stable / beta / dev / v1.2.4" style="width:170px">
|
||||
<button class="btn btn-primary" type="submit" onclick="return confirm('{tr("Обновить панель и скрипты?","Update panel and scripts?")}')">{tr("Обновить","Update")}</button>
|
||||
</form>
|
||||
<form method="post" style="display:inline">
|
||||
|
||||
52
install.sh
52
install.sh
@@ -25,15 +25,31 @@ PANEL_PASS="${PANEL_PASS:-OcAdmin2026!}"
|
||||
TG_TOKEN="${TG_TOKEN:-}"
|
||||
TG_CHAT="${TG_CHAT:-}"
|
||||
OBF_PORTS="${OBF_PORTS:-2083,5443,993}"
|
||||
# Канал: stable по умолчанию (ветка main). Бета — по желанию: CHANNEL=beta (или PCA_BRANCH=beta).
|
||||
# Каналы: stable (открытый, публичный repo) · beta (тест) · dev (разработка).
|
||||
# beta и dev живут в ПРИВАТНОМ repo PCA_Phobos-dev — доступ по токену подписчика
|
||||
# (GH_TOKEN, read-only, выдаётся по подписке Boosty). stable — без токена.
|
||||
GH_TOKEN="${GH_TOKEN:-}"
|
||||
PUB_REPO="andrey271192/PCA_Phobos"
|
||||
DEV_REPO="andrey271192/PCA_Phobos-dev"
|
||||
CHANNEL="${CHANNEL:-stable}"
|
||||
if [ -z "${PCA_BRANCH:-}" ]; then
|
||||
case "$CHANNEL" in beta) PCA_BRANCH="beta";; *) PCA_BRANCH="main";; esac
|
||||
case "$CHANNEL" in
|
||||
beta) REPO="$DEV_REPO"; PCA_BRANCH="${PCA_BRANCH:-beta}";;
|
||||
dev) REPO="$DEV_REPO"; PCA_BRANCH="${PCA_BRANCH:-dev}";;
|
||||
stable|main|"") REPO="$PUB_REPO"; PCA_BRANCH="${PCA_BRANCH:-main}";;
|
||||
*) REPO="$PUB_REPO"; PCA_BRANCH="${PCA_BRANCH:-$CHANNEL}";;
|
||||
esac
|
||||
if [ "$REPO" = "$DEV_REPO" ] && [ -z "$GH_TOKEN" ]; then
|
||||
echo "Канал '$CHANNEL' закрыт — это $([ "$CHANNEL" = dev ] && echo 'разработка (нестабильно)' || echo 'бета (тест)'), приватный репозиторий."
|
||||
echo "Нужен read-only токен подписчика:"
|
||||
echo " GH_TOKEN=ваш_токен CHANNEL=$CHANNEL bash <(curl -fsSL https://raw.githubusercontent.com/$PUB_REPO/main/install.sh)"
|
||||
echo "Токен выдаётся по подписке: https://boosty.to/andrey27"
|
||||
echo "Стабильная версия ставится без токена (CHANNEL=stable, по умолчанию)."
|
||||
exit 1
|
||||
fi
|
||||
GH_TOKEN="${GH_TOKEN:-}" # set for private-repo installs; empty for public
|
||||
[ "$REPO" = "$DEV_REPO" ] && echo "Токен принят — закрытый канал '$CHANNEL' (приватный repo)."
|
||||
PHOBOS_DIR="/opt/Phobos"
|
||||
PANEL_DIR="/opt/phobos-panel"
|
||||
RAW="https://raw.githubusercontent.com/andrey271192/PCA_Phobos/${PCA_BRANCH}"
|
||||
RAW="https://raw.githubusercontent.com/${REPO}/${PCA_BRANCH}"
|
||||
|
||||
[ "$EUID" -eq 0 ] || { echo "Run as root"; exit 1; }
|
||||
|
||||
@@ -69,12 +85,27 @@ if [ ! -x /usr/local/bin/wg-obfuscator ]; then
|
||||
git init -q; git remote add origin https://github.com/Ground-Zerro/Phobos.git
|
||||
git config core.sparseCheckout true; echo "wg-obfuscator" > .git/info/sparse-checkout
|
||||
git pull origin main -q
|
||||
cp -f "wg-obfuscator/bin/wg-obfuscator-${ARCH}" "$PHOBOS_DIR/bin/" 2>/dev/null || true
|
||||
cp -f "wg-obfuscator/bin/"wg-obfuscator-* "$PHOBOS_DIR/bin/" 2>/dev/null || true
|
||||
chmod +x "$PHOBOS_DIR/bin/"wg-obfuscator-* 2>/dev/null || true
|
||||
ln -sf "$PHOBOS_DIR/bin/wg-obfuscator-${ARCH}" /usr/local/bin/wg-obfuscator
|
||||
ln -sf "$PHOBOS_DIR/bin/wg-obfuscator-${ARCH}" /usr/local/bin/wg-obfuscator 2>/dev/null || true
|
||||
cd /; rm -rf "$R"
|
||||
fi
|
||||
_OBF_TAG=$(curl -fsSL -m10 https://api.github.com/repos/ClusterM/wg-obfuscator/releases/latest 2>/dev/null | grep '"tag_name"' | head -1 | sed 's/.*"tag_name": *"\(.*\)".*/\1/')
|
||||
_CB="https://github.com/ClusterM/wg-obfuscator/releases/download/${_OBF_TAG}"
|
||||
for _am in "aarch64:linux-arm64" "mipsel:linux-mipsel-mips32" "mips:linux-mips-mips32" "armv7:linux-armv7-hf"; do
|
||||
_da="${_am%%:*}"; _ss="${_am##*:}"
|
||||
if [ ! -f "$PHOBOS_DIR/bin/wg-obfuscator-${_da}" ] && [ -n "$_OBF_TAG" ]; then
|
||||
_t=$(mktemp -d)
|
||||
curl -fsSL -m30 "${_CB}/wg-obfuscator-${_OBF_TAG}-${_ss}.tar.gz" -o "$_t/o.tgz" 2>/dev/null &&
|
||||
tar -xzf "$_t/o.tgz" -C "$_t" 2>/dev/null &&
|
||||
_b=$(find "$_t" -name "wg-obfuscator" | head -1) &&
|
||||
[ -n "$_b" ] && cp "$_b" "$PHOBOS_DIR/bin/wg-obfuscator-${_da}" && chmod +x "$PHOBOS_DIR/bin/wg-obfuscator-${_da}" && echo " +wg-obfuscator-${_da} (ClusterM ${_OBF_TAG})"
|
||||
rm -rf "$_t"
|
||||
fi
|
||||
done
|
||||
[ -x /usr/local/bin/wg-obfuscator ] || ln -sf "$PHOBOS_DIR/bin/wg-obfuscator-${ARCH}" /usr/local/bin/wg-obfuscator 2>/dev/null || true
|
||||
[ -x /usr/local/bin/wg-obfuscator ] || { echo "ERROR: obfuscator binary for $ARCH missing"; exit 1; }
|
||||
echo " bins: $(ls $PHOBOS_DIR/bin/ | tr '\n' ' ')"
|
||||
|
||||
# ── 3. Phobos repo (onboarding scripts) ──
|
||||
echo "[3/9] Phobos repo (onboarding scripts)..."
|
||||
@@ -244,6 +275,13 @@ if [ -f "$PHOBOS_DIR/server/phobos-router-watchdog.py" ]; then
|
||||
fi
|
||||
|
||||
sleep 2
|
||||
# persist channel + subscriber token so phobos-update can reach private channels
|
||||
mkdir -p "$PANEL_DIR"
|
||||
echo "$CHANNEL" > "$PANEL_DIR/.channel" 2>/dev/null || true
|
||||
if [ "$REPO" = "$DEV_REPO" ] && [ -n "$GH_TOKEN" ]; then
|
||||
( umask 077; printf %s "$GH_TOKEN" > "$PANEL_DIR/.gh_token" )
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo " Installation complete"
|
||||
|
||||
99
update.sh
99
update.sh
@@ -2,24 +2,47 @@
|
||||
# ============================================================
|
||||
# PCA Phobos — updater / rollback
|
||||
#
|
||||
# phobos-update # обновить до последней версии (main)
|
||||
# phobos-update v1.1.0 # обновить до конкретной версии (git tag)
|
||||
# phobos-update # обновить до стабильной (канал stable / main)
|
||||
# phobos-update stable # стабильный канал (публичный, без токена)
|
||||
# GH_TOKEN=... phobos-update beta # бета-канал (приватный, по токену подписчика)
|
||||
# GH_TOKEN=... phobos-update dev # канал разработки (приватный, по токену)
|
||||
# phobos-update v1.2.4 # конкретная версия (git tag)
|
||||
# phobos-update --rollback # откатить на предыдущую версию (из бэкапа)
|
||||
# phobos-update --version # показать установленную и последнюю версию
|
||||
# phobos-update --check # установленная + версии всех каналов
|
||||
# phobos-update --list # список бэкапов для отката
|
||||
#
|
||||
# Обновляет ТОЛЬКО PCA-слой (панель + скрипты онбординга/служебные).
|
||||
# НЕ трогает ключи WireGuard, server.env, клиентов — они сохраняются.
|
||||
# Перед каждым обновлением делает бэкап; откат восстанавливает его.
|
||||
# Каналы:
|
||||
# stable -> публичный репозиторий andrey271192/PCA_Phobos (открыт)
|
||||
# beta / dev -> приватный andrey271192/PCA_Phobos-dev (только подписчики)
|
||||
# Для beta/dev нужен read-only токен подписчика: env GH_TOKEN или файл
|
||||
# $PANEL_DIR/.gh_token (сохраняется при установке закрытого канала).
|
||||
#
|
||||
# Обновляет ТОЛЬКО PCA-слой (панель + скрипты). НЕ трогает ключи WireGuard,
|
||||
# server.env, клиентов. Перед каждым обновлением — бэкап; откат восстанавливает.
|
||||
# ============================================================
|
||||
set -e
|
||||
PHOBOS_DIR=/opt/Phobos
|
||||
PANEL_DIR=/opt/phobos-panel
|
||||
REPO=andrey271192/PCA_Phobos
|
||||
RAW="https://raw.githubusercontent.com/$REPO"
|
||||
PUB_REPO=andrey271192/PCA_Phobos
|
||||
DEV_REPO=andrey271192/PCA_Phobos-dev
|
||||
BACKUPS="$PHOBOS_DIR/updates"
|
||||
VERFILE="$PANEL_DIR/.version"
|
||||
CUR=$(cat "$VERFILE" 2>/dev/null || echo "unknown")
|
||||
# Токен подписчика для приватных каналов: env > сохранённый файл
|
||||
GH_TOKEN="${GH_TOKEN:-$(cat "$PANEL_DIR/.gh_token" 2>/dev/null || true)}"
|
||||
|
||||
# repo for a ref/channel: beta/dev/*-beta/*-dev -> private, остальное -> public
|
||||
repo_for() { case "$1" in beta|dev|*-beta|*-dev) echo "$DEV_REPO";; *) echo "$PUB_REPO";; esac; }
|
||||
is_private() { case "$1" in beta|dev|*-beta|*-dev) return 0;; *) return 1;; esac; }
|
||||
# curl with token header only when ref is a private channel
|
||||
gh_curl() { # $1=ref, rest=curl args
|
||||
local ref="$1"; shift
|
||||
if is_private "$ref" && [ -n "$GH_TOKEN" ]; then
|
||||
curl -H "Authorization: token $GH_TOKEN" "$@"
|
||||
else
|
||||
curl "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
managed_files() {
|
||||
cat <<LIST
|
||||
@@ -35,7 +58,13 @@ $PHOBOS_DIR/server/update.sh|update.sh
|
||||
LIST
|
||||
}
|
||||
|
||||
latest_version() { curl -fsSL -m10 "$RAW/main/VERSION" 2>/dev/null | tr -d ' \r\n'; }
|
||||
# fetch VERSION of a channel (public repos / or private if token present)
|
||||
chan_version() { # $1 = ref(channel)
|
||||
local repo; repo=$(repo_for "$1"); local repo_ref="$1"
|
||||
if is_private "$1" && [ -z "$GH_TOKEN" ]; then echo ""; return; fi
|
||||
gh_curl "$1" -fsSL -m8 "https://raw.githubusercontent.com/$repo/$1/VERSION" 2>/dev/null | tr -d ' \r\n'
|
||||
}
|
||||
latest_version() { curl -fsSL -m10 "https://raw.githubusercontent.com/$PUB_REPO/main/VERSION" 2>/dev/null | tr -d ' \r\n'; }
|
||||
|
||||
do_backup() {
|
||||
local dir="$BACKUPS/${CUR}-$(date +%Y%m%d-%H%M%S)"
|
||||
@@ -48,10 +77,12 @@ do_backup() {
|
||||
}
|
||||
|
||||
apply_ref() {
|
||||
local ref="$1"
|
||||
local ref="$1"; local repo; repo=$(repo_for "$ref")
|
||||
local repo_ref="$ref"
|
||||
local RAW="https://raw.githubusercontent.com/$repo/$ref"
|
||||
managed_files | while IFS='|' read -r lp rp; do
|
||||
local tmp; tmp=$(mktemp)
|
||||
if curl -fsSL -m25 "$RAW/$ref/$rp" -o "$tmp" && [ -s "$tmp" ]; then
|
||||
if gh_curl "$ref" -fsSL -m25 "$RAW/$rp" -o "$tmp" && [ -s "$tmp" ]; then
|
||||
mkdir -p "$(dirname "$lp")"; mv "$tmp" "$lp"
|
||||
case "$lp" in *.sh|*.py) chmod +x "$lp" 2>/dev/null || true;; esac
|
||||
else
|
||||
@@ -60,19 +91,33 @@ apply_ref() {
|
||||
done
|
||||
}
|
||||
|
||||
ref_exists() { curl -fsSL -m12 "$RAW/$1/app.py" -o /dev/null 2>/dev/null; }
|
||||
ref_exists() {
|
||||
local repo; repo=$(repo_for "$1"); local repo_ref="$1"
|
||||
gh_curl "$1" -fsSL -m12 "https://raw.githubusercontent.com/$repo/$1/app.py" -o /dev/null 2>/dev/null
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
--version|-v|--check)
|
||||
echo "Установлено: $CUR"
|
||||
echo "Стабильная: $(latest_version)"
|
||||
beta=$(curl -fsSL -m8 "$RAW/beta/VERSION" 2>/dev/null | tr -d ' \r\n')
|
||||
[ -n "$beta" ] && echo "Бета (beta): $beta"
|
||||
echo "Стабильная: $(latest_version) [открытый]"
|
||||
b=$(chan_version beta); d=$(chan_version dev)
|
||||
if [ -n "$GH_TOKEN" ]; then
|
||||
[ -n "$b" ] && echo "Бета (beta): $b [приватный, токен ок]"
|
||||
[ -n "$d" ] && echo "Разработка(dev):$d [приватный, токен ок]"
|
||||
else
|
||||
echo "Бета (beta): — [приватный: нужен GH_TOKEN подписчика]"
|
||||
echo "Разработка(dev):— [приватный: нужен GH_TOKEN подписчика]"
|
||||
fi
|
||||
;;
|
||||
--versions|--tags)
|
||||
echo "Доступные версии (git tags):"
|
||||
curl -fsSL -m10 "https://api.github.com/repos/$REPO/tags?per_page=100" 2>/dev/null \
|
||||
echo "Стабильные версии (публичные теги):"
|
||||
curl -fsSL -m10 "https://api.github.com/repos/$PUB_REPO/tags?per_page=100" 2>/dev/null \
|
||||
| grep -oE '"name": *"[^"]+"' | sed 's/.*"name": *"\(.*\)"/ \1/' || echo " (нет данных)"
|
||||
if [ -n "$GH_TOKEN" ]; then
|
||||
echo "Закрытые версии (приватные теги, beta/dev):"
|
||||
curl -fsSL -m10 -H "Authorization: token $GH_TOKEN" "https://api.github.com/repos/$DEV_REPO/tags?per_page=100" 2>/dev/null \
|
||||
| grep -oE '"name": *"[^"]+"' | sed 's/.*"name": *"\(.*\)"/ \1/' || echo " (нет данных)"
|
||||
fi
|
||||
;;
|
||||
--list)
|
||||
echo "Бэкапы (для отката):"
|
||||
@@ -91,13 +136,27 @@ case "${1:-}" in
|
||||
echo "Откат выполнен -> $fromver"
|
||||
;;
|
||||
*)
|
||||
ref="${1:-main}"; [ "$ref" = "latest" ] && ref="main"
|
||||
ref="${1:-main}"
|
||||
case "$ref" in latest|stable) ref="main";; esac
|
||||
# Каналы beta/dev — приватный репозиторий, нужен токен подписчика
|
||||
if is_private "$ref" && [ -z "$GH_TOKEN" ]; then
|
||||
echo "Канал '$ref' закрыт (бета/разработка) — приватный репозиторий."
|
||||
echo "Нужен read-only токен подписчика:"
|
||||
echo " GH_TOKEN=ваш_токен phobos-update $ref"
|
||||
echo "Токен — по подписке: https://boosty.to/andrey27 . Стабильная (без токена): phobos-update stable"
|
||||
exit 1
|
||||
fi
|
||||
if ! ref_exists "$ref"; then
|
||||
echo "Версия/ветка '$ref' не найдена на GitHub. Обновление отменено (текущая $CUR не тронута)."
|
||||
echo "Версия/ветка '$ref' не найдена (или токен неверный). Обновление отменено (текущая $CUR не тронута)."
|
||||
echo "Доступные: phobos-update --versions · стабильная: $(latest_version)"
|
||||
exit 1
|
||||
fi
|
||||
target=$(curl -fsSL -m10 "$RAW/$ref/VERSION" 2>/dev/null | tr -d ' \r\n'); [ -z "$target" ] && target="$ref"
|
||||
# сохранить токен для будущих обновлений приватного канала
|
||||
if is_private "$ref" && [ -n "$GH_TOKEN" ]; then
|
||||
( umask 077; printf %s "$GH_TOKEN" > "$PANEL_DIR/.gh_token" )
|
||||
fi
|
||||
repo_ref="$ref"
|
||||
target=$(gh_curl "$ref" -fsSL -m10 "https://raw.githubusercontent.com/$(repo_for "$ref")/$ref/VERSION" 2>/dev/null | tr -d ' \r\n'); [ -z "$target" ] && target="$ref"
|
||||
echo "Текущая: $CUR -> целевая: $target ($ref)"
|
||||
b=$(do_backup); echo "Бэкап: $b"
|
||||
apply_ref "$ref"
|
||||
|
||||
Reference in New Issue
Block a user