Флаг --daily ставит cron, который раз в сутки заново качает launcher со свежим токеном. Снять: --remove-daily. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -93,9 +93,10 @@ vps-tracker/
|
|||||||
## Статус блокировок (censorcheck)
|
## Статус блокировок (censorcheck)
|
||||||
|
|
||||||
Ручная проверка с VPS: `curl -fsSL https://vt.shnt.top/cc | bash` (тот же контейнер, Traefik dual Host).
|
Ручная проверка с VPS: `curl -fsSL https://vt.shnt.top/cc | bash` (тот же контейнер, Traefik dual Host).
|
||||||
|
Раз в сутки: `curl -fsSL https://vt.shnt.top/cc | bash -s -- --daily` (cron, свежий HMAC-токен на каждый запуск).
|
||||||
|
|
||||||
- **Vendor:** `apps/api/scripts/censorcheck/censorcheck.sh` (pin SHA `12c5839`, MIT)
|
- **Vendor:** `apps/api/scripts/censorcheck/censorcheck.sh` (pin SHA `12c5839`, MIT)
|
||||||
- **Launcher:** `GET /cc` минтит HMAC ingest-токен (TTL 20 мин); по `/etc/os-release` ставит `jq`/`dig`/`column` без prompt; прогресс-бар в stderr; `GET /cc/vendor` — скрипт (LF)
|
- **Launcher:** `GET /cc` минтит HMAC ingest-токен (TTL 20 мин); по `/etc/os-release` ставит `jq`/`dig`/`column` без prompt; прогресс-бар в stderr; `GET /cc/vendor` — скрипт (LF); `--daily` / `--remove-daily`
|
||||||
- **Ingest:** `POST /api/integrations/censorcheck/runs` (без portal JWT)
|
- **Ingest:** `POST /api/integrations/censorcheck/runs` (без portal JWT)
|
||||||
- **UI:** `/blocking` — текущие прогоны и история, группировка VPS / сервис
|
- **UI:** `/blocking` — текущие прогоны и история, группировка VPS / сервис
|
||||||
- Env: `CENSORCHECK_INGEST_SECRET`, `CENSORCHECK_PUBLIC_URL`, `VPS_LAUNCHER_DOMAIN`
|
- Env: `CENSORCHECK_INGEST_SECRET`, `CENSORCHECK_PUBLIC_URL`, `VPS_LAUNCHER_DOMAIN`
|
||||||
@@ -103,9 +104,10 @@ vps-tracker/
|
|||||||
## GeoIP (ipregion)
|
## GeoIP (ipregion)
|
||||||
|
|
||||||
Ручная проверка с VPS: `curl -fsSL https://vt.shnt.top/ic | bash`.
|
Ручная проверка с VPS: `curl -fsSL https://vt.shnt.top/ic | bash`.
|
||||||
|
Раз в сутки: `curl -fsSL https://vt.shnt.top/ic | bash -s -- --daily`.
|
||||||
|
|
||||||
- **Vendor:** `apps/api/scripts/ipregion/ipregion.sh` (pin SHA `7d1c25c`, MIT, [vernette/ipregion](https://github.com/vernette/ipregion))
|
- **Vendor:** `apps/api/scripts/ipregion/ipregion.sh` (pin SHA `7d1c25c`, MIT, [vernette/ipregion](https://github.com/vernette/ipregion))
|
||||||
- **Launcher:** `GET /ic` минтит HMAC ingest-токен (тот же `CENSORCHECK_INGEST_SECRET`); `GET /ic/vendor` — pinned скрипт (LF)
|
- **Launcher:** `GET /ic` минтит HMAC ingest-токен (тот же `CENSORCHECK_INGEST_SECRET`); `GET /ic/vendor` — pinned скрипт (LF); `--daily` / `--remove-daily`
|
||||||
- **Ingest:** `POST /api/integrations/ipregion/runs` (без portal JWT)
|
- **Ingest:** `POST /api/integrations/ipregion/runs` (без portal JWT)
|
||||||
- **UI:** `/geo` — матрица ISO-стран VPS × сервисы (primary / custom / cdn)
|
- **UI:** `/geo` — матрица ISO-стран VPS × сервисы (primary / custom / cdn)
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ set -euo pipefail
|
|||||||
|
|
||||||
VT_API_URL="${VT_API_URL:-__VT_API_URL__}"
|
VT_API_URL="${VT_API_URL:-__VT_API_URL__}"
|
||||||
VT_INGEST_TOKEN="${VT_INGEST_TOKEN:-__VT_INGEST_TOKEN__}"
|
VT_INGEST_TOKEN="${VT_INGEST_TOKEN:-__VT_INGEST_TOKEN__}"
|
||||||
LAUNCHER_VERSION="5"
|
LAUNCHER_VERSION="6"
|
||||||
VENDOR_SHA="12c5839"
|
VENDOR_SHA="12c5839"
|
||||||
|
DAILY_SLUG="vt-censorcheck"
|
||||||
|
DAILY_PATH="/cc"
|
||||||
|
|
||||||
OS_ID="unknown"
|
OS_ID="unknown"
|
||||||
OS_LIKE=""
|
OS_LIKE=""
|
||||||
@@ -247,6 +249,102 @@ detect_hoster() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
show_launcher_help() {
|
||||||
|
cat <<EOF
|
||||||
|
Использование:
|
||||||
|
curl -fsSL ${VT_API_URL}${DAILY_PATH} | bash
|
||||||
|
curl -fsSL ${VT_API_URL}${DAILY_PATH} | bash -s -- --daily
|
||||||
|
curl -fsSL ${VT_API_URL}${DAILY_PATH} | bash -s -- --remove-daily
|
||||||
|
|
||||||
|
--daily выполнить проверку и поставить cron раз в сутки
|
||||||
|
--remove-daily убрать ежедневный cron
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
daily_run_cmd() {
|
||||||
|
local url="${VT_API_URL}${DAILY_PATH}"
|
||||||
|
local curl_bin bash_bin flock_bin
|
||||||
|
curl_bin="$(command -v curl)"
|
||||||
|
bash_bin="$(command -v bash)"
|
||||||
|
flock_bin="$(command -v flock || true)"
|
||||||
|
if [ -n "$flock_bin" ]; then
|
||||||
|
printf "%s -n /tmp/%s.lock -c '%s -fsSL --max-time 180 %s | %s'" \
|
||||||
|
"$flock_bin" "$DAILY_SLUG" "$curl_bin" "$url" "$bash_bin"
|
||||||
|
else
|
||||||
|
printf '%s -fsSL --max-time 180 %s | %s' "$curl_bin" "$url" "$bash_bin"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
daily_slot() {
|
||||||
|
local seed n
|
||||||
|
seed="$(hostname -f 2>/dev/null || hostname 2>/dev/null || cat /etc/hostname 2>/dev/null || echo vt)"
|
||||||
|
n="$(printf '%s' "$seed" | cksum | awk '{print $1}')"
|
||||||
|
DAILY_MINUTE=$((n % 60))
|
||||||
|
DAILY_HOUR=$((3 + (n / 60) % 4))
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_daily() {
|
||||||
|
local prefix="" removed=0
|
||||||
|
if [ -e "/etc/cron.d/${DAILY_SLUG}" ]; then
|
||||||
|
if prefix="$(root_prefix)"; then
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
$prefix rm -f "/etc/cron.d/${DAILY_SLUG}"
|
||||||
|
removed=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if command -v crontab >/dev/null 2>&1; then
|
||||||
|
local current
|
||||||
|
current="$(crontab -l 2>/dev/null || true)"
|
||||||
|
if printf '%s\n' "$current" | grep -qF "vps-tracker:${DAILY_SLUG}"; then
|
||||||
|
printf '%s\n' "$current" | grep -vF "vps-tracker:${DAILY_SLUG}" | crontab -
|
||||||
|
removed=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ "$removed" -eq 1 ]; then
|
||||||
|
log "Ежедневная проверка снята (${DAILY_SLUG})"
|
||||||
|
else
|
||||||
|
log "Ежедневная проверка не была установлена"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
install_daily() {
|
||||||
|
daily_slot
|
||||||
|
local run line prefix=""
|
||||||
|
local marker="# vps-tracker:${DAILY_SLUG}"
|
||||||
|
run="$(daily_run_cmd)"
|
||||||
|
|
||||||
|
if [ -d /etc/cron.d ] && prefix="$(root_prefix)"; then
|
||||||
|
local tmp
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
cat >"$tmp" <<EOF
|
||||||
|
# Managed by VPS Tracker launcher. ${marker}
|
||||||
|
SHELL=/bin/bash
|
||||||
|
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||||
|
MAILTO=""
|
||||||
|
${DAILY_MINUTE} ${DAILY_HOUR} * * * root ${run} >>/var/log/${DAILY_SLUG}.log 2>&1
|
||||||
|
EOF
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
$prefix cp "$tmp" "/etc/cron.d/${DAILY_SLUG}"
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
$prefix chmod 644 "/etc/cron.d/${DAILY_SLUG}"
|
||||||
|
rm -f "$tmp"
|
||||||
|
log "Ежедневная проверка: каждый день в ${DAILY_HOUR}:$(printf '%02d' "$DAILY_MINUTE") (/etc/cron.d/${DAILY_SLUG})"
|
||||||
|
log "Снять: curl -fsSL ${VT_API_URL}${DAILY_PATH} | bash -s -- --remove-daily"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v crontab >/dev/null 2>&1; then
|
||||||
|
die "Нет cron (ни /etc/cron.d, ни crontab). Установите пакет cron и повторите --daily"
|
||||||
|
fi
|
||||||
|
line="${DAILY_MINUTE} ${DAILY_HOUR} * * * ${run} >>/tmp/${DAILY_SLUG}.log 2>&1 ${marker}"
|
||||||
|
{
|
||||||
|
(crontab -l 2>/dev/null || true) | grep -vF "vps-tracker:${DAILY_SLUG}" || true
|
||||||
|
printf '%s\n' "$line"
|
||||||
|
} | crontab -
|
||||||
|
log "Ежедневная проверка: каждый день в ${DAILY_HOUR}:$(printf '%02d' "$DAILY_MINUTE") (crontab)"
|
||||||
|
log "Снять: curl -fsSL ${VT_API_URL}${DAILY_PATH} | bash -s -- --remove-daily"
|
||||||
|
}
|
||||||
|
|
||||||
write_vendor() {
|
write_vendor() {
|
||||||
local dest="$1"
|
local dest="$1"
|
||||||
if [ -n "${CENSORCHECK_VENDOR_B64:-}" ]; then
|
if [ -n "${CENSORCHECK_VENDOR_B64:-}" ]; then
|
||||||
@@ -273,6 +371,22 @@ VT_API_URL="${VT_API_URL%/}"
|
|||||||
[ -n "$VT_API_URL" ] || die "VT_API_URL пуст"
|
[ -n "$VT_API_URL" ] || die "VT_API_URL пуст"
|
||||||
[ -n "$VT_INGEST_TOKEN" ] || die "VT_INGEST_TOKEN пуст"
|
[ -n "$VT_INGEST_TOKEN" ] || die "VT_INGEST_TOKEN пуст"
|
||||||
|
|
||||||
|
DAILY_INSTALL=0
|
||||||
|
DAILY_REMOVE=0
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
--daily|--install-daily) DAILY_INSTALL=1 ;;
|
||||||
|
--remove-daily|--uninstall-daily) DAILY_REMOVE=1 ;;
|
||||||
|
-h|--help) show_launcher_help; exit 0 ;;
|
||||||
|
*) die "Неизвестный аргумент: $arg. См. --help" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$DAILY_REMOVE" -eq 1 ]; then
|
||||||
|
remove_daily
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
TMPDIR="$(mktemp -d /tmp/vt-censorcheck.XXXXXX)"
|
TMPDIR="$(mktemp -d /tmp/vt-censorcheck.XXXXXX)"
|
||||||
cleanup() { rm -rf "$TMPDIR"; }
|
cleanup() { rm -rf "$TMPDIR"; }
|
||||||
trap 'cleanup; exit 130' INT
|
trap 'cleanup; exit 130' INT
|
||||||
@@ -336,6 +450,9 @@ set -e
|
|||||||
if [ "$POST_EXIT" -ne 0 ]; then
|
if [ "$POST_EXIT" -ne 0 ]; then
|
||||||
cp "$PAYLOAD" "$FALLBACK"
|
cp "$PAYLOAD" "$FALLBACK"
|
||||||
log "API недоступен (curl exit ${POST_EXIT}). JSON сохранён: ${FALLBACK}" >&2
|
log "API недоступен (curl exit ${POST_EXIT}). JSON сохранён: ${FALLBACK}" >&2
|
||||||
|
if [ "$DAILY_INSTALL" -eq 1 ]; then
|
||||||
|
install_daily
|
||||||
|
fi
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -345,9 +462,15 @@ if [ -z "$CHECK_ID" ]; then
|
|||||||
cp "$PAYLOAD" "$FALLBACK"
|
cp "$PAYLOAD" "$FALLBACK"
|
||||||
log "Некорректный ответ API. JSON сохранён: ${FALLBACK}" >&2
|
log "Некорректный ответ API. JSON сохранён: ${FALLBACK}" >&2
|
||||||
log "$RESP" >&2
|
log "$RESP" >&2
|
||||||
|
if [ "$DAILY_INSTALL" -eq 1 ]; then
|
||||||
|
install_daily
|
||||||
|
fi
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log "Check ID: ${CHECK_ID}"
|
log "Check ID: ${CHECK_ID}"
|
||||||
log "VPS: ${MATCHED}"
|
log "VPS: ${MATCHED}"
|
||||||
|
if [ "$DAILY_INSTALL" -eq 1 ]; then
|
||||||
|
install_daily
|
||||||
|
fi
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ set -euo pipefail
|
|||||||
|
|
||||||
VT_API_URL="${VT_API_URL:-__VT_API_URL__}"
|
VT_API_URL="${VT_API_URL:-__VT_API_URL__}"
|
||||||
VT_INGEST_TOKEN="${VT_INGEST_TOKEN:-__VT_INGEST_TOKEN__}"
|
VT_INGEST_TOKEN="${VT_INGEST_TOKEN:-__VT_INGEST_TOKEN__}"
|
||||||
LAUNCHER_VERSION="1"
|
LAUNCHER_VERSION="2"
|
||||||
VENDOR_SHA="7d1c25c"
|
VENDOR_SHA="7d1c25c"
|
||||||
|
DAILY_SLUG="vt-ipregion"
|
||||||
|
DAILY_PATH="/ic"
|
||||||
|
|
||||||
OS_ID="unknown"
|
OS_ID="unknown"
|
||||||
OS_LIKE=""
|
OS_LIKE=""
|
||||||
@@ -247,6 +249,102 @@ detect_hoster() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
show_launcher_help() {
|
||||||
|
cat <<EOF
|
||||||
|
Использование:
|
||||||
|
curl -fsSL ${VT_API_URL}${DAILY_PATH} | bash
|
||||||
|
curl -fsSL ${VT_API_URL}${DAILY_PATH} | bash -s -- --daily
|
||||||
|
curl -fsSL ${VT_API_URL}${DAILY_PATH} | bash -s -- --remove-daily
|
||||||
|
|
||||||
|
--daily выполнить проверку и поставить cron раз в сутки
|
||||||
|
--remove-daily убрать ежедневный cron
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
daily_run_cmd() {
|
||||||
|
local url="${VT_API_URL}${DAILY_PATH}"
|
||||||
|
local curl_bin bash_bin flock_bin
|
||||||
|
curl_bin="$(command -v curl)"
|
||||||
|
bash_bin="$(command -v bash)"
|
||||||
|
flock_bin="$(command -v flock || true)"
|
||||||
|
if [ -n "$flock_bin" ]; then
|
||||||
|
printf "%s -n /tmp/%s.lock -c '%s -fsSL --max-time 180 %s | %s'" \
|
||||||
|
"$flock_bin" "$DAILY_SLUG" "$curl_bin" "$url" "$bash_bin"
|
||||||
|
else
|
||||||
|
printf '%s -fsSL --max-time 180 %s | %s' "$curl_bin" "$url" "$bash_bin"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
daily_slot() {
|
||||||
|
local seed n
|
||||||
|
seed="$(hostname -f 2>/dev/null || hostname 2>/dev/null || cat /etc/hostname 2>/dev/null || echo vt)"
|
||||||
|
n="$(printf '%s' "$seed" | cksum | awk '{print $1}')"
|
||||||
|
DAILY_MINUTE=$((n % 60))
|
||||||
|
DAILY_HOUR=$((3 + (n / 60) % 4))
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_daily() {
|
||||||
|
local prefix="" removed=0
|
||||||
|
if [ -e "/etc/cron.d/${DAILY_SLUG}" ]; then
|
||||||
|
if prefix="$(root_prefix)"; then
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
$prefix rm -f "/etc/cron.d/${DAILY_SLUG}"
|
||||||
|
removed=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if command -v crontab >/dev/null 2>&1; then
|
||||||
|
local current
|
||||||
|
current="$(crontab -l 2>/dev/null || true)"
|
||||||
|
if printf '%s\n' "$current" | grep -qF "vps-tracker:${DAILY_SLUG}"; then
|
||||||
|
printf '%s\n' "$current" | grep -vF "vps-tracker:${DAILY_SLUG}" | crontab -
|
||||||
|
removed=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ "$removed" -eq 1 ]; then
|
||||||
|
log "Ежедневная проверка снята (${DAILY_SLUG})"
|
||||||
|
else
|
||||||
|
log "Ежедневная проверка не была установлена"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
install_daily() {
|
||||||
|
daily_slot
|
||||||
|
local run line prefix=""
|
||||||
|
local marker="# vps-tracker:${DAILY_SLUG}"
|
||||||
|
run="$(daily_run_cmd)"
|
||||||
|
|
||||||
|
if [ -d /etc/cron.d ] && prefix="$(root_prefix)"; then
|
||||||
|
local tmp
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
cat >"$tmp" <<EOF
|
||||||
|
# Managed by VPS Tracker launcher. ${marker}
|
||||||
|
SHELL=/bin/bash
|
||||||
|
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||||
|
MAILTO=""
|
||||||
|
${DAILY_MINUTE} ${DAILY_HOUR} * * * root ${run} >>/var/log/${DAILY_SLUG}.log 2>&1
|
||||||
|
EOF
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
$prefix cp "$tmp" "/etc/cron.d/${DAILY_SLUG}"
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
$prefix chmod 644 "/etc/cron.d/${DAILY_SLUG}"
|
||||||
|
rm -f "$tmp"
|
||||||
|
log "Ежедневная проверка: каждый день в ${DAILY_HOUR}:$(printf '%02d' "$DAILY_MINUTE") (/etc/cron.d/${DAILY_SLUG})"
|
||||||
|
log "Снять: curl -fsSL ${VT_API_URL}${DAILY_PATH} | bash -s -- --remove-daily"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v crontab >/dev/null 2>&1; then
|
||||||
|
die "Нет cron (ни /etc/cron.d, ни crontab). Установите пакет cron и повторите --daily"
|
||||||
|
fi
|
||||||
|
line="${DAILY_MINUTE} ${DAILY_HOUR} * * * ${run} >>/tmp/${DAILY_SLUG}.log 2>&1 ${marker}"
|
||||||
|
{
|
||||||
|
(crontab -l 2>/dev/null || true) | grep -vF "vps-tracker:${DAILY_SLUG}" || true
|
||||||
|
printf '%s\n' "$line"
|
||||||
|
} | crontab -
|
||||||
|
log "Ежедневная проверка: каждый день в ${DAILY_HOUR}:$(printf '%02d' "$DAILY_MINUTE") (crontab)"
|
||||||
|
log "Снять: curl -fsSL ${VT_API_URL}${DAILY_PATH} | bash -s -- --remove-daily"
|
||||||
|
}
|
||||||
|
|
||||||
write_vendor() {
|
write_vendor() {
|
||||||
local dest="$1"
|
local dest="$1"
|
||||||
if [ -n "${IPREGION_VENDOR_B64:-}" ]; then
|
if [ -n "${IPREGION_VENDOR_B64:-}" ]; then
|
||||||
@@ -273,6 +371,22 @@ VT_API_URL="${VT_API_URL%/}"
|
|||||||
[ -n "$VT_API_URL" ] || die "VT_API_URL пуст"
|
[ -n "$VT_API_URL" ] || die "VT_API_URL пуст"
|
||||||
[ -n "$VT_INGEST_TOKEN" ] || die "VT_INGEST_TOKEN пуст"
|
[ -n "$VT_INGEST_TOKEN" ] || die "VT_INGEST_TOKEN пуст"
|
||||||
|
|
||||||
|
DAILY_INSTALL=0
|
||||||
|
DAILY_REMOVE=0
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
--daily|--install-daily) DAILY_INSTALL=1 ;;
|
||||||
|
--remove-daily|--uninstall-daily) DAILY_REMOVE=1 ;;
|
||||||
|
-h|--help) show_launcher_help; exit 0 ;;
|
||||||
|
*) die "Неизвестный аргумент: $arg. См. --help" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$DAILY_REMOVE" -eq 1 ]; then
|
||||||
|
remove_daily
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
TMPDIR="$(mktemp -d /tmp/vt-ipregion.XXXXXX)"
|
TMPDIR="$(mktemp -d /tmp/vt-ipregion.XXXXXX)"
|
||||||
cleanup() { rm -rf "$TMPDIR"; }
|
cleanup() { rm -rf "$TMPDIR"; }
|
||||||
trap 'cleanup; exit 130' INT
|
trap 'cleanup; exit 130' INT
|
||||||
@@ -339,6 +453,9 @@ set -e
|
|||||||
if [ "$POST_EXIT" -ne 0 ]; then
|
if [ "$POST_EXIT" -ne 0 ]; then
|
||||||
cp "$PAYLOAD" "$FALLBACK"
|
cp "$PAYLOAD" "$FALLBACK"
|
||||||
log "API недоступен (curl exit ${POST_EXIT}). JSON сохранён: ${FALLBACK}" >&2
|
log "API недоступен (curl exit ${POST_EXIT}). JSON сохранён: ${FALLBACK}" >&2
|
||||||
|
if [ "$DAILY_INSTALL" -eq 1 ]; then
|
||||||
|
install_daily
|
||||||
|
fi
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -348,9 +465,15 @@ if [ -z "$CHECK_ID" ]; then
|
|||||||
cp "$PAYLOAD" "$FALLBACK"
|
cp "$PAYLOAD" "$FALLBACK"
|
||||||
log "Некорректный ответ API. JSON сохранён: ${FALLBACK}" >&2
|
log "Некорректный ответ API. JSON сохранён: ${FALLBACK}" >&2
|
||||||
log "$RESP" >&2
|
log "$RESP" >&2
|
||||||
|
if [ "$DAILY_INSTALL" -eq 1 ]; then
|
||||||
|
install_daily
|
||||||
|
fi
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log "Check ID: ${CHECK_ID}"
|
log "Check ID: ${CHECK_ID}"
|
||||||
log "VPS: ${MATCHED}"
|
log "VPS: ${MATCHED}"
|
||||||
|
if [ "$DAILY_INSTALL" -eq 1 ]; then
|
||||||
|
install_daily
|
||||||
|
fi
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -33,6 +33,11 @@ describe('GET /cc launcher', () => {
|
|||||||
expect(res.body).toContain('/etc/os-release')
|
expect(res.body).toContain('/etc/os-release')
|
||||||
expect(res.body).toContain('apt-get install -y -qq')
|
expect(res.body).toContain('apt-get install -y -qq')
|
||||||
expect(res.body).toContain('Проверяю сайты')
|
expect(res.body).toContain('Проверяю сайты')
|
||||||
|
expect(res.body).toContain('--daily')
|
||||||
|
expect(res.body).toContain('--remove-daily')
|
||||||
|
expect(res.body).toContain('DAILY_SLUG="vt-censorcheck"')
|
||||||
|
expect(res.body).toContain('vps-tracker:${DAILY_SLUG}')
|
||||||
|
expect(res.body).toContain('/etc/cron.d')
|
||||||
expect(res.body).not.toContain('2>/tmp/vt-censorcheck-err')
|
expect(res.body).not.toContain('2>/tmp/vt-censorcheck-err')
|
||||||
expect(res.body).not.toContain('\r')
|
expect(res.body).not.toContain('\r')
|
||||||
expect(res.body).not.toContain('__VT_API_URL__')
|
expect(res.body).not.toContain('__VT_API_URL__')
|
||||||
@@ -80,6 +85,10 @@ describe('GET /ic launcher', () => {
|
|||||||
expect(res.body).toContain('/api/integrations/ipregion/runs')
|
expect(res.body).toContain('/api/integrations/ipregion/runs')
|
||||||
expect(res.body).toContain('/ic/vendor')
|
expect(res.body).toContain('/ic/vendor')
|
||||||
expect(res.body).toContain('7d1c25c')
|
expect(res.body).toContain('7d1c25c')
|
||||||
|
expect(res.body).toContain('--daily')
|
||||||
|
expect(res.body).toContain('--remove-daily')
|
||||||
|
expect(res.body).toContain('DAILY_SLUG="vt-ipregion"')
|
||||||
|
expect(res.body).toContain('vps-tracker:${DAILY_SLUG}')
|
||||||
expect(res.body).not.toContain('\r')
|
expect(res.body).not.toContain('\r')
|
||||||
expect(res.body).not.toContain('__VT_API_URL__')
|
expect(res.body).not.toContain('__VT_API_URL__')
|
||||||
expect(res.body).not.toContain('__VT_INGEST_TOKEN__')
|
expect(res.body).not.toContain('__VT_INGEST_TOKEN__')
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { useMemo, useState } from 'react'
|
|||||||
import { useQuery } from '@tanstack/react-query'
|
import { useQuery } from '@tanstack/react-query'
|
||||||
import {
|
import {
|
||||||
BanIcon,
|
BanIcon,
|
||||||
|
CalendarClockIcon,
|
||||||
CopyIcon,
|
CopyIcon,
|
||||||
GlobeIcon,
|
GlobeIcon,
|
||||||
ServerIcon,
|
ServerIcon,
|
||||||
@@ -38,6 +39,7 @@ import { filterCensorcheckRuns, serviceMatrixRows } from './blocking-filters'
|
|||||||
import {
|
import {
|
||||||
CENSORCHECK_STATUS_LABELS,
|
CENSORCHECK_STATUS_LABELS,
|
||||||
LAUNCHER_CMD,
|
LAUNCHER_CMD,
|
||||||
|
LAUNCHER_CMD_DAILY,
|
||||||
formatCheckedAt,
|
formatCheckedAt,
|
||||||
type CensorcheckRunDto,
|
type CensorcheckRunDto,
|
||||||
} from './types'
|
} from './types'
|
||||||
@@ -143,14 +145,24 @@ export function BlockingPage() {
|
|||||||
const blocked = filtered.reduce((sum, row) => sum + row.summary.blocked, 0)
|
const blocked = filtered.reduce((sum, row) => sum + row.summary.blocked, 0)
|
||||||
|
|
||||||
const copyLauncher = (
|
const copyLauncher = (
|
||||||
<Button
|
<>
|
||||||
type="button"
|
<Button
|
||||||
variant="outline"
|
type="button"
|
||||||
onClick={() => void copyText(LAUNCHER_CMD, 'Команда скопирована')}
|
variant="outline"
|
||||||
>
|
onClick={() => void copyText(LAUNCHER_CMD, 'Команда скопирована')}
|
||||||
<CopyIcon data-icon="inline-start" />
|
>
|
||||||
Скопировать команду
|
<CopyIcon data-icon="inline-start" />
|
||||||
</Button>
|
Скопировать команду
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => void copyText(LAUNCHER_CMD_DAILY, 'Команда для ежедневного запуска скопирована')}
|
||||||
|
>
|
||||||
|
<CalendarClockIcon data-icon="inline-start" />
|
||||||
|
Раз в день
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ export const CENSORCHECK_STATUS_LABELS: Record<string, string> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const LAUNCHER_CMD = 'curl -fsSL https://vt.shnt.top/cc | bash'
|
export const LAUNCHER_CMD = 'curl -fsSL https://vt.shnt.top/cc | bash'
|
||||||
|
export const LAUNCHER_CMD_DAILY = 'curl -fsSL https://vt.shnt.top/cc | bash -s -- --daily'
|
||||||
|
|
||||||
export function formatVpsResources(vcpu: number, ramGb: number, diskGb: number): string {
|
export function formatVpsResources(vcpu: number, ramGb: number, diskGb: number): string {
|
||||||
return `${vcpu} vCPU / ${ramGb} GB / ${diskGb} GB`
|
return `${vcpu} vCPU / ${ramGb} GB / ${diskGb} GB`
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useMemo, useState } from 'react'
|
import { useMemo, useState } from 'react'
|
||||||
import { useQuery } from '@tanstack/react-query'
|
import { useQuery } from '@tanstack/react-query'
|
||||||
import {
|
import {
|
||||||
|
CalendarClockIcon,
|
||||||
CopyIcon,
|
CopyIcon,
|
||||||
GlobeIcon,
|
GlobeIcon,
|
||||||
MapPinIcon,
|
MapPinIcon,
|
||||||
@@ -43,6 +44,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
IPREGION_STATUS_LABELS,
|
IPREGION_STATUS_LABELS,
|
||||||
LAUNCHER_CMD,
|
LAUNCHER_CMD,
|
||||||
|
LAUNCHER_CMD_DAILY,
|
||||||
formatCheckedAt,
|
formatCheckedAt,
|
||||||
type IpregionRunDto,
|
type IpregionRunDto,
|
||||||
} from './types'
|
} from './types'
|
||||||
@@ -148,14 +150,24 @@ export function GeoPage() {
|
|||||||
const mismatches = filtered.filter(isGeoMismatch).length
|
const mismatches = filtered.filter(isGeoMismatch).length
|
||||||
|
|
||||||
const copyLauncher = (
|
const copyLauncher = (
|
||||||
<Button
|
<>
|
||||||
type="button"
|
<Button
|
||||||
variant="outline"
|
type="button"
|
||||||
onClick={() => void copyText(LAUNCHER_CMD, 'Команда скопирована')}
|
variant="outline"
|
||||||
>
|
onClick={() => void copyText(LAUNCHER_CMD, 'Команда скопирована')}
|
||||||
<CopyIcon data-icon="inline-start" />
|
>
|
||||||
Скопировать команду
|
<CopyIcon data-icon="inline-start" />
|
||||||
</Button>
|
Скопировать команду
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => void copyText(LAUNCHER_CMD_DAILY, 'Команда для ежедневного запуска скопирована')}
|
||||||
|
>
|
||||||
|
<CalendarClockIcon data-icon="inline-start" />
|
||||||
|
Раз в день
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ export const IPREGION_STATUS_LABELS: Record<string, string> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const LAUNCHER_CMD = 'curl -fsSL https://vt.shnt.top/ic | bash'
|
export const LAUNCHER_CMD = 'curl -fsSL https://vt.shnt.top/ic | bash'
|
||||||
|
export const LAUNCHER_CMD_DAILY = 'curl -fsSL https://vt.shnt.top/ic | bash -s -- --daily'
|
||||||
|
|
||||||
export function formatVpsResources(vcpu: number, ramGb: number, diskGb: number): string {
|
export function formatVpsResources(vcpu: number, ramGb: number, diskGb: number): string {
|
||||||
return `${vcpu} vCPU / ${ramGb} GB / ${diskGb} GB`
|
return `${vcpu} vCPU / ${ramGb} GB / ${diskGb} GB`
|
||||||
|
|||||||
Reference in New Issue
Block a user