refactor(rebrand): полный ребрендинг в Tachyon и перенос служб watchdog/doctor на Ucode
This commit is contained in:
@@ -11,8 +11,8 @@ body:
|
||||
Спасибо за создание отчета об ошибке!
|
||||
|
||||
Перед отправкой, пожалуйста:
|
||||
- Проверьте [существующие issues](https://github.com/ushan0v/forkop/issues)
|
||||
- Просмотрите [README проекта](https://github.com/ushan0v/forkop#readme)
|
||||
- Проверьте [существующие issues](https://github.com/ushan0v/tachyon/issues)
|
||||
- Просмотрите [README проекта](https://github.com/ushan0v/tachyon#readme)
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
@@ -53,7 +53,7 @@ body:
|
||||
Информация о вашей системе (заполните всё применимое)
|
||||
value: |
|
||||
- **OpenWrt версия**:
|
||||
- **Forkop версия**:
|
||||
- **Tachyon версия**:
|
||||
- **Роутер модель**:
|
||||
- **Sing-box версия**:
|
||||
render: markdown
|
||||
@@ -68,7 +68,7 @@ body:
|
||||
Релевантные части конфигурации (удалите чувствительную информацию!)
|
||||
placeholder: |
|
||||
Например:
|
||||
- Содержимое /etc/config/forkop
|
||||
- Содержимое /etc/config/tachyon
|
||||
- Конфигурация sing-box (если релевантно)
|
||||
- Дополнительные конфиги, которые потребуются wireless/network/dhcp и т.д.
|
||||
render: shell
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 💬 Если у вас что-то не работает, прежде всего прочитайте README проекта
|
||||
url: https://github.com/ushan0v/forkop
|
||||
url: https://github.com/ushan0v/tachyon
|
||||
about: README проекта
|
||||
- name: 📚 Если вы не нашли в README документацию, то вот ссылка на неё
|
||||
url: https://github.com/ushan0v/forkop#readme
|
||||
about: README Forkop
|
||||
url: https://github.com/ushan0v/tachyon#readme
|
||||
about: README Tachyon
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: ✨ Запрос новой функции
|
||||
description: Предложите новую функцию или улучшение для Forkop
|
||||
description: Предложите новую функцию или улучшение для Tachyon
|
||||
title: "[FEATURE] "
|
||||
labels: ["enhancement", "needs-discussion"]
|
||||
assignees: []
|
||||
@@ -11,14 +11,14 @@ body:
|
||||
Спасибо за предложение новой функции!
|
||||
|
||||
Перед отправкой, пожалуйста:
|
||||
- Проверьте [существующие запросы](https://github.com/ushan0v/forkop/issues?q=is%3Aissue+label%3Aenhancement)
|
||||
- Убедитесь, что функции не существует в [README проекта](https://github.com/ushan0v/forkop#readme)
|
||||
- Проверьте [существующие запросы](https://github.com/ushan0v/tachyon/issues?q=is%3Aissue+label%3Aenhancement)
|
||||
- Убедитесь, что функции не существует в [README проекта](https://github.com/ushan0v/tachyon#readme)
|
||||
|
||||
- type: textarea
|
||||
id: summary
|
||||
attributes:
|
||||
label: Краткое описание
|
||||
description: Краткое описание предлагаемой функции для Forkop
|
||||
description: Краткое описание предлагаемой функции для Tachyon
|
||||
placeholder: В одном предложении опишите, что вы хотите добавить...
|
||||
validations:
|
||||
required: true
|
||||
@@ -40,7 +40,7 @@ body:
|
||||
label: 💡 Предлагаемое решение
|
||||
description: Четкое и краткое описание того, что вы хотите реализовать
|
||||
placeholder: |
|
||||
Я хочу, чтобы Forkop мог [...]
|
||||
Я хочу, чтобы Tachyon мог [...]
|
||||
Предлагаю добавить функцию, которая [...]
|
||||
Можно было бы улучшить [...] путем [...]
|
||||
validations:
|
||||
|
||||
@@ -3,8 +3,8 @@ name: Backend CI
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'forkop/files/**'
|
||||
- 'forkop/Makefile'
|
||||
- 'tachyon/files/**'
|
||||
- 'tachyon/Makefile'
|
||||
- 'build.sh'
|
||||
- 'tests/**'
|
||||
- '.github/workflows/backend-ci.yml'
|
||||
@@ -12,8 +12,8 @@ on:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'forkop/files/**'
|
||||
- 'forkop/Makefile'
|
||||
- 'tachyon/files/**'
|
||||
- 'tachyon/Makefile'
|
||||
- 'build.sh'
|
||||
- 'tests/**'
|
||||
- '.github/workflows/backend-ci.yml'
|
||||
@@ -48,8 +48,8 @@ jobs:
|
||||
- name: Check ucode syntax
|
||||
shell: bash
|
||||
run: |
|
||||
find forkop/files/usr/lib -name '*.uc' -print0 | xargs -0 -n1 ucode -c -o /dev/null
|
||||
find forkop/files/usr/lib -name '*.uc' -print0 | xargs -0 -n1 ucode -S -c -o /dev/null
|
||||
find tachyon/files/usr/lib -name '*.uc' -print0 | xargs -0 -n1 ucode -c -o /dev/null
|
||||
find tachyon/files/usr/lib -name '*.uc' -print0 | xargs -0 -n1 ucode -S -c -o /dev/null
|
||||
|
||||
- name: Run backend tests
|
||||
shell: bash
|
||||
|
||||
+20
-20
@@ -45,7 +45,7 @@ jobs:
|
||||
echo "commitish=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
build:
|
||||
name: Build Forkop release packages
|
||||
name: Build Tachyon release packages
|
||||
runs-on: ubuntu-latest
|
||||
needs: preparation
|
||||
steps:
|
||||
@@ -122,12 +122,12 @@ jobs:
|
||||
mkdir -p "$web_dir/releases"
|
||||
|
||||
expected_files=(
|
||||
"forkop_${VERSION}.ipk"
|
||||
"forkop_${VERSION}.apk"
|
||||
"luci-app-forkop_${VERSION}.ipk"
|
||||
"luci-app-forkop_${VERSION}.apk"
|
||||
"luci-i18n-forkop-ru_${VERSION}.ipk"
|
||||
"luci-i18n-forkop-ru_${VERSION}.apk"
|
||||
"tachyon_${VERSION}.ipk"
|
||||
"tachyon_${VERSION}.apk"
|
||||
"luci-app-tachyon_${VERSION}.ipk"
|
||||
"luci-app-tachyon_${VERSION}.apk"
|
||||
"luci-i18n-tachyon-ru_${VERSION}.ipk"
|
||||
"luci-i18n-tachyon-ru_${VERSION}.apk"
|
||||
)
|
||||
for file_name in "${expected_files[@]}"; do
|
||||
test -s "$release_dir/$file_name"
|
||||
@@ -150,7 +150,7 @@ jobs:
|
||||
|
||||
replace_once(
|
||||
b'https://api.github.com/repos/${owner}/${repo}/releases/latest',
|
||||
b'https://forkop.sourceforge.io/releases/latest.json',
|
||||
b'https://tachyon.sourceforge.io/releases/latest.json',
|
||||
)
|
||||
replace_once(b'\nSING_BOX_INSTALL_VARIANT=""\n', b'\n')
|
||||
replace_once(
|
||||
@@ -211,7 +211,7 @@ jobs:
|
||||
version = sys.argv[1]
|
||||
release_dir = pathlib.Path(sys.argv[2])
|
||||
output_path = pathlib.Path(sys.argv[3])
|
||||
base_url = f"https://downloads.sourceforge.net/project/forkop/releases/{version}"
|
||||
base_url = f"https://downloads.sourceforge.net/project/tachyon/releases/{version}"
|
||||
assets = []
|
||||
for path in sorted(release_dir.iterdir(), key=lambda item: item.name):
|
||||
assets.append({
|
||||
@@ -253,9 +253,9 @@ jobs:
|
||||
set -euo pipefail
|
||||
|
||||
sftp -i "$HOME/.ssh/sourceforge" -b - ushan0v@frs.sourceforge.net <<EOF
|
||||
-mkdir /home/frs/project/forkop/releases
|
||||
-mkdir /home/frs/project/forkop/releases/${VERSION}
|
||||
put $PWD/filtered-bin/release/* /home/frs/project/forkop/releases/${VERSION}/
|
||||
-mkdir /home/frs/project/tachyon/releases
|
||||
-mkdir /home/frs/project/tachyon/releases/${VERSION}
|
||||
put $PWD/filtered-bin/release/* /home/frs/project/tachyon/releases/${VERSION}/
|
||||
EOF
|
||||
|
||||
- name: Verify SourceForge package downloads
|
||||
@@ -267,7 +267,7 @@ jobs:
|
||||
|
||||
for package_path in "$PWD"/filtered-bin/release/*; do
|
||||
package_name="$(basename "$package_path")"
|
||||
package_url="https://downloads.sourceforge.net/project/forkop/releases/${VERSION}/${package_name}"
|
||||
package_url="https://downloads.sourceforge.net/project/tachyon/releases/${VERSION}/${package_name}"
|
||||
download_path="$(mktemp)"
|
||||
verified=0
|
||||
for attempt in $(seq 1 12); do
|
||||
@@ -293,11 +293,11 @@ jobs:
|
||||
|
||||
web_dir="$PWD/filtered-bin/sourceforge-web"
|
||||
sftp -i "$HOME/.ssh/sourceforge" -b - ushan0v@web.sourceforge.net <<EOF
|
||||
-mkdir /home/project-web/forkop/htdocs/releases
|
||||
put ${web_dir}/install.sh /home/project-web/forkop/htdocs/install.sh.new
|
||||
rename /home/project-web/forkop/htdocs/install.sh.new /home/project-web/forkop/htdocs/install.sh
|
||||
put ${web_dir}/releases/latest.json /home/project-web/forkop/htdocs/releases/latest.json.new
|
||||
rename /home/project-web/forkop/htdocs/releases/latest.json.new /home/project-web/forkop/htdocs/releases/latest.json
|
||||
-mkdir /home/project-web/tachyon/htdocs/releases
|
||||
put ${web_dir}/install.sh /home/project-web/tachyon/htdocs/install.sh.new
|
||||
rename /home/project-web/tachyon/htdocs/install.sh.new /home/project-web/tachyon/htdocs/install.sh
|
||||
put ${web_dir}/releases/latest.json /home/project-web/tachyon/htdocs/releases/latest.json.new
|
||||
rename /home/project-web/tachyon/htdocs/releases/latest.json.new /home/project-web/tachyon/htdocs/releases/latest.json
|
||||
EOF
|
||||
|
||||
- name: Verify SourceForge installer metadata
|
||||
@@ -327,11 +327,11 @@ jobs:
|
||||
}
|
||||
|
||||
verify_public_file \
|
||||
"https://forkop.sourceforge.io/install.sh" \
|
||||
"https://tachyon.sourceforge.io/install.sh" \
|
||||
"$web_dir/install.sh" \
|
||||
"$web_dir/published-install.sh"
|
||||
verify_public_file \
|
||||
"https://forkop.sourceforge.io/releases/latest.json" \
|
||||
"https://tachyon.sourceforge.io/releases/latest.json" \
|
||||
"$web_dir/releases/latest.json" \
|
||||
"$web_dir/releases/published-latest.json"
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ name: Frontend CI
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'fe-app-forkop/**'
|
||||
- 'fe-app-tachyon/**'
|
||||
- '.github/workflows/frontend-ci.yml'
|
||||
|
||||
jobs:
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
defaults:
|
||||
run:
|
||||
working-directory: fe-app-forkop
|
||||
working-directory: fe-app-tachyon
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
@@ -28,14 +28,14 @@ jobs:
|
||||
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
working-directory: fe-app-forkop
|
||||
working-directory: fe-app-tachyon
|
||||
run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache yarn dependencies
|
||||
uses: actions/cache@v4.3.0
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('fe-app-forkop/yarn.lock') }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('fe-app-tachyon/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ on:
|
||||
paths:
|
||||
- 'build.sh'
|
||||
- 'install.sh'
|
||||
- 'forkop/files/etc/init.d/**'
|
||||
- 'luci-app-forkop/root/etc/uci-defaults/**'
|
||||
- 'tachyon/files/etc/init.d/**'
|
||||
- 'luci-app-tachyon/root/etc/uci-defaults/**'
|
||||
- 'tests/**/*.sh'
|
||||
- '.github/workflows/shellcheck.yml'
|
||||
pull_request:
|
||||
@@ -20,8 +20,8 @@ on:
|
||||
paths:
|
||||
- 'build.sh'
|
||||
- 'install.sh'
|
||||
- 'forkop/files/etc/init.d/**'
|
||||
- 'luci-app-forkop/root/etc/uci-defaults/**'
|
||||
- 'tachyon/files/etc/init.d/**'
|
||||
- 'luci-app-tachyon/root/etc/uci-defaults/**'
|
||||
- 'tests/**/*.sh'
|
||||
- '.github/workflows/shellcheck.yml'
|
||||
|
||||
@@ -48,8 +48,8 @@ jobs:
|
||||
mapfile -d '' scripts < <(
|
||||
find . -type f \
|
||||
\( -name '*.sh' -o -path './build.sh' -o -path './install.sh' \
|
||||
-o -path './forkop/files/etc/init.d/*' \
|
||||
-o -path './luci-app-forkop/root/etc/uci-defaults/*' \) \
|
||||
-o -path './tachyon/files/etc/init.d/*' \
|
||||
-o -path './luci-app-tachyon/root/etc/uci-defaults/*' \) \
|
||||
-print0
|
||||
)
|
||||
shellcheck --severity=error "${scripts[@]}"
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
.idea
|
||||
fe-app-forkop/node_modules
|
||||
fe-app-forkop/.yarn/
|
||||
fe-app-forkop/.env
|
||||
fe-app-tachyon/node_modules
|
||||
fe-app-tachyon/.yarn/
|
||||
fe-app-tachyon/.env
|
||||
.DS_Store
|
||||
|
||||
sandbox/
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
[](https://github.com/Dushnilin/tachyon/stargazers)
|
||||
[](https://github.com/Dushnilin/tachyon/releases)
|
||||
[](https://t.me/tachyon_chat)
|
||||
[](https://t.me/tachyon_aibot)
|
||||
|
||||
> **Tachyon** — это форк проекта **Forkop** (ранее известного как **Podkop Plus**). Проект переименован и развивается как независимое решение для OpenWrt на базе оригинального [Podkop](https://github.com/itdoginfo/podkop).
|
||||
|
||||
@@ -13,6 +11,10 @@
|
||||
sh <(wget -O - https://raw.githubusercontent.com/Dushnilin/tachyon/main/install.sh)
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Конфигурация от **Forkop** (или **Podkop Plus**) полностью совместима и автоматически перенесется и переименуется в `/etc/config/tachyon` во время установки!
|
||||
|
||||
|
||||
### Что нового в этом форке
|
||||
|
||||
* **Поддержка подписок**: автоматическое управление узлами и их регулярное обновление.
|
||||
@@ -29,12 +31,6 @@ sh <(wget -O - https://raw.githubusercontent.com/Dushnilin/tachyon/main/install.
|
||||
* **Интеграция средств обхода**: встроенная поддержка `Zapret`, `Zapret2` и `ByeDPI` как индивидуальных действий для каждого правила.
|
||||
* **Современный бэкенд**: вся логика службы полностью переписана на `ucode`.
|
||||
|
||||
### Документация и поддержка
|
||||
|
||||
Отдельной документации со всеми деталями пока нет. Задать вопрос, сообщить об ошибке или обсудить проект можно в [Telegram-чате](https://t.me/tachyon_chat).
|
||||
|
||||
Для быстрых ответов на вопросы о настройке и работе проекта вы можете использовать бесплатного AI-ассистента [@tachyon_aibot](https://t.me/tachyon_aibot) в Telegram.
|
||||
|
||||
### Поддержать проект
|
||||
|
||||
* 💳 **Карты РФ / СБП / Tinkoff Pay:** [Донат на Dalink](https://dalink.to/dushnilin)
|
||||
|
||||
@@ -22,22 +22,22 @@ if [[ ! "$RELEASE_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
fi
|
||||
APK_INTERNAL_VERSION="$RELEASE_VERSION"
|
||||
|
||||
WSL_NATIVE_ROOT="${WSL_NATIVE_ROOT:-$DEFAULT_BUILD_HOME/build/forkop}"
|
||||
WSL_NATIVE_ROOT="${WSL_NATIVE_ROOT:-$DEFAULT_BUILD_HOME/build/tachyon}"
|
||||
WORK_DIR="${WORK_DIR:-$ROOT_DIR/.wsl-build}"
|
||||
SDK_WORK_DIR="${SDK_WORK_DIR:-$WORK_DIR/sdk}"
|
||||
SDK_CACHE_DIR="${SDK_CACHE_DIR:-$DEFAULT_BUILD_HOME/.cache/forkop/openwrt-sdk}"
|
||||
SDK_CACHE_DIR="${SDK_CACHE_DIR:-$DEFAULT_BUILD_HOME/.cache/tachyon/openwrt-sdk}"
|
||||
IPK_SDK_URL="${IPK_SDK_URL:-https://downloads.openwrt.org/releases/24.10.6/targets/x86/64/openwrt-sdk-24.10.6-x86-64_gcc-13.3.0_musl.Linux-x86_64.tar.zst}"
|
||||
APK_SDK_URL="${APK_SDK_URL:-https://downloads.openwrt.org/releases/25.12.3/targets/x86/64/openwrt-sdk-25.12.3-x86-64_gcc-14.3.0_musl.Linux-x86_64.tar.zst}"
|
||||
|
||||
BACKEND_DESCRIPTION="Rule-based Forkop backend with hybrid sing-box + zapret orchestration"
|
||||
APP_DESCRIPTION="Rule-based Forkop LuCI app with hybrid sing-box + zapret orchestration"
|
||||
I18N_DESCRIPTION="Translation for luci-app-forkop - Русский (Russian)"
|
||||
BACKEND_DESCRIPTION="Rule-based Tachyon backend with hybrid sing-box + zapret orchestration"
|
||||
APP_DESCRIPTION="Rule-based Tachyon LuCI app with hybrid sing-box + zapret orchestration"
|
||||
I18N_DESCRIPTION="Translation for luci-app-tachyon - Русский (Russian)"
|
||||
MAINTAINER="Dushnilin <dushnilin@gmail.com>"
|
||||
PROJECT_URL="https://github.com/Dushnilin/tachyon"
|
||||
BACKEND_DEPENDS_IPK="libc, ca-bundle, kmod-inet-diag, kmod-netlink-diag, kmod-tun, curl, ucode, ucode-mod-fs, ucode-mod-uci, kmod-nft-tproxy, coreutils-base64, coreutils-sort, bind-dig, nftables, kmod-nft-nat, ip-full"
|
||||
BACKEND_DEPENDS_APK="bind-dig ca-bundle coreutils-base64 coreutils-sort curl ip-full kmod-inet-diag kmod-netlink-diag kmod-nft-nat kmod-nft-tproxy kmod-tun libc nftables ucode ucode-mod-fs ucode-mod-uci"
|
||||
APP_DEPENDS_IPK="libc, luci-base, forkop"
|
||||
APP_DEPENDS_APK="libc luci-base forkop"
|
||||
APP_DEPENDS_IPK="libc, luci-base, tachyon"
|
||||
APP_DEPENDS_APK="libc luci-base tachyon"
|
||||
|
||||
APT_PACKAGES=(
|
||||
build-essential
|
||||
@@ -70,14 +70,14 @@ copy_to_native_root() {
|
||||
--exclude "dist" \
|
||||
--exclude ".idea" \
|
||||
--exclude "sandbox" \
|
||||
--exclude "fe-app-forkop/node_modules" \
|
||||
--exclude "fe-app-forkop/tests" \
|
||||
--exclude "fe-app-tachyon/node_modules" \
|
||||
--exclude "fe-app-tachyon/tests" \
|
||||
"$ROOT_DIR/" "$target_root/"
|
||||
rm -rf \
|
||||
"$target_root/.idea" \
|
||||
"$target_root/sandbox" \
|
||||
"$target_root/fe-app-forkop/node_modules" \
|
||||
"$target_root/fe-app-forkop/tests"
|
||||
"$target_root/fe-app-tachyon/node_modules" \
|
||||
"$target_root/fe-app-tachyon/tests"
|
||||
|
||||
if [[ -n "$OUTPUT_DIR_INPUT" ]]; then
|
||||
target_output="$OUTPUT_DIR_INPUT"
|
||||
@@ -172,7 +172,7 @@ extract_sdk() {
|
||||
local archive_path="$2"
|
||||
local sdk_url="$3"
|
||||
local destination="$SDK_WORK_DIR/$kind"
|
||||
local marker_file="$destination/.forkop-sdk-url"
|
||||
local marker_file="$destination/.tachyon-sdk-url"
|
||||
local temp_dir
|
||||
local extracted_root
|
||||
|
||||
@@ -235,18 +235,18 @@ build_backend_root() {
|
||||
make_dir "$output_root/etc/init.d"
|
||||
make_dir "$output_root/etc/config"
|
||||
make_dir "$output_root/usr/bin"
|
||||
make_dir "$output_root/usr/lib/forkop"
|
||||
make_dir "$output_root/usr/lib/tachyon"
|
||||
|
||||
install -m 0755 "$ROOT_DIR/forkop/files/etc/init.d/forkop" "$output_root/etc/init.d/forkop"
|
||||
install -m 0644 "$ROOT_DIR/forkop/files/etc/config/forkop" "$output_root/etc/config/forkop"
|
||||
install -m 0755 "$ROOT_DIR/forkop/files/usr/bin/forkop" "$output_root/usr/bin/forkop"
|
||||
cp -a "$ROOT_DIR/forkop/files/usr/lib/." "$output_root/usr/lib/forkop/"
|
||||
install -m 0755 "$ROOT_DIR/tachyon/files/etc/init.d/tachyon" "$output_root/etc/init.d/tachyon"
|
||||
install -m 0644 "$ROOT_DIR/tachyon/files/etc/config/tachyon" "$output_root/etc/config/tachyon"
|
||||
install -m 0755 "$ROOT_DIR/tachyon/files/usr/bin/tachyon" "$output_root/usr/bin/tachyon"
|
||||
cp -a "$ROOT_DIR/tachyon/files/usr/lib/." "$output_root/usr/lib/tachyon/"
|
||||
|
||||
sed -i -e "s/__COMPILED_VERSION_VARIABLE__/${RELEASE_VERSION}/g" \
|
||||
"$output_root/usr/lib/forkop/core/constants.uc"
|
||||
"$output_root/usr/lib/tachyon/core/constants.uc"
|
||||
|
||||
normalize_package_root_modes "$output_root"
|
||||
chmod 0755 "$output_root/etc/init.d/forkop" "$output_root/usr/bin/forkop"
|
||||
chmod 0755 "$output_root/etc/init.d/tachyon" "$output_root/usr/bin/tachyon"
|
||||
}
|
||||
|
||||
build_app_root() {
|
||||
@@ -255,17 +255,17 @@ build_app_root() {
|
||||
rm -rf "$output_root"
|
||||
make_dir "$output_root/www"
|
||||
|
||||
if [[ -d "$ROOT_DIR/luci-app-forkop/htdocs" ]]; then
|
||||
cp -a "$ROOT_DIR/luci-app-forkop/htdocs/." "$output_root/www/"
|
||||
if [[ -d "$ROOT_DIR/luci-app-tachyon/htdocs" ]]; then
|
||||
cp -a "$ROOT_DIR/luci-app-tachyon/htdocs/." "$output_root/www/"
|
||||
fi
|
||||
|
||||
if [[ -d "$ROOT_DIR/luci-app-forkop/root" ]]; then
|
||||
cp -a "$ROOT_DIR/luci-app-forkop/root/." "$output_root/"
|
||||
if [[ -d "$ROOT_DIR/luci-app-tachyon/root" ]]; then
|
||||
cp -a "$ROOT_DIR/luci-app-tachyon/root/." "$output_root/"
|
||||
fi
|
||||
|
||||
if [[ -f "$output_root/www/luci-static/resources/view/forkop/main.js" ]]; then
|
||||
if [[ -f "$output_root/www/luci-static/resources/view/tachyon/main.js" ]]; then
|
||||
sed -i -e "s/__COMPILED_VERSION_VARIABLE__/${RELEASE_VERSION}/g" \
|
||||
"$output_root/www/luci-static/resources/view/forkop/main.js"
|
||||
"$output_root/www/luci-static/resources/view/tachyon/main.js"
|
||||
fi
|
||||
|
||||
normalize_package_root_modes "$output_root"
|
||||
@@ -275,17 +275,17 @@ build_app_root() {
|
||||
build_i18n_root() {
|
||||
local output_root="$1"
|
||||
local po2lmo_bin="$2"
|
||||
local lmo_path="$output_root/usr/lib/lua/luci/i18n/forkop.ru.lmo"
|
||||
local lmo_path="$output_root/usr/lib/lua/luci/i18n/tachyon.ru.lmo"
|
||||
|
||||
rm -rf "$output_root"
|
||||
make_dir "$output_root/etc/uci-defaults"
|
||||
make_dir "$(dirname "$lmo_path")"
|
||||
|
||||
cat > "$output_root/etc/uci-defaults/luci-i18n-forkop-ru" <<'EOF'
|
||||
cat > "$output_root/etc/uci-defaults/luci-i18n-tachyon-ru" <<'EOF'
|
||||
uci set luci.languages.ru='Русский (Russian)'; uci commit luci
|
||||
EOF
|
||||
|
||||
"$po2lmo_bin" "$ROOT_DIR/luci-app-forkop/po/ru/forkop.po" "$lmo_path"
|
||||
"$po2lmo_bin" "$ROOT_DIR/luci-app-tachyon/po/ru/tachyon.po" "$lmo_path"
|
||||
|
||||
normalize_package_root_modes "$output_root"
|
||||
find "$output_root/etc/uci-defaults" -type f -exec chmod 0755 {} + 2>/dev/null || true
|
||||
@@ -326,7 +326,7 @@ write_backend_ipk_control() {
|
||||
make_dir "$control_dir"
|
||||
|
||||
cat > "$control_dir/control" <<EOF
|
||||
Package: forkop
|
||||
Package: tachyon
|
||||
Version: ${RELEASE_VERSION}
|
||||
Depends: ${BACKEND_DEPENDS_IPK}
|
||||
License: GPL-2.0-or-later
|
||||
@@ -339,20 +339,20 @@ Description: ${BACKEND_DESCRIPTION}
|
||||
EOF
|
||||
|
||||
cat > "$control_dir/conffiles" <<'EOF'
|
||||
/etc/config/forkop
|
||||
/etc/config/tachyon
|
||||
EOF
|
||||
|
||||
cat > "$control_dir/postinst" <<'EOF'
|
||||
#!/bin/sh
|
||||
[ -n "${IPKG_INSTROOT}" ] && exit 0
|
||||
FORKOP_LIB=/usr/lib/forkop ucode -L /usr/lib/forkop /usr/lib/forkop/config/migration.uc migrate
|
||||
TACHYON_LIB=/usr/lib/tachyon ucode -L /usr/lib/tachyon /usr/lib/tachyon/config/migration.uc migrate
|
||||
EOF
|
||||
|
||||
cat > "$control_dir/prerm" <<'EOF'
|
||||
#!/usr/bin/ucode
|
||||
|
||||
if (getenv("IPKG_INSTROOT") == null || getenv("IPKG_INSTROOT") == "")
|
||||
system("/usr/bin/forkop package_prerm >/dev/null 2>&1");
|
||||
system("/usr/bin/tachyon package_prerm >/dev/null 2>&1");
|
||||
|
||||
exit(0);
|
||||
EOF
|
||||
@@ -368,7 +368,7 @@ write_app_ipk_control() {
|
||||
make_dir "$control_dir"
|
||||
|
||||
cat > "$control_dir/control" <<EOF
|
||||
Package: luci-app-forkop
|
||||
Package: luci-app-tachyon
|
||||
Version: ${RELEASE_VERSION}
|
||||
Depends: ${APP_DEPENDS_IPK}
|
||||
License: GPL-2.0-or-later
|
||||
@@ -389,7 +389,7 @@ default_postinst $0 $@
|
||||
EOF
|
||||
|
||||
cat > "$control_dir/postinst-pkg" <<'EOF'
|
||||
[ -n "${IPKG_INSTROOT}" ] || /usr/bin/forkop luci_postinst >/dev/null 2>&1 || true
|
||||
[ -n "${IPKG_INSTROOT}" ] || /usr/bin/tachyon luci_postinst >/dev/null 2>&1 || true
|
||||
EOF
|
||||
|
||||
cat > "$control_dir/prerm" <<'EOF'
|
||||
@@ -410,9 +410,9 @@ write_i18n_ipk_control() {
|
||||
make_dir "$control_dir"
|
||||
|
||||
cat > "$control_dir/control" <<EOF
|
||||
Package: luci-i18n-forkop-ru
|
||||
Package: luci-i18n-tachyon-ru
|
||||
Version: ${RELEASE_VERSION}
|
||||
Depends: libc, luci-app-forkop
|
||||
Depends: libc, luci-app-tachyon
|
||||
License: GPL-2.0-or-later
|
||||
Section: luci
|
||||
URL: ${PROJECT_URL}
|
||||
@@ -494,7 +494,7 @@ EOF
|
||||
cat > "$scripts_dir/backend-post-install.sh" <<'EOF'
|
||||
#!/usr/bin/ucode
|
||||
if (getenv("IPKG_INSTROOT") == null || getenv("IPKG_INSTROOT") == "")
|
||||
exit(system("FORKOP_LIB=/usr/lib/forkop ucode -L /usr/lib/forkop /usr/lib/forkop/config/migration.uc migrate"));
|
||||
exit(system("TACHYON_LIB=/usr/lib/tachyon ucode -L /usr/lib/tachyon /usr/lib/tachyon/config/migration.uc migrate"));
|
||||
exit(0);
|
||||
EOF
|
||||
|
||||
@@ -502,7 +502,7 @@ EOF
|
||||
#!/usr/bin/ucode
|
||||
|
||||
if (getenv("IPKG_INSTROOT") == null || getenv("IPKG_INSTROOT") == "")
|
||||
system("/usr/bin/forkop package_prerm >/dev/null 2>&1");
|
||||
system("/usr/bin/tachyon package_prerm >/dev/null 2>&1");
|
||||
|
||||
exit(0);
|
||||
EOF
|
||||
@@ -515,7 +515,7 @@ EOF
|
||||
cat > "$scripts_dir/backend-post-upgrade.sh" <<'EOF'
|
||||
#!/usr/bin/ucode
|
||||
if (getenv("IPKG_INSTROOT") == null || getenv("IPKG_INSTROOT") == "")
|
||||
exit(system("FORKOP_LIB=/usr/lib/forkop ucode -L /usr/lib/forkop /usr/lib/forkop/config/migration.uc migrate"));
|
||||
exit(system("TACHYON_LIB=/usr/lib/tachyon ucode -L /usr/lib/tachyon /usr/lib/tachyon/config/migration.uc migrate"));
|
||||
exit(0);
|
||||
EOF
|
||||
|
||||
@@ -538,10 +538,10 @@ EOF
|
||||
[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0
|
||||
. ${IPKG_INSTROOT}/lib/functions.sh
|
||||
export root="${IPKG_INSTROOT}"
|
||||
export pkgname="luci-app-forkop"
|
||||
export pkgname="luci-app-tachyon"
|
||||
add_group_and_user
|
||||
default_postinst
|
||||
[ -n "${IPKG_INSTROOT}" ] || /usr/bin/forkop luci_postinst >/dev/null 2>&1 || true
|
||||
[ -n "${IPKG_INSTROOT}" ] || /usr/bin/tachyon luci_postinst >/dev/null 2>&1 || true
|
||||
EOF
|
||||
|
||||
cat > "$scripts_dir/app-pre-deinstall.sh" <<'EOF'
|
||||
@@ -549,7 +549,7 @@ EOF
|
||||
[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0
|
||||
. ${IPKG_INSTROOT}/lib/functions.sh
|
||||
export root="${IPKG_INSTROOT}"
|
||||
export pkgname="luci-app-forkop"
|
||||
export pkgname="luci-app-tachyon"
|
||||
default_prerm
|
||||
exit 0
|
||||
EOF
|
||||
@@ -566,10 +566,10 @@ export PKG_UPGRADE=1
|
||||
[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0
|
||||
. ${IPKG_INSTROOT}/lib/functions.sh
|
||||
export root="${IPKG_INSTROOT}"
|
||||
export pkgname="luci-app-forkop"
|
||||
export pkgname="luci-app-tachyon"
|
||||
add_group_and_user
|
||||
default_postinst
|
||||
[ -n "${IPKG_INSTROOT}" ] || /usr/bin/forkop luci_postinst >/dev/null 2>&1 || true
|
||||
[ -n "${IPKG_INSTROOT}" ] || /usr/bin/tachyon luci_postinst >/dev/null 2>&1 || true
|
||||
EOF
|
||||
|
||||
chmod 0755 "$scripts_dir"/app-*.sh
|
||||
@@ -591,7 +591,7 @@ EOF
|
||||
[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0
|
||||
. ${IPKG_INSTROOT}/lib/functions.sh
|
||||
export root="${IPKG_INSTROOT}"
|
||||
export pkgname="luci-i18n-forkop-ru"
|
||||
export pkgname="luci-i18n-tachyon-ru"
|
||||
add_group_and_user
|
||||
default_postinst
|
||||
EOF
|
||||
@@ -601,7 +601,7 @@ EOF
|
||||
[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0
|
||||
. ${IPKG_INSTROOT}/lib/functions.sh
|
||||
export root="${IPKG_INSTROOT}"
|
||||
export pkgname="luci-i18n-forkop-ru"
|
||||
export pkgname="luci-i18n-tachyon-ru"
|
||||
default_prerm
|
||||
EOF
|
||||
|
||||
@@ -617,7 +617,7 @@ export PKG_UPGRADE=1
|
||||
[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0
|
||||
. ${IPKG_INSTROOT}/lib/functions.sh
|
||||
export root="${IPKG_INSTROOT}"
|
||||
export pkgname="luci-i18n-forkop-ru"
|
||||
export pkgname="luci-i18n-tachyon-ru"
|
||||
add_group_and_user
|
||||
default_postinst
|
||||
EOF
|
||||
@@ -654,7 +654,7 @@ build_apk_package() {
|
||||
-I "description:${description}" \
|
||||
-I "arch:noarch" \
|
||||
-I "license:GPL-2.0-or-later" \
|
||||
-I "origin:forkop" \
|
||||
-I "origin:tachyon" \
|
||||
-I "maintainer:${maintainer}" \
|
||||
-I "url:${PROJECT_URL}" \
|
||||
-I "depends:${depends}" \
|
||||
@@ -673,7 +673,7 @@ build_apk_package() {
|
||||
-I "description:${description}" \
|
||||
-I "arch:noarch" \
|
||||
-I "license:GPL-2.0-or-later" \
|
||||
-I "origin:forkop" \
|
||||
-I "origin:tachyon" \
|
||||
-I "maintainer:${maintainer}" \
|
||||
-I "url:${PROJECT_URL}" \
|
||||
-I "depends:${depends}" \
|
||||
@@ -695,7 +695,7 @@ build_apk_package() {
|
||||
-I 'description:${description}' \
|
||||
-I 'arch:noarch' \
|
||||
-I 'license:GPL-2.0-or-later' \
|
||||
-I 'origin:forkop' \
|
||||
-I 'origin:tachyon' \
|
||||
-I 'maintainer:${maintainer}' \
|
||||
-I 'url:${PROJECT_URL}' \
|
||||
-I 'depends:${depends}' \
|
||||
@@ -717,7 +717,7 @@ build_apk_package() {
|
||||
-I 'description:${description}' \
|
||||
-I 'arch:noarch' \
|
||||
-I 'license:GPL-2.0-or-later' \
|
||||
-I 'origin:forkop' \
|
||||
-I 'origin:tachyon' \
|
||||
-I 'maintainer:${maintainer}' \
|
||||
-I 'url:${PROJECT_URL}' \
|
||||
-I 'depends:${depends}' \
|
||||
@@ -798,17 +798,17 @@ sync_artifacts_to_windows() {
|
||||
fi
|
||||
|
||||
rm -f \
|
||||
"$WINDOWS_ARTIFACTS_DIR"/forkop_* \
|
||||
"$WINDOWS_ARTIFACTS_DIR"/luci-app-forkop_* \
|
||||
"$WINDOWS_ARTIFACTS_DIR"/luci-i18n-forkop-ru_*
|
||||
"$WINDOWS_ARTIFACTS_DIR"/tachyon_* \
|
||||
"$WINDOWS_ARTIFACTS_DIR"/luci-app-tachyon_* \
|
||||
"$WINDOWS_ARTIFACTS_DIR"/luci-i18n-tachyon-ru_*
|
||||
|
||||
cp -f \
|
||||
"$output_dir"/forkop_"${RELEASE_VERSION}".ipk \
|
||||
"$output_dir"/luci-app-forkop_"${RELEASE_VERSION}".ipk \
|
||||
"$output_dir"/luci-i18n-forkop-ru_"${RELEASE_VERSION}".ipk \
|
||||
"$output_dir"/forkop_"${RELEASE_VERSION}".apk \
|
||||
"$output_dir"/luci-app-forkop_"${RELEASE_VERSION}".apk \
|
||||
"$output_dir"/luci-i18n-forkop-ru_"${RELEASE_VERSION}".apk \
|
||||
"$output_dir"/tachyon_"${RELEASE_VERSION}".ipk \
|
||||
"$output_dir"/luci-app-tachyon_"${RELEASE_VERSION}".ipk \
|
||||
"$output_dir"/luci-i18n-tachyon-ru_"${RELEASE_VERSION}".ipk \
|
||||
"$output_dir"/tachyon_"${RELEASE_VERSION}".apk \
|
||||
"$output_dir"/luci-app-tachyon_"${RELEASE_VERSION}".apk \
|
||||
"$output_dir"/luci-i18n-tachyon-ru_"${RELEASE_VERSION}".apk \
|
||||
"$WINDOWS_ARTIFACTS_DIR"/
|
||||
|
||||
echo "Synced artifacts to Windows path: $WINDOWS_ARTIFACTS_DIR" >&2
|
||||
@@ -853,7 +853,7 @@ main() {
|
||||
mkdir -p "$WORK_DIR"
|
||||
output_dir="${OUTPUT_DIR_INPUT:-$ROOT_DIR/dist/release-final}"
|
||||
mkdir -p "$output_dir"
|
||||
rm -f "$output_dir"/forkop_* "$output_dir"/luci-app-forkop_* "$output_dir"/luci-i18n-forkop-ru_*
|
||||
rm -f "$output_dir"/tachyon_* "$output_dir"/luci-app-tachyon_* "$output_dir"/luci-i18n-tachyon-ru_*
|
||||
|
||||
ipk_archive="$(download_sdk_archive "$IPK_SDK_URL")"
|
||||
apk_archive="$(download_sdk_archive "$APK_SDK_URL")"
|
||||
@@ -880,74 +880,74 @@ main() {
|
||||
|
||||
build_ipk_package \
|
||||
"$ipkg_build_bin" \
|
||||
"forkop" \
|
||||
"tachyon" \
|
||||
"$backend_root" \
|
||||
"$backend_control" \
|
||||
"$output_dir/forkop_${RELEASE_VERSION}.ipk"
|
||||
"$output_dir/tachyon_${RELEASE_VERSION}.ipk"
|
||||
|
||||
build_ipk_package \
|
||||
"$ipkg_build_bin" \
|
||||
"luci-app-forkop" \
|
||||
"luci-app-tachyon" \
|
||||
"$app_root" \
|
||||
"$app_control" \
|
||||
"$output_dir/luci-app-forkop_${RELEASE_VERSION}.ipk"
|
||||
"$output_dir/luci-app-tachyon_${RELEASE_VERSION}.ipk"
|
||||
|
||||
build_ipk_package \
|
||||
"$ipkg_build_bin" \
|
||||
"luci-i18n-forkop-ru" \
|
||||
"luci-i18n-tachyon-ru" \
|
||||
"$i18n_root" \
|
||||
"$i18n_control" \
|
||||
"$output_dir/luci-i18n-forkop-ru_${RELEASE_VERSION}.ipk"
|
||||
"$output_dir/luci-i18n-tachyon-ru_${RELEASE_VERSION}.ipk"
|
||||
|
||||
generate_apk_metadata_files "forkop" "$backend_root" "/etc/config/forkop"
|
||||
generate_apk_metadata_files "luci-app-forkop" "$app_root"
|
||||
generate_apk_metadata_files "luci-i18n-forkop-ru" "$i18n_root"
|
||||
generate_apk_metadata_files "tachyon" "$backend_root" "/etc/config/tachyon"
|
||||
generate_apk_metadata_files "luci-app-tachyon" "$app_root"
|
||||
generate_apk_metadata_files "luci-i18n-tachyon-ru" "$i18n_root"
|
||||
write_backend_apk_scripts "$apk_scripts"
|
||||
write_app_apk_scripts "$apk_scripts"
|
||||
write_i18n_apk_scripts "$apk_scripts"
|
||||
|
||||
build_apk_package \
|
||||
"$apk_bin" \
|
||||
"forkop" \
|
||||
"tachyon" \
|
||||
"$APK_INTERNAL_VERSION" \
|
||||
"$BACKEND_DESCRIPTION" \
|
||||
"$BACKEND_DEPENDS_APK" \
|
||||
"$backend_root" \
|
||||
"$apk_scripts" \
|
||||
"backend" \
|
||||
"$output_dir/forkop_${RELEASE_VERSION}.apk" \
|
||||
"$output_dir/tachyon_${RELEASE_VERSION}.apk" \
|
||||
"$MAINTAINER"
|
||||
|
||||
build_apk_package \
|
||||
"$apk_bin" \
|
||||
"luci-app-forkop" \
|
||||
"luci-app-tachyon" \
|
||||
"$APK_INTERNAL_VERSION" \
|
||||
"$APP_DESCRIPTION" \
|
||||
"$APP_DEPENDS_APK" \
|
||||
"$app_root" \
|
||||
"$apk_scripts" \
|
||||
"app" \
|
||||
"$output_dir/luci-app-forkop_${RELEASE_VERSION}.apk" \
|
||||
"$output_dir/luci-app-tachyon_${RELEASE_VERSION}.apk" \
|
||||
"$MAINTAINER"
|
||||
|
||||
build_apk_package \
|
||||
"$apk_bin" \
|
||||
"luci-i18n-forkop-ru" \
|
||||
"luci-i18n-tachyon-ru" \
|
||||
"$APK_INTERNAL_VERSION" \
|
||||
"$I18N_DESCRIPTION" \
|
||||
"libc luci-app-forkop" \
|
||||
"libc luci-app-tachyon" \
|
||||
"$i18n_root" \
|
||||
"$apk_scripts" \
|
||||
"i18n" \
|
||||
"$output_dir/luci-i18n-forkop-ru_${RELEASE_VERSION}.apk" \
|
||||
"$output_dir/luci-i18n-tachyon-ru_${RELEASE_VERSION}.apk" \
|
||||
"$MAINTAINER"
|
||||
|
||||
verify_ipk_metadata "$output_dir/forkop_${RELEASE_VERSION}.ipk" "forkop" "$RELEASE_VERSION"
|
||||
verify_ipk_metadata "$output_dir/luci-app-forkop_${RELEASE_VERSION}.ipk" "luci-app-forkop" "$RELEASE_VERSION"
|
||||
verify_ipk_metadata "$output_dir/luci-i18n-forkop-ru_${RELEASE_VERSION}.ipk" "luci-i18n-forkop-ru" "$RELEASE_VERSION"
|
||||
verify_apk_metadata "$apk_bin" "$output_dir/forkop_${RELEASE_VERSION}.apk" "forkop" "$APK_INTERNAL_VERSION"
|
||||
verify_apk_metadata "$apk_bin" "$output_dir/luci-app-forkop_${RELEASE_VERSION}.apk" "luci-app-forkop" "$APK_INTERNAL_VERSION"
|
||||
verify_apk_metadata "$apk_bin" "$output_dir/luci-i18n-forkop-ru_${RELEASE_VERSION}.apk" "luci-i18n-forkop-ru" "$APK_INTERNAL_VERSION"
|
||||
verify_ipk_metadata "$output_dir/tachyon_${RELEASE_VERSION}.ipk" "tachyon" "$RELEASE_VERSION"
|
||||
verify_ipk_metadata "$output_dir/luci-app-tachyon_${RELEASE_VERSION}.ipk" "luci-app-tachyon" "$RELEASE_VERSION"
|
||||
verify_ipk_metadata "$output_dir/luci-i18n-tachyon-ru_${RELEASE_VERSION}.ipk" "luci-i18n-tachyon-ru" "$RELEASE_VERSION"
|
||||
verify_apk_metadata "$apk_bin" "$output_dir/tachyon_${RELEASE_VERSION}.apk" "tachyon" "$APK_INTERNAL_VERSION"
|
||||
verify_apk_metadata "$apk_bin" "$output_dir/luci-app-tachyon_${RELEASE_VERSION}.apk" "luci-app-tachyon" "$APK_INTERNAL_VERSION"
|
||||
verify_apk_metadata "$apk_bin" "$output_dir/luci-i18n-tachyon-ru_${RELEASE_VERSION}.apk" "luci-i18n-tachyon-ru" "$APK_INTERNAL_VERSION"
|
||||
|
||||
cleanup_work_dir
|
||||
sync_artifacts_to_windows "$output_dir"
|
||||
|
||||
@@ -6,11 +6,11 @@ SFTP_PASS=
|
||||
# you can use key if needed
|
||||
# SFTP_PRIVATE_KEY=~/.ssh/id_rsa
|
||||
|
||||
LOCAL_DIR_FE=../luci-app-forkop/htdocs/luci-static/resources/view/forkop
|
||||
REMOTE_DIR_FE=/www/luci-static/resources/view/forkop
|
||||
LOCAL_DIR_FE=../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon
|
||||
REMOTE_DIR_FE=/www/luci-static/resources/view/tachyon
|
||||
|
||||
LOCAL_DIR_BIN=../forkop/files/usr/bin/
|
||||
LOCAL_DIR_BIN=../tachyon/files/usr/bin/
|
||||
REMOTE_DIR_BIN=/usr/bin/
|
||||
|
||||
LOCAL_DIR_LIB=../forkop/files/usr/lib/
|
||||
REMOTE_DIR_LIB=/usr/lib/forkop/
|
||||
LOCAL_DIR_LIB=../tachyon/files/usr/lib/
|
||||
REMOTE_DIR_LIB=/usr/lib/tachyon/
|
||||
|
||||
@@ -6,7 +6,7 @@ const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const sourceDir = path.resolve(__dirname, 'locales');
|
||||
const targetRoot = path.resolve(__dirname, '../luci-app-forkop/po');
|
||||
const targetRoot = path.resolve(__dirname, '../luci-app-tachyon/po');
|
||||
|
||||
async function main() {
|
||||
const files = await fs.readdir(sourceDir);
|
||||
@@ -14,17 +14,17 @@ async function main() {
|
||||
for (const file of files) {
|
||||
const filePath = path.join(sourceDir, file);
|
||||
|
||||
if (file === 'forkop.pot') {
|
||||
const potTarget = path.join(targetRoot, 'templates', 'forkop.pot');
|
||||
if (file === 'tachyon.pot') {
|
||||
const potTarget = path.join(targetRoot, 'templates', 'tachyon.pot');
|
||||
await fs.mkdir(path.dirname(potTarget), { recursive: true });
|
||||
await fs.copyFile(filePath, potTarget);
|
||||
console.log(`✅ Copied POT: ${filePath} → ${potTarget}`);
|
||||
}
|
||||
|
||||
const match = file.match(/^forkop\.([a-zA-Z_]+)\.po$/);
|
||||
const match = file.match(/^tachyon\.([a-zA-Z_]+)\.po$/);
|
||||
if (match) {
|
||||
const lang = match[1];
|
||||
const poTarget = path.join(targetRoot, lang, 'forkop.po');
|
||||
const poTarget = path.join(targetRoot, lang, 'tachyon.po');
|
||||
await fs.mkdir(path.dirname(poTarget), { recursive: true });
|
||||
await fs.copyFile(filePath, poTarget);
|
||||
console.log(`✅ Copied ${lang.toUpperCase()}: ${filePath} → ${poTarget}`);
|
||||
|
||||
@@ -19,12 +19,12 @@ function stripIllegalReturn(code) {
|
||||
|
||||
const files = await glob([
|
||||
'src/**/*.ts',
|
||||
'../luci-app-forkop/htdocs/luci-static/resources/view/forkop/**/*.js',
|
||||
'../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/**/*.js',
|
||||
], {
|
||||
ignore: [
|
||||
'**/*.test.ts',
|
||||
'**/main.js',
|
||||
'../luci-app-forkop/htdocs/luci-static/resources/view/forkop/main.js',
|
||||
'../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js',
|
||||
],
|
||||
absolute: true,
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ if (!lang) {
|
||||
}
|
||||
|
||||
const callsPath = 'locales/calls.json';
|
||||
const poPath = `locales/forkop.${lang}.po`;
|
||||
const poPath = `locales/tachyon.${lang}.po`;
|
||||
|
||||
function getHeader(lang) {
|
||||
const now = new Date();
|
||||
@@ -28,14 +28,14 @@ function getHeader(lang) {
|
||||
: 'nplurals=2; plural=(n != 1);';
|
||||
|
||||
return [
|
||||
`# ${lang.toUpperCase()} translations for FORKOP package.`,
|
||||
`# Copyright (C) ${now.getFullYear()} THE FORKOP COPYRIGHT HOLDER`,
|
||||
`# This file is distributed under the same license as the FORKOP package.`,
|
||||
`# ${lang.toUpperCase()} translations for TACHYON package.`,
|
||||
`# Copyright (C) ${now.getFullYear()} THE TACHYON COPYRIGHT HOLDER`,
|
||||
`# This file is distributed under the same license as the TACHYON package.`,
|
||||
`# ${translator}, ${now.getFullYear()}.`,
|
||||
'#',
|
||||
'msgid ""',
|
||||
'msgstr ""',
|
||||
`"Project-Id-Version: FORKOP\\n"`,
|
||||
`"Project-Id-Version: TACHYON\\n"`,
|
||||
`"Report-Msgid-Bugs-To: \\n"`,
|
||||
`"POT-Creation-Date: ${date} ${time}${tzOffset}\\n"`,
|
||||
`"PO-Revision-Date: ${date} ${time}${tzOffset}\\n"`,
|
||||
|
||||
@@ -2,8 +2,8 @@ import fs from 'fs/promises';
|
||||
import { getGitUser } from './locales-utils.js';
|
||||
|
||||
const inputFile = 'locales/calls.json';
|
||||
const outputFile = 'locales/forkop.pot';
|
||||
const projectId = 'FORKOP';
|
||||
const outputFile = 'locales/tachyon.pot';
|
||||
const projectId = 'TACHYON';
|
||||
|
||||
function getPotHeader({ name, email }) {
|
||||
const now = new Date();
|
||||
|
||||
+1076
-1076
File diff suppressed because it is too large
Load Diff
+997
-997
File diff suppressed because it is too large
Load Diff
@@ -1,15 +1,15 @@
|
||||
# RU translations for FORKOP package.
|
||||
# Copyright (C) 2026 THE FORKOP COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the FORKOP package.
|
||||
# ushan0v, 2026.
|
||||
# RU translations for TACHYON package.
|
||||
# Copyright (C) 2026 THE TACHYON COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the TACHYON package.
|
||||
# Dushnilin, 2026.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: FORKOP\n"
|
||||
"Project-Id-Version: TACHYON\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-07-13 03:22+0300\n"
|
||||
"PO-Revision-Date: 2026-07-13 03:22+0300\n"
|
||||
"Last-Translator: ushan0v\n"
|
||||
"POT-Creation-Date: 2026-07-13 13:18+0300\n"
|
||||
"PO-Revision-Date: 2026-07-13 13:18+0300\n"
|
||||
"Last-Translator: Dushnilin\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -191,8 +191,8 @@ msgstr "Встроенные наборы правил"
|
||||
msgid "By flag emoji from name"
|
||||
msgstr "По эмодзи флага из названия"
|
||||
|
||||
msgid "ByeDPI listen address and port are assigned by Forkop and must not be set in the strategy."
|
||||
msgstr "Адрес и порт прослушивания ByeDPI назначаются Forkop и не должны задаваться в стратегии."
|
||||
msgid "ByeDPI listen address and port are assigned by Tachyon and must not be set in the strategy."
|
||||
msgstr "Адрес и порт прослушивания ByeDPI назначаются Tachyon и не должны задаваться в стратегии."
|
||||
|
||||
msgid "ByeDPI option does not accept a compact value: %s"
|
||||
msgstr "Опция ByeDPI не принимает компактное значение: %s"
|
||||
@@ -323,8 +323,8 @@ msgstr "Условия"
|
||||
msgid "Config File Path"
|
||||
msgstr "Путь к файлу конфигурации"
|
||||
|
||||
msgid "Configuration for Forkop service"
|
||||
msgstr "Настройки сервиса Forkop"
|
||||
msgid "Configuration for Tachyon service"
|
||||
msgstr "Настройки сервиса Tachyon"
|
||||
|
||||
msgid "Configure User-Agent in the item settings"
|
||||
msgstr "Настройте User-Agent в настройках элемента"
|
||||
@@ -374,8 +374,8 @@ msgstr "Дашборд сейчас недоступен"
|
||||
msgid "Default address for checking server availability and latency. URLTest uses its own address."
|
||||
msgstr "Адрес по умолчанию для проверки доступности и задержки серверов. Для URLTest используется собственный адрес."
|
||||
|
||||
msgid "Delay in milliseconds before reloading Forkop after interface UP"
|
||||
msgstr "Задержка в миллисекундах перед перезапуском Forkop после поднятия интерфейса"
|
||||
msgid "Delay in milliseconds before reloading Tachyon after interface UP"
|
||||
msgstr "Задержка в миллисекундах перед перезапуском Tachyon после поднятия интерфейса"
|
||||
|
||||
msgid "Delay value cannot be empty"
|
||||
msgstr "Значение задержки не может быть пустым"
|
||||
@@ -419,8 +419,8 @@ msgstr "Отключить QUIC"
|
||||
msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming"
|
||||
msgstr "Отключить QUIC протокол для улучшения совместимости или исправления видео стриминга"
|
||||
|
||||
msgid "Disabling interception is incompatible with action=zapret2 because Forkop sends matched traffic through NFQUEUE."
|
||||
msgstr "Отключение перехвата несовместимо с action=zapret2, потому что Forkop отправляет совпавший трафик через NFQUEUE."
|
||||
msgid "Disabling interception is incompatible with action=zapret2 because Tachyon sends matched traffic through NFQUEUE."
|
||||
msgstr "Отключение перехвата несовместимо с action=zapret2, потому что Tachyon отправляет совпавший трафик через NFQUEUE."
|
||||
|
||||
msgid "Display name"
|
||||
msgstr "Отображаемое имя"
|
||||
@@ -656,11 +656,11 @@ msgstr "Истекает"
|
||||
msgid "Expose this section as a local HTTP+SOCKS proxy"
|
||||
msgstr "Открыть эту секцию как локальный HTTP+SOCKS прокси"
|
||||
|
||||
msgid "External nfqws config files bypass Forkop queue management and explicit validation."
|
||||
msgstr "Внешние конфиги nfqws обходят управление очередями и явную валидацию Forkop."
|
||||
msgid "External nfqws config files bypass Tachyon queue management and explicit validation."
|
||||
msgstr "Внешние конфиги nfqws обходят управление очередями и явную валидацию Tachyon."
|
||||
|
||||
msgid "External nfqws2 config files bypass Forkop queue management and explicit validation."
|
||||
msgstr "Внешние конфиги nfqws2 обходят управление очередями и явную валидацию Forkop."
|
||||
msgid "External nfqws2 config files bypass Tachyon queue management and explicit validation."
|
||||
msgstr "Внешние конфиги nfqws2 обходят управление очередями и явную валидацию Tachyon."
|
||||
|
||||
msgid "Failed to close connection"
|
||||
msgstr "Не удалось закрыть подключение"
|
||||
@@ -707,63 +707,6 @@ msgstr "Исправьте подсвеченные поля и сохранит
|
||||
msgid "Forced device routing"
|
||||
msgstr "Принудительная маршрутизация устройств"
|
||||
|
||||
msgid "Forkop Error"
|
||||
msgstr "Ошибка Forkop"
|
||||
|
||||
msgid "Forkop manages ciadpi pid files itself, so pidfile options are not allowed here."
|
||||
msgstr "Forkop сам управляет pid-файлами ciadpi, поэтому параметры pidfile здесь запрещены."
|
||||
|
||||
msgid "Forkop manages the ciadpi process lifecycle itself, so daemon mode is not allowed here."
|
||||
msgstr "Forkop сам управляет жизненным циклом ciadpi, поэтому режим daemon здесь запрещён."
|
||||
|
||||
msgid "Forkop manages the nfqws process lifecycle itself, so daemon mode is not allowed here."
|
||||
msgstr "Forkop сам управляет жизненным циклом nfqws, поэтому режим daemon здесь запрещён."
|
||||
|
||||
msgid "Forkop manages the nfqws2 process lifecycle itself, so daemon mode is not allowed here."
|
||||
msgstr "Forkop сам управляет жизненным циклом nfqws2, поэтому режим daemon здесь запрещён."
|
||||
|
||||
msgid "Forkop service is stopped. Start the service to display connections."
|
||||
msgstr "Служба Forkop остановлена. Запустите сервис для отображения подключений."
|
||||
|
||||
msgid "Forkop service is stopped. Start the service to display the dashboard."
|
||||
msgstr "Служба Forkop остановлена. Запустите сервис для отображения дашборда."
|
||||
|
||||
msgid "Forkop Settings"
|
||||
msgstr "Настройки Forkop"
|
||||
|
||||
msgid "Forkop will not modify your DHCP configuration"
|
||||
msgstr "Forkop не будет изменять вашу конфигурацию DHCP"
|
||||
|
||||
msgid "Forkop-managed ciadpi runtime has restarted"
|
||||
msgstr "ciadpi Forkop перезапускался"
|
||||
|
||||
msgid "Forkop-managed ciadpi runtime is not ready"
|
||||
msgstr "ciadpi Forkop не готов"
|
||||
|
||||
msgid "Forkop-managed ciadpi runtime is not running"
|
||||
msgstr "ciadpi Forkop не запущен"
|
||||
|
||||
msgid "Forkop-managed ciadpi runtime is ready"
|
||||
msgstr "ciadpi Forkop готов"
|
||||
|
||||
msgid "Forkop-managed nfqws runtime is not ready"
|
||||
msgstr "NFQWS Forkop не готов"
|
||||
|
||||
msgid "Forkop-managed nfqws runtime is not running"
|
||||
msgstr "NFQWS Forkop не запущен"
|
||||
|
||||
msgid "Forkop-managed nfqws runtime is ready"
|
||||
msgstr "NFQWS Forkop готов"
|
||||
|
||||
msgid "Forkop-managed nfqws2 runtime is not ready"
|
||||
msgstr "NFQWS2 Forkop не готов"
|
||||
|
||||
msgid "Forkop-managed nfqws2 runtime is not running"
|
||||
msgstr "NFQWS2 Forkop не запущен"
|
||||
|
||||
msgid "Forkop-managed nfqws2 runtime is ready"
|
||||
msgstr "NFQWS2 Forkop готов"
|
||||
|
||||
msgid "Fronting IP"
|
||||
msgstr "IP фронтинга"
|
||||
|
||||
@@ -773,8 +716,8 @@ msgstr "Порт фронтинга"
|
||||
msgid "Fronting proxy protocol"
|
||||
msgstr "Proxy protocol для фронтинга"
|
||||
|
||||
msgid "Fuzzing is not supported here because Forkop needs deterministic runtime validation."
|
||||
msgstr "Fuzzing здесь не поддерживается, потому что Forkop нужна предсказуемая runtime-валидация."
|
||||
msgid "Fuzzing is not supported here because Tachyon needs deterministic runtime validation."
|
||||
msgstr "Fuzzing здесь не поддерживается, потому что Tachyon нужна предсказуемая runtime-валидация."
|
||||
|
||||
msgid "Generate HWID from router hardware information for this subscription"
|
||||
msgstr "Генерировать HWID из аппаратной информации роутера для этой подписки"
|
||||
@@ -1541,8 +1484,8 @@ msgstr "Выбор ресурсов по IP или CIDR внутри nfqws зд
|
||||
msgid "Resource selection by IP or CIDR inside nfqws2 is not supported here; sing-box selects resources before NFQUEUE."
|
||||
msgstr "Выбор ресурсов по IP или CIDR внутри nfqws2 здесь не поддерживается; sing-box выбирает ресурсы до NFQUEUE."
|
||||
|
||||
msgid "Restart Forkop"
|
||||
msgstr "Перезапустить Forkop"
|
||||
msgid "Restart Tachyon"
|
||||
msgstr "Перезапустить Tachyon"
|
||||
|
||||
msgid "Resume updates"
|
||||
msgstr "Продолжить обновление"
|
||||
@@ -1787,8 +1730,8 @@ msgstr "Укажите разные файлы"
|
||||
msgid "Standalone ByeDPI autostart is enabled"
|
||||
msgstr "Автозапуск отдельной службы ByeDPI включен"
|
||||
|
||||
msgid "Standalone ByeDPI is active together with Forkop ByeDPI rules"
|
||||
msgstr "Отдельная служба ByeDPI активна вместе с правилами ByeDPI в Forkop"
|
||||
msgid "Standalone ByeDPI is active together with Tachyon ByeDPI rules"
|
||||
msgstr "Отдельная служба ByeDPI активна вместе с правилами ByeDPI в Tachyon"
|
||||
|
||||
msgid "Standalone ByeDPI service is active"
|
||||
msgstr "Отдельная служба ByeDPI активна"
|
||||
@@ -1796,8 +1739,8 @@ msgstr "Отдельная служба ByeDPI активна"
|
||||
msgid "Standalone ByeDPI service is inactive"
|
||||
msgstr "Отдельная служба ByeDPI неактивна"
|
||||
|
||||
msgid "Standalone Zapret is active together with Forkop Zapret rules"
|
||||
msgstr "Отдельная служба Zapret активна вместе с правилами Zapret в Forkop"
|
||||
msgid "Standalone Zapret is active together with Tachyon Zapret rules"
|
||||
msgstr "Отдельная служба Zapret активна вместе с правилами Zapret в Tachyon"
|
||||
|
||||
msgid "Standalone Zapret service is active"
|
||||
msgstr "Отдельная служба Zapret активна"
|
||||
@@ -1808,8 +1751,8 @@ msgstr "Отдельная служба Zapret неактивна"
|
||||
msgid "Standalone Zapret2 autostart is enabled"
|
||||
msgstr "Автозапуск отдельной службы Zapret2 включён"
|
||||
|
||||
msgid "Standalone Zapret2 is active together with Forkop Zapret2 rules"
|
||||
msgstr "Отдельная служба Zapret2 активна вместе с правилами Zapret2 в Forkop"
|
||||
msgid "Standalone Zapret2 is active together with Tachyon Zapret2 rules"
|
||||
msgstr "Отдельная служба Zapret2 активна вместе с правилами Zapret2 в Tachyon"
|
||||
|
||||
msgid "Standalone Zapret2 service is active"
|
||||
msgstr "Отдельная служба Zapret2 активна"
|
||||
@@ -1817,14 +1760,14 @@ msgstr "Отдельная служба Zapret2 активна"
|
||||
msgid "Standalone Zapret2 service is inactive"
|
||||
msgstr "Отдельная служба Zapret2 неактивна"
|
||||
|
||||
msgid "Start Forkop"
|
||||
msgstr "Запустить Forkop"
|
||||
msgid "Start Tachyon"
|
||||
msgstr "Запустить Tachyon"
|
||||
|
||||
msgid "Stop checking when URLTest group is not used. Use sing-box duration format like 1d, 12h or 30m."
|
||||
msgstr "Останавливать проверку если URLTest группа не используется. Используйте формат длительности sing-box, например 1d, 12h или 30m."
|
||||
|
||||
msgid "Stop Forkop"
|
||||
msgstr "Остановить Forkop"
|
||||
msgid "Stop Tachyon"
|
||||
msgstr "Остановить Tachyon"
|
||||
|
||||
msgid "Subnets from the list will be extracted and added to nftables"
|
||||
msgstr "IP-адреса и подсети из списка будут извлечены и добавлены в nftables"
|
||||
@@ -1862,6 +1805,63 @@ msgstr "Системная информация"
|
||||
msgid "Table exist"
|
||||
msgstr "Таблица существует"
|
||||
|
||||
msgid "Tachyon Error"
|
||||
msgstr "Ошибка Tachyon"
|
||||
|
||||
msgid "Tachyon manages ciadpi pid files itself, so pidfile options are not allowed here."
|
||||
msgstr "Tachyon сам управляет pid-файлами ciadpi, поэтому параметры pidfile здесь запрещены."
|
||||
|
||||
msgid "Tachyon manages the ciadpi process lifecycle itself, so daemon mode is not allowed here."
|
||||
msgstr "Tachyon сам управляет жизненным циклом ciadpi, поэтому режим daemon здесь запрещён."
|
||||
|
||||
msgid "Tachyon manages the nfqws process lifecycle itself, so daemon mode is not allowed here."
|
||||
msgstr "Tachyon сам управляет жизненным циклом nfqws, поэтому режим daemon здесь запрещён."
|
||||
|
||||
msgid "Tachyon manages the nfqws2 process lifecycle itself, so daemon mode is not allowed here."
|
||||
msgstr "Tachyon сам управляет жизненным циклом nfqws2, поэтому режим daemon здесь запрещён."
|
||||
|
||||
msgid "Tachyon service is stopped. Start the service to display connections."
|
||||
msgstr "Служба Tachyon остановлена. Запустите сервис для отображения подключений."
|
||||
|
||||
msgid "Tachyon service is stopped. Start the service to display the dashboard."
|
||||
msgstr "Служба Tachyon остановлена. Запустите сервис для отображения дашборда."
|
||||
|
||||
msgid "Tachyon Settings"
|
||||
msgstr "Настройки Tachyon"
|
||||
|
||||
msgid "Tachyon will not modify your DHCP configuration"
|
||||
msgstr "Tachyon не будет изменять вашу конфигурацию DHCP"
|
||||
|
||||
msgid "Tachyon-managed ciadpi runtime has restarted"
|
||||
msgstr "ciadpi Tachyon перезапускался"
|
||||
|
||||
msgid "Tachyon-managed ciadpi runtime is not ready"
|
||||
msgstr "ciadpi Tachyon не готов"
|
||||
|
||||
msgid "Tachyon-managed ciadpi runtime is not running"
|
||||
msgstr "ciadpi Tachyon не запущен"
|
||||
|
||||
msgid "Tachyon-managed ciadpi runtime is ready"
|
||||
msgstr "ciadpi Tachyon готов"
|
||||
|
||||
msgid "Tachyon-managed nfqws runtime is not ready"
|
||||
msgstr "NFQWS Tachyon не готов"
|
||||
|
||||
msgid "Tachyon-managed nfqws runtime is not running"
|
||||
msgstr "NFQWS Tachyon не запущен"
|
||||
|
||||
msgid "Tachyon-managed nfqws runtime is ready"
|
||||
msgstr "NFQWS Tachyon готов"
|
||||
|
||||
msgid "Tachyon-managed nfqws2 runtime is not ready"
|
||||
msgstr "NFQWS2 Tachyon не готов"
|
||||
|
||||
msgid "Tachyon-managed nfqws2 runtime is not running"
|
||||
msgstr "NFQWS2 Tachyon не запущен"
|
||||
|
||||
msgid "Tachyon-managed nfqws2 runtime is ready"
|
||||
msgstr "NFQWS2 Tachyon готов"
|
||||
|
||||
msgid "Tailscale auth key"
|
||||
msgstr "Ключ авторизации Tailscale"
|
||||
|
||||
@@ -1898,11 +1898,11 @@ msgstr "Тестировать серверы, имена которых сов
|
||||
msgid "Testing URL"
|
||||
msgstr "URL проверки"
|
||||
|
||||
msgid "The desync fwmark is managed by Forkop for loop prevention and must not be overridden here."
|
||||
msgstr "Desync fwmark управляется Forkop для защиты от циклов и не должен переопределяться здесь."
|
||||
msgid "The desync fwmark is managed by Tachyon for loop prevention and must not be overridden here."
|
||||
msgstr "Desync fwmark управляется Tachyon для защиты от циклов и не должен переопределяться здесь."
|
||||
|
||||
msgid "The NFQUEUE number is assigned by Forkop for each rule and must not be overridden here."
|
||||
msgstr "Номер NFQUEUE назначается Forkop для каждого правила и не должен переопределяться здесь."
|
||||
msgid "The NFQUEUE number is assigned by Tachyon for each rule and must not be overridden here."
|
||||
msgstr "Номер NFQUEUE назначается Tachyon для каждого правила и не должен переопределяться здесь."
|
||||
|
||||
msgid "The rule applies to the domain and all its subdomains. Use full:, keyword:, or regex: prefixes for exact match, keyword match, or regular expression."
|
||||
msgstr "Правило применяется к домену и всем его поддоменам. Для полного совпадения, совпадению по слову или регулярному выражению используйте префиксы full:, keyword: или regex:."
|
||||
@@ -1967,8 +1967,8 @@ msgstr "Трафик этого уровня пойдёт напрямую."
|
||||
msgid "Traffic Total"
|
||||
msgstr "Всего трафика"
|
||||
|
||||
msgid "Transparent proxy mode is incompatible with action=byedpi because Forkop connects to ciadpi through SOCKS."
|
||||
msgstr "Режим прозрачного прокси несовместим с action=byedpi, потому что Forkop подключается к ciadpi через SOCKS."
|
||||
msgid "Transparent proxy mode is incompatible with action=byedpi because Tachyon connects to ciadpi through SOCKS."
|
||||
msgstr "Режим прозрачного прокси несовместим с action=byedpi, потому что Tachyon подключается к ciadpi через SOCKS."
|
||||
|
||||
msgid "Transport"
|
||||
msgstr "Транспорт"
|
||||
@@ -2015,18 +2015,18 @@ msgstr "Таймаут недоступности"
|
||||
msgid "Unexpected ByeDPI strategy argument: %s"
|
||||
msgstr "Неожиданный аргумент стратегии ByeDPI: %s"
|
||||
|
||||
msgid "Unexpected Forkop-managed ciadpi runtime is running"
|
||||
msgstr "Обнаружен лишний ciadpi Forkop"
|
||||
|
||||
msgid "Unexpected Forkop-managed nfqws runtime is running"
|
||||
msgstr "Обнаружен лишний NFQWS Forkop"
|
||||
|
||||
msgid "Unexpected Forkop-managed nfqws2 runtime is running"
|
||||
msgstr "Обнаружен лишний NFQWS2 Forkop"
|
||||
|
||||
msgid "Unexpected standalone token. Use explicit flags such as --name or --name=value."
|
||||
msgstr "Неожиданный отдельный токен. Используйте явные флаги вида --имя или --имя=значение."
|
||||
|
||||
msgid "Unexpected Tachyon-managed ciadpi runtime is running"
|
||||
msgstr "Обнаружен лишний ciadpi Tachyon"
|
||||
|
||||
msgid "Unexpected Tachyon-managed nfqws runtime is running"
|
||||
msgstr "Обнаружен лишний NFQWS Tachyon"
|
||||
|
||||
msgid "Unexpected Tachyon-managed nfqws2 runtime is running"
|
||||
msgstr "Обнаружен лишний NFQWS2 Tachyon"
|
||||
|
||||
msgid "unique UCI identifier"
|
||||
msgstr "уникальный идентификатор UCI"
|
||||
|
||||
@@ -2192,8 +2192,8 @@ msgstr "Предупреждение: %s нельзя использовать
|
||||
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
|
||||
msgstr "Предупреждение: Russia inside может быть использован только с %s. %s уже есть в Russia inside и будет удален из выбранных."
|
||||
|
||||
msgid "What Forkop should do when this section matches"
|
||||
msgstr "Что Forkop должен делать при совпадении этой секции"
|
||||
msgid "What Tachyon should do when this section matches"
|
||||
msgstr "Что Tachyon должен делать при совпадении этой секции"
|
||||
|
||||
msgid "When switching to another level, test every server and select the fastest instead of the first working one."
|
||||
msgstr "При переходе на другой уровень тестировать все сервера и выбирать самый быстрый, а не первый работающий."
|
||||
@@ -2210,8 +2210,8 @@ msgstr "Да"
|
||||
msgid "You can select Output Network Interface, by default autodetect"
|
||||
msgstr "Вы можете выбрать выходной сетевой интерфейс, по умолчанию он определяется автоматически."
|
||||
|
||||
msgid "Zapret hostlist templates are not supported here because Forkop does not expand them for per-rule NFQWS strategies."
|
||||
msgstr "Шаблоны hostlist zapret здесь не поддерживаются, потому что Forkop не разворачивает их для per-rule стратегий NFQWS."
|
||||
msgid "Zapret hostlist templates are not supported here because Tachyon does not expand them for per-rule NFQWS strategies."
|
||||
msgstr "Шаблоны hostlist zapret здесь не поддерживаются, потому что Tachyon не разворачивает их для per-rule стратегий NFQWS."
|
||||
|
||||
msgid "Zapret package is installed"
|
||||
msgstr "Пакет Zapret установлен"
|
||||
@@ -2231,8 +2231,8 @@ msgstr "sing-box outbound для Zapret настроен"
|
||||
msgid "Zapret sing-box outbound is not configured"
|
||||
msgstr "sing-box outbound для Zapret не настроен"
|
||||
|
||||
msgid "Zapret2 hostlist templates are not supported here because Forkop does not expand them for per-rule NFQWS2 strategies."
|
||||
msgstr "Шаблоны hostlist Zapret2 здесь не поддерживаются, потому что Forkop не разворачивает их для per-rule стратегий NFQWS2."
|
||||
msgid "Zapret2 hostlist templates are not supported here because Tachyon does not expand them for per-rule NFQWS2 strategies."
|
||||
msgstr "Шаблоны hostlist Zapret2 здесь не поддерживаются, потому что Tachyon не разворачивает их для per-rule стратегий NFQWS2."
|
||||
|
||||
msgid "Zapret2 package is installed"
|
||||
msgstr "Пакет Zapret2 установлен"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export const FORKOP_UCI_PACKAGE = 'forkop';
|
||||
export const FORKOP_LUCI_APP_VERSION = '__COMPILED_VERSION_VARIABLE__';
|
||||
export const FORKOP_ACTION_PROVIDERS_AVAILABILITY_EVENT =
|
||||
'forkop:action-providers-availability';
|
||||
export const TACHYON_UCI_PACKAGE = 'tachyon';
|
||||
export const TACHYON_LUCI_APP_VERSION = '__COMPILED_VERSION_VARIABLE__';
|
||||
export const TACHYON_ACTION_PROVIDERS_AVAILABILITY_EVENT =
|
||||
'tachyon:action-providers-availability';
|
||||
export const FAKEIP_CHECK_DOMAIN = 'fakeip.podkop.fyi';
|
||||
export const IP_CHECK_DOMAIN = 'ip.podkop.fyi';
|
||||
export const DEFAULT_LATENCY_TEST_URL = 'https://www.gstatic.com/generate_204';
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { GlobalStyles } from '../styles';
|
||||
|
||||
const FORKOP_GLOBAL_STYLES_ID = 'forkop-global-styles';
|
||||
const TACHYON_GLOBAL_STYLES_ID = 'tachyon-global-styles';
|
||||
|
||||
export function injectGlobalStyles() {
|
||||
if (document.getElementById(FORKOP_GLOBAL_STYLES_ID)) {
|
||||
if (document.getElementById(TACHYON_GLOBAL_STYLES_ID)) {
|
||||
return;
|
||||
}
|
||||
|
||||
document.head.insertAdjacentHTML(
|
||||
'beforeend',
|
||||
`
|
||||
<style id="${FORKOP_GLOBAL_STYLES_ID}">
|
||||
<style id="${TACHYON_GLOBAL_STYLES_ID}">
|
||||
${GlobalStyles}
|
||||
</style>
|
||||
`,
|
||||
|
||||
@@ -7,7 +7,7 @@ import { describe, expect, it } from 'vitest';
|
||||
const testDir = path.dirname(fileURLToPath(import.meta.url));
|
||||
const serverViewPath = path.resolve(
|
||||
testDir,
|
||||
'../../../../luci-app-forkop/htdocs/luci-static/resources/view/forkop/server.js',
|
||||
'../../../../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js',
|
||||
);
|
||||
|
||||
function loadBuildHysteria2Link(values) {
|
||||
@@ -52,7 +52,7 @@ function loadBuildHysteria2Link(values) {
|
||||
},
|
||||
};
|
||||
|
||||
return factory(uci, 'forkop', { location: { hostname: 'router.lan' } });
|
||||
return factory(uci, 'tachyon', { location: { hostname: 'router.lan' } });
|
||||
}
|
||||
|
||||
describe('buildHysteria2Link', () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { logger } from '../forkop/services/logger.service';
|
||||
import { logger } from '../tachyon/services/logger.service';
|
||||
|
||||
export async function withTimeout<T>(
|
||||
promise: Promise<T>,
|
||||
|
||||
+10
-10
@@ -25,14 +25,14 @@ export { getProxyUrlName } from './helpers/getProxyUrlName';
|
||||
export { injectGlobalStyles } from './helpers/injectGlobalStyles';
|
||||
export { showToast } from './helpers/showToast';
|
||||
export { getClashUIUrl } from './helpers/getClashApiUrl';
|
||||
export { ForkopShellMethods } from './forkop/methods/shell';
|
||||
export { coreService } from './forkop/services/core.service';
|
||||
export { store } from './forkop/services/store.service';
|
||||
export { applyUiStateToStore } from './forkop/services/uiState.service';
|
||||
export { DashboardTab } from './forkop/tabs/dashboard';
|
||||
export { DiagnosticTab } from './forkop/tabs/diagnostic';
|
||||
export { MonitoringTab } from './forkop/tabs/monitoring';
|
||||
export { UpdatesTab } from './forkop/tabs/updates';
|
||||
export { TachyonShellMethods } from './tachyon/methods/shell';
|
||||
export { coreService } from './tachyon/services/core.service';
|
||||
export { store } from './tachyon/services/store.service';
|
||||
export { applyUiStateToStore } from './tachyon/services/uiState.service';
|
||||
export { DashboardTab } from './tachyon/tabs/dashboard';
|
||||
export { DiagnosticTab } from './tachyon/tabs/diagnostic';
|
||||
export { MonitoringTab } from './tachyon/tabs/monitoring';
|
||||
export { UpdatesTab } from './tachyon/tabs/updates';
|
||||
export {
|
||||
ALLOWED_WITH_RUSSIA_INSIDE,
|
||||
BOOTSTRAP_DNS_SERVER_OPTIONS,
|
||||
@@ -40,7 +40,7 @@ export {
|
||||
DNS_SERVER_OPTIONS,
|
||||
DOMAIN_LIST_OPTIONS,
|
||||
LATENCY_TEST_URL_OPTIONS,
|
||||
FORKOP_ACTION_PROVIDERS_AVAILABILITY_EVENT,
|
||||
FORKOP_UCI_PACKAGE,
|
||||
TACHYON_ACTION_PROVIDERS_AVAILABILITY_EVENT,
|
||||
TACHYON_UCI_PACKAGE,
|
||||
REGIONAL_OPTIONS,
|
||||
} from './constants';
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// language=CSS
|
||||
import { DashboardTab } from './forkop/tabs/dashboard';
|
||||
import { DiagnosticTab } from './forkop/tabs/diagnostic';
|
||||
import { MonitoringTab } from './forkop/tabs/monitoring';
|
||||
import { UpdatesTab } from './forkop/tabs/updates';
|
||||
import { DashboardTab } from './tachyon/tabs/dashboard';
|
||||
import { DiagnosticTab } from './tachyon/tabs/diagnostic';
|
||||
import { MonitoringTab } from './tachyon/tabs/monitoring';
|
||||
import { UpdatesTab } from './tachyon/tabs/updates';
|
||||
import { PartialStyles } from './partials';
|
||||
import { FORKOP_UCI_PACKAGE as FORKOP_CBI_PREFIX } from './constants';
|
||||
import { TACHYON_UCI_PACKAGE as TACHYON_CBI_PREFIX } from './constants';
|
||||
|
||||
export const GlobalStyles = `
|
||||
${DashboardTab.styles}
|
||||
@@ -15,49 +15,49 @@ ${PartialStyles}
|
||||
|
||||
|
||||
/* Hide extra H3 for settings tab */
|
||||
#cbi-${FORKOP_CBI_PREFIX}-settings > h3 {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-settings > h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Hide extra H3 for rules tab */
|
||||
#cbi-${FORKOP_CBI_PREFIX}-section > h3:nth-child(1) {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-section > h3:nth-child(1) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Vertical align for remove rule action button */
|
||||
#cbi-${FORKOP_CBI_PREFIX}-section > .cbi-section-remove {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-section > .cbi-section-remove {
|
||||
margin-bottom: -32px;
|
||||
}
|
||||
|
||||
#cbi-${FORKOP_CBI_PREFIX}-section .cbi-section-actions > div {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-section .cbi-section-actions > div {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
#cbi-${FORKOP_CBI_PREFIX}-section .cbi-section-actions {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-section .cbi-section-actions {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* Rule reorder visuals */
|
||||
#cbi-${FORKOP_CBI_PREFIX}-section {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-section {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#cbi-${FORKOP_CBI_PREFIX}-section .cbi-section-table-row {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-section .cbi-section-table-row {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#cbi-${FORKOP_CBI_PREFIX}-section .cbi-section-table-row.placeholder {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-section .cbi-section-table-row.placeholder {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#cbi-${FORKOP_CBI_PREFIX}-section .cbi-section-table-row.placeholder em {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-section .cbi-section-table-row.placeholder em {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#cbi-${FORKOP_CBI_PREFIX}-section .cbi-section-table-row.drag-over-above::after,
|
||||
#cbi-${FORKOP_CBI_PREFIX}-section .cbi-section-table-row.drag-over-below::after {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-section .cbi-section-table-row.drag-over-above::after,
|
||||
#cbi-${TACHYON_CBI_PREFIX}-section .cbi-section-table-row.drag-over-below::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
@@ -69,11 +69,11 @@ ${PartialStyles}
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#cbi-${FORKOP_CBI_PREFIX}-section .cbi-section-table-row.drag-over-above::after {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-section .cbi-section-table-row.drag-over-above::after {
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
#cbi-${FORKOP_CBI_PREFIX}-section .cbi-section-table-row.drag-over-below::after {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-section .cbi-section-table-row.drag-over-below::after {
|
||||
bottom: -1px;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { ForkopShellMethods } from '../methods';
|
||||
import { TachyonShellMethods } from '../methods';
|
||||
import { logger } from '../services/logger.service';
|
||||
import { store } from '../services/store.service';
|
||||
import { refreshRuntimeUiState } from '../services/runtimeUiState.service';
|
||||
import { Forkop } from '../types';
|
||||
import { Tachyon } from '../types';
|
||||
|
||||
let latestServicesInfoRequestId = 0;
|
||||
|
||||
function getSettledMethodResponse<T>(
|
||||
scope: string,
|
||||
result: PromiseSettledResult<Forkop.MethodResponse<T>>,
|
||||
): Forkop.MethodResponse<T> {
|
||||
result: PromiseSettledResult<Tachyon.MethodResponse<T>>,
|
||||
): Tachyon.MethodResponse<T> {
|
||||
if (result.status === 'fulfilled') {
|
||||
return result.value;
|
||||
}
|
||||
@@ -34,34 +34,34 @@ export async function fetchServicesInfo() {
|
||||
return uiState;
|
||||
}
|
||||
|
||||
const [forkopResult, singboxResult] = await Promise.allSettled([
|
||||
ForkopShellMethods.getStatus(),
|
||||
ForkopShellMethods.getSingBoxStatus(),
|
||||
const [tachyonResult, singboxResult] = await Promise.allSettled([
|
||||
TachyonShellMethods.getStatus(),
|
||||
TachyonShellMethods.getSingBoxStatus(),
|
||||
]);
|
||||
|
||||
if (requestId !== latestServicesInfoRequestId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const forkop = getSettledMethodResponse('getStatus', forkopResult);
|
||||
const tachyon = getSettledMethodResponse('getStatus', tachyonResult);
|
||||
const singbox = getSettledMethodResponse('getSingBoxStatus', singboxResult);
|
||||
const previousData = store.get().servicesInfoWidget.data;
|
||||
|
||||
store.set({
|
||||
servicesInfoWidget: {
|
||||
loading: false,
|
||||
failed: !forkop.success || !singbox.success,
|
||||
failed: !tachyon.success || !singbox.success,
|
||||
data: {
|
||||
singbox: singbox.success ? singbox.data.running : previousData.singbox,
|
||||
forkopRunning: forkop.success
|
||||
? forkop.data.running
|
||||
: previousData.forkopRunning,
|
||||
forkopEnabled: forkop.success
|
||||
? forkop.data.enabled
|
||||
: previousData.forkopEnabled,
|
||||
forkopStatus: forkop.success
|
||||
? forkop.data.status
|
||||
: previousData.forkopStatus,
|
||||
tachyonRunning: tachyon.success
|
||||
? tachyon.data.running
|
||||
: previousData.tachyonRunning,
|
||||
tachyonEnabled: tachyon.success
|
||||
? tachyon.data.enabled
|
||||
: previousData.tachyonEnabled,
|
||||
tachyonStatus: tachyon.success
|
||||
? tachyon.data.status
|
||||
: previousData.tachyonStatus,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -20,7 +20,7 @@ describe('fetchServicesInfo', () => {
|
||||
it('returns the fast UI state after applying it to the shared store', async () => {
|
||||
const uiState = {
|
||||
service: {
|
||||
forkop: {
|
||||
tachyon: {
|
||||
running: 1,
|
||||
enabled: 1,
|
||||
status: 'restarting',
|
||||
@@ -67,7 +67,7 @@ describe('fetchServicesInfo', () => {
|
||||
|
||||
const state = store.get();
|
||||
|
||||
expect(state.servicesInfoWidget.data.forkopStatus).toBe('restarting');
|
||||
expect(state.servicesInfoWidget.data.tachyonStatus).toBe('restarting');
|
||||
expect(state.diagnosticsActions.restart.loading).toBe(true);
|
||||
});
|
||||
|
||||
@@ -78,9 +78,9 @@ describe('fetchServicesInfo', () => {
|
||||
failed: false,
|
||||
data: {
|
||||
singbox: 1,
|
||||
forkopRunning: 1,
|
||||
forkopEnabled: 1,
|
||||
forkopStatus: 'running & enabled',
|
||||
tachyonRunning: 1,
|
||||
tachyonEnabled: 1,
|
||||
tachyonStatus: 'running & enabled',
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -113,9 +113,9 @@ describe('fetchServicesInfo', () => {
|
||||
expect(state.servicesInfoWidget.failed).toBe(true);
|
||||
expect(state.servicesInfoWidget.data).toEqual({
|
||||
singbox: 0,
|
||||
forkopRunning: 1,
|
||||
forkopEnabled: 1,
|
||||
forkopStatus: 'running & enabled',
|
||||
tachyonRunning: 1,
|
||||
tachyonEnabled: 1,
|
||||
tachyonStatus: 'running & enabled',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { StoreType } from '../services/store.service';
|
||||
import type { Forkop } from '../types';
|
||||
import type { Tachyon } from '../types';
|
||||
|
||||
export type UpdatesActionKey = keyof StoreType['updatesActions'];
|
||||
|
||||
const componentActionKeyMap: Record<string, UpdatesActionKey> = {
|
||||
'forkop:check_update': 'forkopCheck',
|
||||
'forkop:install': 'forkopInstall',
|
||||
'tachyon:check_update': 'tachyonCheck',
|
||||
'tachyon:install': 'tachyonInstall',
|
||||
'sing_box:check_update': 'singBoxCheck',
|
||||
'sing_box:install': 'singBoxInstall',
|
||||
'sing_box:install_extended': 'singBoxInstallExtended',
|
||||
@@ -24,8 +24,8 @@ const componentActionKeyMap: Record<string, UpdatesActionKey> = {
|
||||
};
|
||||
|
||||
export function getComponentActionKey(
|
||||
component: Forkop.ComponentName,
|
||||
action: Forkop.ComponentAction,
|
||||
component: Tachyon.ComponentName,
|
||||
action: Tachyon.ComponentAction,
|
||||
): UpdatesActionKey | undefined {
|
||||
return componentActionKeyMap[`${component}:${action}`];
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Forkop } from '../../types';
|
||||
import { FORKOP_UCI_PACKAGE } from '../../../constants';
|
||||
import { Tachyon } from '../../types';
|
||||
import { TACHYON_UCI_PACKAGE } from '../../../constants';
|
||||
|
||||
export async function getConfigSections(): Promise<Forkop.ConfigSection[]> {
|
||||
export async function getConfigSections(): Promise<Tachyon.ConfigSection[]> {
|
||||
return uci
|
||||
.load(FORKOP_UCI_PACKAGE)
|
||||
.then(() => uci.sections(FORKOP_UCI_PACKAGE));
|
||||
.load(TACHYON_UCI_PACKAGE)
|
||||
.then(() => uci.sections(TACHYON_UCI_PACKAGE));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getConfigSections } from './getConfigSections';
|
||||
import { ClashAPI, Forkop } from '../../types';
|
||||
import { ClashAPI, Tachyon } from '../../types';
|
||||
import {
|
||||
canUseDirectClashApi,
|
||||
getClashHttpUrl,
|
||||
@@ -7,11 +7,11 @@ import {
|
||||
isCopyableProxyLink,
|
||||
} from '../../../helpers';
|
||||
import { getOutboundTagBySection } from '../../runtimeTags';
|
||||
import { ForkopShellMethods } from '../shell';
|
||||
import { TachyonShellMethods } from '../shell';
|
||||
|
||||
interface IGetDashboardSectionsResponse {
|
||||
success: boolean;
|
||||
data: Forkop.OutboundGroup[];
|
||||
data: Tachyon.OutboundGroup[];
|
||||
}
|
||||
|
||||
interface IGetDashboardSectionsOptions {
|
||||
@@ -28,12 +28,12 @@ type DashboardSectionCache = {
|
||||
section?: string;
|
||||
links?: Record<string, string>;
|
||||
linkRefs?: Record<string, unknown>;
|
||||
outboundMetadata?: Forkop.GetOutboundMetadata;
|
||||
outboundMetadata?: Tachyon.GetOutboundMetadata;
|
||||
urltestGroups?: Record<string, UrlTestCacheGroup>;
|
||||
priorityGroups?: Record<string, PriorityCacheGroup>;
|
||||
subscriptionMetadata?:
|
||||
| Forkop.SubscriptionMetadata
|
||||
| Forkop.SubscriptionMetadata[];
|
||||
| Tachyon.SubscriptionMetadata
|
||||
| Tachyon.SubscriptionMetadata[];
|
||||
};
|
||||
|
||||
type UrlTestCacheGroup = {
|
||||
@@ -130,21 +130,21 @@ type ChildType =
|
||||
| 'priority_group'
|
||||
| 'priority_level';
|
||||
|
||||
const DASHBOARD_SECTION_CACHE_DIR = '/var/run/forkop/section-cache';
|
||||
const DASHBOARD_SECTION_CACHE_DIR = '/var/run/tachyon/section-cache';
|
||||
|
||||
function getDisplayName(section: Forkop.ConfigSection) {
|
||||
function getDisplayName(section: Tachyon.ConfigSection) {
|
||||
return section.label || section['.name'];
|
||||
}
|
||||
|
||||
function getSectionAction(section: Forkop.ConfigSection) {
|
||||
function getSectionAction(section: Tachyon.ConfigSection) {
|
||||
return section.action || '';
|
||||
}
|
||||
|
||||
function getSettingsSection(configSections: Forkop.ConfigSection[]) {
|
||||
function getSettingsSection(configSections: Tachyon.ConfigSection[]) {
|
||||
return configSections.find((section) => section['.type'] === 'settings');
|
||||
}
|
||||
|
||||
function getClashApiSecret(configSections: Forkop.ConfigSection[]) {
|
||||
function getClashApiSecret(configSections: Tachyon.ConfigSection[]) {
|
||||
return getSettingsSection(configSections)?.yacd_secret_key || '';
|
||||
}
|
||||
|
||||
@@ -153,8 +153,8 @@ function canFetchClashApiDirectly() {
|
||||
}
|
||||
|
||||
async function getClashApiProxies(
|
||||
configSections: Forkop.ConfigSection[],
|
||||
): Promise<Forkop.MethodResponse<ClashAPI.Proxies>> {
|
||||
configSections: Tachyon.ConfigSection[],
|
||||
): Promise<Tachyon.MethodResponse<ClashAPI.Proxies>> {
|
||||
if (canFetchClashApiDirectly()) {
|
||||
const secret = getClashApiSecret(configSections);
|
||||
|
||||
@@ -174,7 +174,7 @@ async function getClashApiProxies(
|
||||
}
|
||||
}
|
||||
|
||||
return ForkopShellMethods.getClashApiProxies();
|
||||
return TachyonShellMethods.getClashApiProxies();
|
||||
}
|
||||
|
||||
function getListValues(value?: string[] | string) {
|
||||
@@ -193,25 +193,25 @@ function getListValues(value?: string[] | string) {
|
||||
}
|
||||
|
||||
function childSections(
|
||||
configSections: Forkop.ConfigSection[],
|
||||
configSections: Tachyon.ConfigSection[],
|
||||
type: ChildType,
|
||||
) {
|
||||
return configSections.filter((section) => section['.type'] === type);
|
||||
}
|
||||
|
||||
function ownedChildSections(
|
||||
parent: Forkop.ConfigSection,
|
||||
children: Forkop.ConfigSection[],
|
||||
parent: Tachyon.ConfigSection,
|
||||
children: Tachyon.ConfigSection[],
|
||||
) {
|
||||
return children.filter(
|
||||
(section): section is Forkop.ConfigSection =>
|
||||
(section): section is Tachyon.ConfigSection =>
|
||||
section.section === parent['.name'],
|
||||
);
|
||||
}
|
||||
|
||||
function childSectionsByOwner(
|
||||
children: Forkop.ConfigSection[],
|
||||
ownerKey: keyof Forkop.ConfigSection,
|
||||
children: Tachyon.ConfigSection[],
|
||||
ownerKey: keyof Tachyon.ConfigSection,
|
||||
ownerValue: string,
|
||||
) {
|
||||
return children.filter((section) => section[ownerKey] === ownerValue);
|
||||
@@ -221,7 +221,7 @@ function compactSettingsMap(settings: Record<string, ItemSettings>) {
|
||||
return Object.keys(settings).length ? JSON.stringify(settings) : undefined;
|
||||
}
|
||||
|
||||
function hydrateConfigSections(configSections: Forkop.ConfigSection[]) {
|
||||
function hydrateConfigSections(configSections: Tachyon.ConfigSection[]) {
|
||||
const subscriptionUrls = childSections(configSections, 'subscription_url');
|
||||
const interfaces = childSections(configSections, 'section_interface');
|
||||
const urltests = childSections(configSections, 'urltest');
|
||||
@@ -233,7 +233,7 @@ function hydrateConfigSections(configSections: Forkop.ConfigSection[]) {
|
||||
return section;
|
||||
}
|
||||
|
||||
const next: Forkop.ConfigSection = { ...section };
|
||||
const next: Tachyon.ConfigSection = { ...section };
|
||||
const subscriptionUrlItems = ownedChildSections(next, subscriptionUrls);
|
||||
const interfaceItems = ownedChildSections(next, interfaces);
|
||||
const urltestItems = ownedChildSections(next, urltests);
|
||||
@@ -350,16 +350,16 @@ function hydrateConfigSections(configSections: Forkop.ConfigSection[]) {
|
||||
});
|
||||
}
|
||||
|
||||
function getManualProxyLinks(section: Forkop.ConfigSection) {
|
||||
function getManualProxyLinks(section: Tachyon.ConfigSection) {
|
||||
return getListValues(section.selector_proxy_links);
|
||||
}
|
||||
|
||||
function getConnectionInterfaces(section: Forkop.ConfigSection) {
|
||||
function getConnectionInterfaces(section: Tachyon.ConfigSection) {
|
||||
const values = getListValues(section.interfaces);
|
||||
return values.length ? values : getListValues(section.interface);
|
||||
}
|
||||
|
||||
function getJsonOutbounds(section: Forkop.ConfigSection) {
|
||||
function getJsonOutbounds(section: Tachyon.ConfigSection) {
|
||||
const values = getListValues(section.outbound_jsons);
|
||||
return values.length ? values : getListValues(section.outbound_json);
|
||||
}
|
||||
@@ -368,27 +368,27 @@ function isConnectionAction(action: string) {
|
||||
return ['connection', 'proxy', 'outbound', 'vpn'].includes(action);
|
||||
}
|
||||
|
||||
function hasSubscriptionSources(section: Forkop.ConfigSection) {
|
||||
function hasSubscriptionSources(section: Tachyon.ConfigSection) {
|
||||
return getSubscriptionSourceCount(section) > 0;
|
||||
}
|
||||
|
||||
function getSubscriptionSourceCount(section: Forkop.ConfigSection) {
|
||||
function getSubscriptionSourceCount(section: Tachyon.ConfigSection) {
|
||||
return getListValues(section.subscription_urls).length;
|
||||
}
|
||||
|
||||
function shouldSortByLatency(section: Forkop.ConfigSection) {
|
||||
function shouldSortByLatency(section: Tachyon.ConfigSection) {
|
||||
return section.sort_by_latency === '1';
|
||||
}
|
||||
|
||||
function hasConfiguredUrlTestList(section: Forkop.ConfigSection) {
|
||||
function hasConfiguredUrlTestList(section: Tachyon.ConfigSection) {
|
||||
return getListValues(section.urltests).length > 0;
|
||||
}
|
||||
|
||||
function hasConfiguredPriorityList(section: Forkop.ConfigSection) {
|
||||
function hasConfiguredPriorityList(section: Tachyon.ConfigSection) {
|
||||
return getListValues(section.priority_groups).length > 0;
|
||||
}
|
||||
|
||||
function getUrlTestIds(section: Forkop.ConfigSection) {
|
||||
function getUrlTestIds(section: Tachyon.ConfigSection) {
|
||||
const values = getListValues(section.urltests);
|
||||
return values.length
|
||||
? values
|
||||
@@ -397,11 +397,11 @@ function getUrlTestIds(section: Forkop.ConfigSection) {
|
||||
: [];
|
||||
}
|
||||
|
||||
function isUrlTestEnabled(section: Forkop.ConfigSection) {
|
||||
function isUrlTestEnabled(section: Tachyon.ConfigSection) {
|
||||
return getUrlTestIds(section).length > 0;
|
||||
}
|
||||
|
||||
function shouldUseProxyGroup(section: Forkop.ConfigSection) {
|
||||
function shouldUseProxyGroup(section: Tachyon.ConfigSection) {
|
||||
return (
|
||||
getManualProxyLinks(section).length > 0 ||
|
||||
hasSubscriptionSources(section) ||
|
||||
@@ -412,7 +412,7 @@ function shouldUseProxyGroup(section: Forkop.ConfigSection) {
|
||||
);
|
||||
}
|
||||
|
||||
function getSectionProxyConfigType(section: Forkop.ConfigSection) {
|
||||
function getSectionProxyConfigType(section: Tachyon.ConfigSection) {
|
||||
if (hasSubscriptionSources(section)) {
|
||||
return 'subscription' as const;
|
||||
}
|
||||
@@ -440,7 +440,7 @@ function getSectionProxyConfigType(section: Forkop.ConfigSection) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getJsonOutboundDisplayName(section: Forkop.ConfigSection) {
|
||||
function getJsonOutboundDisplayName(section: Tachyon.ConfigSection) {
|
||||
try {
|
||||
const parsedOutbound = JSON.parse(section.outbound_json || '{}');
|
||||
return parsedOutbound?.tag ? decodeURIComponent(parsedOutbound.tag) : '';
|
||||
@@ -449,7 +449,7 @@ function getJsonOutboundDisplayName(section: Forkop.ConfigSection) {
|
||||
}
|
||||
}
|
||||
|
||||
function buildManualLinkByCode(section: Forkop.ConfigSection) {
|
||||
function buildManualLinkByCode(section: Tachyon.ConfigSection) {
|
||||
const sectionName = section['.name'];
|
||||
|
||||
return new Map(
|
||||
@@ -468,7 +468,7 @@ function uniqueCodes(codes: string[]) {
|
||||
return Array.from(new Set(codes.filter(Boolean)));
|
||||
}
|
||||
|
||||
function isSelectorOutbound(outbound: Forkop.Outbound) {
|
||||
function isSelectorOutbound(outbound: Tachyon.Outbound) {
|
||||
return outbound.type?.toLowerCase() === 'selector';
|
||||
}
|
||||
|
||||
@@ -485,7 +485,7 @@ function getLatencySortValue(outbound: { latency: number }) {
|
||||
}
|
||||
|
||||
function sortOutboundsForDashboard(
|
||||
outbounds: Forkop.Outbound[],
|
||||
outbounds: Tachyon.Outbound[],
|
||||
options: {
|
||||
pinnedCode?: string;
|
||||
pinnedCodes?: string[];
|
||||
@@ -536,7 +536,7 @@ function sortOutboundsForDashboard(
|
||||
.map((item) => item.outbound);
|
||||
}
|
||||
|
||||
function sortUrlTestMembers(outbounds: Forkop.UrlTestMember[]) {
|
||||
function sortUrlTestMembers(outbounds: Tachyon.UrlTestMember[]) {
|
||||
return outbounds
|
||||
.map((outbound, index) => ({ outbound, index }))
|
||||
.sort((left, right) => {
|
||||
@@ -636,7 +636,7 @@ function getPriorityTag(sectionName: string, id: string) {
|
||||
}
|
||||
|
||||
function getUrlTestDisplayName(
|
||||
section: Forkop.ConfigSection,
|
||||
section: Tachyon.ConfigSection,
|
||||
id: string,
|
||||
settings: ItemSettings | undefined,
|
||||
) {
|
||||
@@ -647,7 +647,7 @@ function getUrlTestDisplayName(
|
||||
);
|
||||
}
|
||||
|
||||
function getUrlTestConfigs(section: Forkop.ConfigSection): UrlTestConfig[] {
|
||||
function getUrlTestConfigs(section: Tachyon.ConfigSection): UrlTestConfig[] {
|
||||
const settingsMap = itemSettingsMap(section.urltest_settings);
|
||||
const sectionName = section['.name'];
|
||||
|
||||
@@ -730,11 +730,11 @@ function priorityLevelConfigsFromSettings(
|
||||
);
|
||||
}
|
||||
|
||||
function getPriorityGroupIds(section: Forkop.ConfigSection) {
|
||||
function getPriorityGroupIds(section: Tachyon.ConfigSection) {
|
||||
return getListValues(section.priority_groups);
|
||||
}
|
||||
|
||||
function getPriorityConfigs(section: Forkop.ConfigSection): PriorityConfig[] {
|
||||
function getPriorityConfigs(section: Tachyon.ConfigSection): PriorityConfig[] {
|
||||
const settingsMap = itemSettingsMap(section.priority_group_settings);
|
||||
const sectionName = section['.name'];
|
||||
|
||||
@@ -840,7 +840,7 @@ function getOutboundDisplayName(
|
||||
code: string,
|
||||
entry: ClashProxyEntry | undefined,
|
||||
link: string,
|
||||
outboundMetadata?: Forkop.GetOutboundMetadata,
|
||||
outboundMetadata?: Tachyon.GetOutboundMetadata,
|
||||
preferMetadata = false,
|
||||
) {
|
||||
const metadataName = outboundMetadata?.names?.[code];
|
||||
@@ -872,10 +872,10 @@ function buildUrlTestInfo({
|
||||
proxyByCode: Map<string, ClashProxyEntry>;
|
||||
manualLinkByCode: Map<string, string>;
|
||||
cachedProxyLinks: Map<string, string>;
|
||||
outboundMetadata?: Forkop.GetOutboundMetadata;
|
||||
outboundMetadata?: Tachyon.GetOutboundMetadata;
|
||||
subscriptionCopyableCodes: Set<string>;
|
||||
showDetectedCountries: boolean;
|
||||
}): Forkop.UrlTestInfo {
|
||||
}): Tachyon.UrlTestInfo {
|
||||
const childCodes = uniqueCodes(
|
||||
groupCache?.outbounds?.length
|
||||
? groupCache.outbounds
|
||||
@@ -949,10 +949,10 @@ function buildPriorityInfo({
|
||||
proxyByCode: Map<string, ClashProxyEntry>;
|
||||
manualLinkByCode: Map<string, string>;
|
||||
cachedProxyLinks: Map<string, string>;
|
||||
outboundMetadata?: Forkop.GetOutboundMetadata;
|
||||
outboundMetadata?: Tachyon.GetOutboundMetadata;
|
||||
subscriptionCopyableCodes: Set<string>;
|
||||
showDetectedCountries: boolean;
|
||||
}): Forkop.PriorityInfo {
|
||||
}): Tachyon.PriorityInfo {
|
||||
const selectedCode = entry?.value.now || '';
|
||||
const cacheLevels = Array.isArray(groupCache?.levels)
|
||||
? groupCache.levels
|
||||
@@ -1076,9 +1076,9 @@ function buildPriorityInfo({
|
||||
}
|
||||
|
||||
function buildProxyGroupOutbounds(
|
||||
section: Forkop.ConfigSection,
|
||||
section: Tachyon.ConfigSection,
|
||||
proxies: ClashProxyEntry[],
|
||||
outboundMetadata?: Forkop.GetOutboundMetadata,
|
||||
outboundMetadata?: Tachyon.GetOutboundMetadata,
|
||||
urltestGroups: Record<string, UrlTestCacheGroup> = {},
|
||||
priorityGroups: Record<string, PriorityCacheGroup> = {},
|
||||
subscriptionCopyableCodes: Set<string> = new Set(),
|
||||
@@ -1261,9 +1261,9 @@ function buildProxyGroupOutbounds(
|
||||
function metadataMatchesCurrentSource(
|
||||
sectionName: string,
|
||||
sourceCount: number,
|
||||
metadata: Forkop.SubscriptionMetadata,
|
||||
metadata: Tachyon.SubscriptionMetadata,
|
||||
) {
|
||||
const legacyMetadata = metadata as Forkop.SubscriptionMetadata & {
|
||||
const legacyMetadata = metadata as Tachyon.SubscriptionMetadata & {
|
||||
source_index?: number;
|
||||
source_section?: string;
|
||||
};
|
||||
@@ -1315,9 +1315,9 @@ function metadataMatchesCurrentSource(
|
||||
function getSubscriptionMetadataSourceIndex(
|
||||
sectionName: string,
|
||||
sourceCount: number,
|
||||
metadata: Forkop.SubscriptionMetadata,
|
||||
metadata: Tachyon.SubscriptionMetadata,
|
||||
) {
|
||||
const legacyMetadata = metadata as Forkop.SubscriptionMetadata & {
|
||||
const legacyMetadata = metadata as Tachyon.SubscriptionMetadata & {
|
||||
source_index?: number;
|
||||
source_section?: string;
|
||||
};
|
||||
@@ -1340,9 +1340,9 @@ function getSubscriptionMetadataSourceIndex(
|
||||
}
|
||||
|
||||
function isSubscriptionMetadataVisible(
|
||||
section: Forkop.ConfigSection,
|
||||
section: Tachyon.ConfigSection,
|
||||
sourceCount: number,
|
||||
metadata: Forkop.SubscriptionMetadata,
|
||||
metadata: Tachyon.SubscriptionMetadata,
|
||||
) {
|
||||
const sourceIndex = getSubscriptionMetadataSourceIndex(
|
||||
section['.name'],
|
||||
@@ -1363,7 +1363,7 @@ function isSubscriptionMetadataVisible(
|
||||
}
|
||||
|
||||
function getSubscriptionMetadata(
|
||||
section: Forkop.ConfigSection,
|
||||
section: Tachyon.ConfigSection,
|
||||
sourceCount: number,
|
||||
dashboardCache?: DashboardSectionCache,
|
||||
) {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { getConfigSections } from './getConfigSections';
|
||||
import { getDashboardSections } from './getDashboardSections';
|
||||
import { getClashApiSecret } from './getClashApiSecret';
|
||||
|
||||
export const CustomForkopMethods = {
|
||||
export const CustomTachyonMethods = {
|
||||
getConfigSections,
|
||||
getDashboardSections,
|
||||
getClashApiSecret,
|
||||
|
||||
@@ -12,7 +12,7 @@ vi.mock('../getConfigSections', () => ({
|
||||
}));
|
||||
|
||||
vi.mock('../../shell', () => ({
|
||||
ForkopShellMethods: {
|
||||
TachyonShellMethods: {
|
||||
getClashApiProxies: mocks.getClashApiProxies,
|
||||
},
|
||||
}));
|
||||
@@ -26,7 +26,7 @@ vi.mock('../../../../helpers', () => ({
|
||||
}));
|
||||
|
||||
import { getDashboardSections } from '../getDashboardSections';
|
||||
import { ClashAPI, Forkop } from '../../../types';
|
||||
import { ClashAPI, Tachyon } from '../../../types';
|
||||
|
||||
function proxy(
|
||||
type: string,
|
||||
@@ -43,8 +43,8 @@ function proxy(
|
||||
}
|
||||
|
||||
function proxySection(
|
||||
options: Partial<Forkop.ConfigSection> = {},
|
||||
): Forkop.ConfigSection {
|
||||
options: Partial<Tachyon.ConfigSection> = {},
|
||||
): Tachyon.ConfigSection {
|
||||
return {
|
||||
'.name': 'main',
|
||||
'.type': 'section',
|
||||
@@ -71,8 +71,8 @@ function urlTestSettings(
|
||||
|
||||
function priorityGroup(
|
||||
id: string,
|
||||
options: Partial<Forkop.ConfigSection> = {},
|
||||
): Forkop.ConfigSection {
|
||||
options: Partial<Tachyon.ConfigSection> = {},
|
||||
): Tachyon.ConfigSection {
|
||||
return {
|
||||
'.name': id,
|
||||
'.type': 'priority_group',
|
||||
@@ -94,8 +94,8 @@ function priorityGroup(
|
||||
|
||||
function priorityLevel(
|
||||
id: string,
|
||||
options: Partial<Forkop.ConfigSection> = {},
|
||||
): Forkop.ConfigSection {
|
||||
options: Partial<Tachyon.ConfigSection> = {},
|
||||
): Tachyon.ConfigSection {
|
||||
return {
|
||||
'.name': id,
|
||||
'.type': 'priority_level',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { executeShellCommand } from '../../../helpers';
|
||||
import { Forkop } from '../../types';
|
||||
import { Tachyon } from '../../types';
|
||||
|
||||
interface CallBaseMethodOptions {
|
||||
allowNonZeroWithStdout?: boolean;
|
||||
@@ -7,11 +7,11 @@ interface CallBaseMethodOptions {
|
||||
}
|
||||
|
||||
export async function callBaseMethod<T>(
|
||||
method: Forkop.AvailableMethods,
|
||||
method: Tachyon.AvailableMethods,
|
||||
args: string[] = [],
|
||||
command: string = '/usr/bin/forkop',
|
||||
command: string = '/usr/bin/tachyon',
|
||||
options: CallBaseMethodOptions = {},
|
||||
): Promise<Forkop.MethodResponse<T>> {
|
||||
): Promise<Tachyon.MethodResponse<T>> {
|
||||
try {
|
||||
const response = await executeShellCommand({
|
||||
command,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { callBaseMethod } from './callBaseMethod';
|
||||
import { ClashAPI, Forkop } from '../../types';
|
||||
import { ClashAPI, Tachyon } from '../../types';
|
||||
import { executeShellCommand } from '../../../helpers';
|
||||
import { isTransientRpcError } from '../../helpers/isTransientRpcError';
|
||||
|
||||
@@ -16,7 +16,7 @@ const COMPONENT_ACTION_POLL_INTERVAL_MS = 1500;
|
||||
const COMPONENT_ACTION_STATUS_REFRESH_INTERVAL_MS = 15000;
|
||||
const COMPONENT_ACTION_SELF_UPDATE_SETTLE_MS = 30000;
|
||||
const COMPONENT_ACTION_TRANSIENT_RPC_GRACE_MS = 30000;
|
||||
const COMPONENT_ACTION_STATE_DIR = '/var/run/forkop/component-actions';
|
||||
const COMPONENT_ACTION_STATE_DIR = '/var/run/tachyon/component-actions';
|
||||
const GET_UI_STATE_RPC_TIMEOUT_MS = 3000;
|
||||
|
||||
function sleep(ms: number) {
|
||||
@@ -50,7 +50,7 @@ function parseJsonObjectOutput<T>(output: string): T | null {
|
||||
}
|
||||
|
||||
function parseComponentActionOutput(output: string) {
|
||||
return parseJsonObjectOutput<Forkop.ComponentActionResult>(output);
|
||||
return parseJsonObjectOutput<Tachyon.ComponentActionResult>(output);
|
||||
}
|
||||
|
||||
function parseComponentActionResult(
|
||||
@@ -68,13 +68,13 @@ function parseComponentActionStartResult(
|
||||
return null;
|
||||
}
|
||||
|
||||
return parsedResponse as unknown as Forkop.ComponentActionStartResult;
|
||||
return parsedResponse as unknown as Tachyon.ComponentActionStartResult;
|
||||
}
|
||||
|
||||
function parseSubscriptionUpdateStartResult(
|
||||
response: Awaited<ReturnType<typeof executeShellCommand>>,
|
||||
) {
|
||||
return parseJsonObjectOutput<Forkop.SubscriptionUpdateStartResult>(
|
||||
return parseJsonObjectOutput<Tachyon.SubscriptionUpdateStartResult>(
|
||||
response.stdout,
|
||||
);
|
||||
}
|
||||
@@ -82,7 +82,7 @@ function parseSubscriptionUpdateStartResult(
|
||||
function parseSubscriptionUpdateJobState(
|
||||
response: Awaited<ReturnType<typeof executeShellCommand>>,
|
||||
) {
|
||||
return parseJsonObjectOutput<Forkop.SubscriptionUpdateJobState>(
|
||||
return parseJsonObjectOutput<Tachyon.SubscriptionUpdateJobState>(
|
||||
response.stdout,
|
||||
);
|
||||
}
|
||||
@@ -90,19 +90,19 @@ function parseSubscriptionUpdateJobState(
|
||||
function parseUiActionStartResult(
|
||||
response: Awaited<ReturnType<typeof executeShellCommand>>,
|
||||
) {
|
||||
return parseJsonObjectOutput<Forkop.UiActionStartResult>(response.stdout);
|
||||
return parseJsonObjectOutput<Tachyon.UiActionStartResult>(response.stdout);
|
||||
}
|
||||
|
||||
function parseServiceActionState(
|
||||
response: Awaited<ReturnType<typeof executeShellCommand>>,
|
||||
) {
|
||||
return parseJsonObjectOutput<Forkop.ServiceActionState>(response.stdout);
|
||||
return parseJsonObjectOutput<Tachyon.ServiceActionState>(response.stdout);
|
||||
}
|
||||
|
||||
function parseLatencyActionState(
|
||||
response: Awaited<ReturnType<typeof executeShellCommand>>,
|
||||
) {
|
||||
return parseJsonObjectOutput<Forkop.LatencyActionState>(response.stdout);
|
||||
return parseJsonObjectOutput<Tachyon.LatencyActionState>(response.stdout);
|
||||
}
|
||||
|
||||
function isComponentActionJobId(jobId: string) {
|
||||
@@ -123,9 +123,9 @@ async function readComponentActionState(jobId: string) {
|
||||
}
|
||||
}
|
||||
|
||||
async function readForkopVersion() {
|
||||
async function readTachyonVersion() {
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/forkop',
|
||||
command: '/usr/bin/tachyon',
|
||||
args: ['show_version'],
|
||||
timeout: COMPONENT_ACTION_RPC_TIMEOUT_MS,
|
||||
});
|
||||
@@ -139,13 +139,13 @@ async function readForkopVersion() {
|
||||
|
||||
async function isComponentActionStillRunning(
|
||||
jobId: string,
|
||||
component: Forkop.ComponentName,
|
||||
action: Forkop.ComponentAction,
|
||||
component: Tachyon.ComponentName,
|
||||
action: Tachyon.ComponentAction,
|
||||
) {
|
||||
const response = await callBaseMethod<Forkop.UiState>(
|
||||
Forkop.AvailableMethods.GET_UI_STATE,
|
||||
const response = await callBaseMethod<Tachyon.UiState>(
|
||||
Tachyon.AvailableMethods.GET_UI_STATE,
|
||||
[],
|
||||
'/usr/bin/forkop',
|
||||
'/usr/bin/tachyon',
|
||||
{ timeout: GET_UI_STATE_RPC_TIMEOUT_MS },
|
||||
);
|
||||
|
||||
@@ -163,12 +163,12 @@ async function isComponentActionStillRunning(
|
||||
|
||||
function componentActionFailure(
|
||||
response: Awaited<ReturnType<typeof executeShellCommand>>,
|
||||
parsedResponse?: Pick<Forkop.ComponentActionResult, 'message'> | null,
|
||||
parsedResponse?: Pick<Tachyon.ComponentActionResult, 'message'> | null,
|
||||
) {
|
||||
return {
|
||||
success: false,
|
||||
error: parsedResponse?.message || response.stderr || _('Failed to execute'),
|
||||
} as Forkop.MethodFailureResponse;
|
||||
} as Tachyon.MethodFailureResponse;
|
||||
}
|
||||
|
||||
function uiActionFailure(
|
||||
@@ -179,7 +179,7 @@ function uiActionFailure(
|
||||
return {
|
||||
success: false,
|
||||
error: parsedResponse?.message || response.stderr || fallback,
|
||||
} as Forkop.MethodFailureResponse;
|
||||
} as Tachyon.MethodFailureResponse;
|
||||
}
|
||||
|
||||
function createTransientRpcGraceTracker(graceMs: number) {
|
||||
@@ -204,170 +204,170 @@ function createTransientRpcGraceTracker(graceMs: number) {
|
||||
};
|
||||
}
|
||||
|
||||
export const ForkopShellMethods = {
|
||||
export const TachyonShellMethods = {
|
||||
checkDNSAvailable: async () =>
|
||||
callBaseMethod<Forkop.DnsCheckResult>(
|
||||
Forkop.AvailableMethods.CHECK_DNS_AVAILABLE,
|
||||
callBaseMethod<Tachyon.DnsCheckResult>(
|
||||
Tachyon.AvailableMethods.CHECK_DNS_AVAILABLE,
|
||||
),
|
||||
checkFakeIP: async () =>
|
||||
callBaseMethod<Forkop.FakeIPCheckResult>(
|
||||
Forkop.AvailableMethods.CHECK_FAKEIP,
|
||||
callBaseMethod<Tachyon.FakeIPCheckResult>(
|
||||
Tachyon.AvailableMethods.CHECK_FAKEIP,
|
||||
),
|
||||
checkNftRules: async () =>
|
||||
callBaseMethod<Forkop.NftRulesCheckResult>(
|
||||
Forkop.AvailableMethods.CHECK_NFT_RULES,
|
||||
callBaseMethod<Tachyon.NftRulesCheckResult>(
|
||||
Tachyon.AvailableMethods.CHECK_NFT_RULES,
|
||||
),
|
||||
checkZapretRuntime: async () =>
|
||||
callBaseMethod<Forkop.ZapretCheckResult>(
|
||||
Forkop.AvailableMethods.CHECK_ZAPRET_RUNTIME,
|
||||
callBaseMethod<Tachyon.ZapretCheckResult>(
|
||||
Tachyon.AvailableMethods.CHECK_ZAPRET_RUNTIME,
|
||||
),
|
||||
checkZapret2Runtime: async () =>
|
||||
callBaseMethod<Forkop.Zapret2CheckResult>(
|
||||
Forkop.AvailableMethods.CHECK_ZAPRET2_RUNTIME,
|
||||
callBaseMethod<Tachyon.Zapret2CheckResult>(
|
||||
Tachyon.AvailableMethods.CHECK_ZAPRET2_RUNTIME,
|
||||
),
|
||||
checkByedpiRuntime: async () =>
|
||||
callBaseMethod<Forkop.ByedpiCheckResult>(
|
||||
Forkop.AvailableMethods.CHECK_BYEDPI_RUNTIME,
|
||||
callBaseMethod<Tachyon.ByedpiCheckResult>(
|
||||
Tachyon.AvailableMethods.CHECK_BYEDPI_RUNTIME,
|
||||
),
|
||||
checkInboundsConfig: async () =>
|
||||
callBaseMethod<Forkop.InboundsConfigCheckResult>(
|
||||
Forkop.AvailableMethods.CHECK_INBOUNDS_CONFIG,
|
||||
callBaseMethod<Tachyon.InboundsConfigCheckResult>(
|
||||
Tachyon.AvailableMethods.CHECK_INBOUNDS_CONFIG,
|
||||
),
|
||||
getStatus: async () =>
|
||||
callBaseMethod<Forkop.GetStatus>(Forkop.AvailableMethods.GET_STATUS),
|
||||
callBaseMethod<Tachyon.GetStatus>(Tachyon.AvailableMethods.GET_STATUS),
|
||||
getOutboundLink: async (section: string, tag: string) =>
|
||||
callBaseMethod<Forkop.GetOutboundLink>(
|
||||
Forkop.AvailableMethods.GET_OUTBOUND_LINK,
|
||||
callBaseMethod<Tachyon.GetOutboundLink>(
|
||||
Tachyon.AvailableMethods.GET_OUTBOUND_LINK,
|
||||
[section, tag],
|
||||
),
|
||||
getOutboundLinkStates: async (section: string) =>
|
||||
callBaseMethod<Forkop.GetOutboundLinkStates>(
|
||||
Forkop.AvailableMethods.GET_OUTBOUND_LINK_STATES,
|
||||
callBaseMethod<Tachyon.GetOutboundLinkStates>(
|
||||
Tachyon.AvailableMethods.GET_OUTBOUND_LINK_STATES,
|
||||
[section],
|
||||
),
|
||||
getOutboundMetadata: async (section: string) =>
|
||||
callBaseMethod<Forkop.GetOutboundMetadata>(
|
||||
Forkop.AvailableMethods.GET_OUTBOUND_METADATA,
|
||||
callBaseMethod<Tachyon.GetOutboundMetadata>(
|
||||
Tachyon.AvailableMethods.GET_OUTBOUND_METADATA,
|
||||
[section],
|
||||
),
|
||||
getSubscriptionMetadata: async (section: string) =>
|
||||
callBaseMethod<Forkop.SubscriptionMetadata | Forkop.SubscriptionMetadata[]>(
|
||||
Forkop.AvailableMethods.GET_SUBSCRIPTION_METADATA,
|
||||
callBaseMethod<Tachyon.SubscriptionMetadata | Tachyon.SubscriptionMetadata[]>(
|
||||
Tachyon.AvailableMethods.GET_SUBSCRIPTION_METADATA,
|
||||
[section],
|
||||
),
|
||||
checkSingBox: async () =>
|
||||
callBaseMethod<Forkop.SingBoxCheckResult>(
|
||||
Forkop.AvailableMethods.CHECK_SING_BOX,
|
||||
callBaseMethod<Tachyon.SingBoxCheckResult>(
|
||||
Tachyon.AvailableMethods.CHECK_SING_BOX,
|
||||
),
|
||||
checkInbounds: async () =>
|
||||
callBaseMethod<Forkop.InboundsCheckResult>(
|
||||
Forkop.AvailableMethods.CHECK_INBOUNDS,
|
||||
callBaseMethod<Tachyon.InboundsCheckResult>(
|
||||
Tachyon.AvailableMethods.CHECK_INBOUNDS,
|
||||
),
|
||||
getSingBoxStatus: async () =>
|
||||
callBaseMethod<Forkop.GetSingBoxStatus>(
|
||||
Forkop.AvailableMethods.GET_SING_BOX_STATUS,
|
||||
callBaseMethod<Tachyon.GetSingBoxStatus>(
|
||||
Tachyon.AvailableMethods.GET_SING_BOX_STATUS,
|
||||
),
|
||||
getZapretStatus: async () =>
|
||||
callBaseMethod<Forkop.GetZapretStatus>(
|
||||
Forkop.AvailableMethods.GET_ZAPRET_STATUS,
|
||||
callBaseMethod<Tachyon.GetZapretStatus>(
|
||||
Tachyon.AvailableMethods.GET_ZAPRET_STATUS,
|
||||
),
|
||||
getZapret2Status: async () =>
|
||||
callBaseMethod<Forkop.GetZapret2Status>(
|
||||
Forkop.AvailableMethods.GET_ZAPRET2_STATUS,
|
||||
callBaseMethod<Tachyon.GetZapret2Status>(
|
||||
Tachyon.AvailableMethods.GET_ZAPRET2_STATUS,
|
||||
),
|
||||
getByedpiStatus: async () =>
|
||||
callBaseMethod<Forkop.GetByedpiStatus>(
|
||||
Forkop.AvailableMethods.GET_BYEDPI_STATUS,
|
||||
callBaseMethod<Tachyon.GetByedpiStatus>(
|
||||
Tachyon.AvailableMethods.GET_BYEDPI_STATUS,
|
||||
),
|
||||
getClashApiProxies: async () =>
|
||||
callBaseMethod<ClashAPI.Proxies>(Forkop.AvailableMethods.CLASH_API, [
|
||||
Forkop.AvailableClashAPIMethods.GET_PROXIES,
|
||||
callBaseMethod<ClashAPI.Proxies>(Tachyon.AvailableMethods.CLASH_API, [
|
||||
Tachyon.AvailableClashAPIMethods.GET_PROXIES,
|
||||
]),
|
||||
getClashApiConnections: async () =>
|
||||
callBaseMethod<unknown>(Forkop.AvailableMethods.CLASH_API, [
|
||||
Forkop.AvailableClashAPIMethods.GET_CONNECTIONS,
|
||||
callBaseMethod<unknown>(Tachyon.AvailableMethods.CLASH_API, [
|
||||
Tachyon.AvailableClashAPIMethods.GET_CONNECTIONS,
|
||||
]),
|
||||
getClashApiProxyLatency: async (tag: string, timeout = '5000') =>
|
||||
callBaseMethod<Forkop.GetClashApiProxyLatency>(
|
||||
Forkop.AvailableMethods.CLASH_API,
|
||||
[Forkop.AvailableClashAPIMethods.GET_PROXY_LATENCY, tag, timeout],
|
||||
callBaseMethod<Tachyon.GetClashApiProxyLatency>(
|
||||
Tachyon.AvailableMethods.CLASH_API,
|
||||
[Tachyon.AvailableClashAPIMethods.GET_PROXY_LATENCY, tag, timeout],
|
||||
),
|
||||
getClashApiProxyLatencies: async (tags: string[]) =>
|
||||
callBaseMethod<Forkop.GetClashApiProxyLatencies>(
|
||||
Forkop.AvailableMethods.CLASH_API,
|
||||
callBaseMethod<Tachyon.GetClashApiProxyLatencies>(
|
||||
Tachyon.AvailableMethods.CLASH_API,
|
||||
[
|
||||
Forkop.AvailableClashAPIMethods.GET_PROXY_LATENCIES,
|
||||
Tachyon.AvailableClashAPIMethods.GET_PROXY_LATENCIES,
|
||||
JSON.stringify(tags),
|
||||
'5000',
|
||||
],
|
||||
),
|
||||
getClashApiGroupLatency: async (tag: string) =>
|
||||
callBaseMethod<Forkop.GetClashApiGroupLatency>(
|
||||
Forkop.AvailableMethods.CLASH_API,
|
||||
[Forkop.AvailableClashAPIMethods.GET_GROUP_LATENCY, tag, '10000'],
|
||||
callBaseMethod<Tachyon.GetClashApiGroupLatency>(
|
||||
Tachyon.AvailableMethods.CLASH_API,
|
||||
[Tachyon.AvailableClashAPIMethods.GET_GROUP_LATENCY, tag, '10000'],
|
||||
),
|
||||
setClashApiGroupProxy: async (group: string, proxy: string) =>
|
||||
callBaseMethod<unknown>(Forkop.AvailableMethods.CLASH_API, [
|
||||
Forkop.AvailableClashAPIMethods.SET_GROUP_PROXY,
|
||||
callBaseMethod<unknown>(Tachyon.AvailableMethods.CLASH_API, [
|
||||
Tachyon.AvailableClashAPIMethods.SET_GROUP_PROXY,
|
||||
group,
|
||||
proxy,
|
||||
]),
|
||||
closeClashApiConnection: async (connectionId: string) =>
|
||||
callBaseMethod<unknown>(Forkop.AvailableMethods.CLASH_API, [
|
||||
Forkop.AvailableClashAPIMethods.CLOSE_CONNECTION,
|
||||
callBaseMethod<unknown>(Tachyon.AvailableMethods.CLASH_API, [
|
||||
Tachyon.AvailableClashAPIMethods.CLOSE_CONNECTION,
|
||||
connectionId,
|
||||
]),
|
||||
closeAllClashApiConnections: async () =>
|
||||
callBaseMethod<unknown>(Forkop.AvailableMethods.CLASH_API, [
|
||||
Forkop.AvailableClashAPIMethods.CLOSE_ALL_CONNECTIONS,
|
||||
callBaseMethod<unknown>(Tachyon.AvailableMethods.CLASH_API, [
|
||||
Tachyon.AvailableClashAPIMethods.CLOSE_ALL_CONNECTIONS,
|
||||
]),
|
||||
enable: async () =>
|
||||
callBaseMethod<unknown>(
|
||||
Forkop.AvailableMethods.ENABLE,
|
||||
Tachyon.AvailableMethods.ENABLE,
|
||||
[],
|
||||
'/etc/init.d/forkop',
|
||||
'/etc/init.d/tachyon',
|
||||
),
|
||||
disable: async () =>
|
||||
callBaseMethod<unknown>(
|
||||
Forkop.AvailableMethods.DISABLE,
|
||||
Tachyon.AvailableMethods.DISABLE,
|
||||
[],
|
||||
'/etc/init.d/forkop',
|
||||
'/etc/init.d/tachyon',
|
||||
),
|
||||
globalCheck: async (masked = true) =>
|
||||
callBaseMethod<unknown>(Forkop.AvailableMethods.GLOBAL_CHECK, [
|
||||
callBaseMethod<unknown>(Tachyon.AvailableMethods.GLOBAL_CHECK, [
|
||||
masked ? 'masked' : 'raw',
|
||||
]),
|
||||
showSingBoxConfig: async (masked = true) =>
|
||||
callBaseMethod<unknown>(Forkop.AvailableMethods.SHOW_SING_BOX_CONFIG, [
|
||||
callBaseMethod<unknown>(Tachyon.AvailableMethods.SHOW_SING_BOX_CONFIG, [
|
||||
masked ? 'masked' : 'raw',
|
||||
]),
|
||||
checkLogs: async () =>
|
||||
callBaseMethod<unknown>(Forkop.AvailableMethods.CHECK_LOGS),
|
||||
callBaseMethod<unknown>(Tachyon.AvailableMethods.CHECK_LOGS),
|
||||
checkSingBoxLogs: async () =>
|
||||
callBaseMethod<unknown>(Forkop.AvailableMethods.CHECK_SING_BOX_LOGS),
|
||||
callBaseMethod<unknown>(Tachyon.AvailableMethods.CHECK_SING_BOX_LOGS),
|
||||
getSystemInfo: async () =>
|
||||
callBaseMethod<Forkop.GetSystemInfo>(
|
||||
Forkop.AvailableMethods.GET_SYSTEM_INFO,
|
||||
callBaseMethod<Tachyon.GetSystemInfo>(
|
||||
Tachyon.AvailableMethods.GET_SYSTEM_INFO,
|
||||
),
|
||||
getServerCapabilities: async () =>
|
||||
callBaseMethod<Forkop.GetServerCapabilities>(
|
||||
Forkop.AvailableMethods.GET_SERVER_CAPABILITIES,
|
||||
callBaseMethod<Tachyon.GetServerCapabilities>(
|
||||
Tachyon.AvailableMethods.GET_SERVER_CAPABILITIES,
|
||||
),
|
||||
getUiCapabilities: async () =>
|
||||
callBaseMethod<Forkop.GetUiCapabilities>(
|
||||
Forkop.AvailableMethods.GET_UI_CAPABILITIES,
|
||||
callBaseMethod<Tachyon.GetUiCapabilities>(
|
||||
Tachyon.AvailableMethods.GET_UI_CAPABILITIES,
|
||||
),
|
||||
getUiState: async () =>
|
||||
callBaseMethod<Forkop.UiState>(
|
||||
Forkop.AvailableMethods.GET_UI_STATE,
|
||||
callBaseMethod<Tachyon.UiState>(
|
||||
Tachyon.AvailableMethods.GET_UI_STATE,
|
||||
[],
|
||||
'/usr/bin/forkop',
|
||||
'/usr/bin/tachyon',
|
||||
{ timeout: GET_UI_STATE_RPC_TIMEOUT_MS },
|
||||
),
|
||||
serviceActionStart: async (action: Forkop.ServiceAction) => {
|
||||
serviceActionStart: async (action: Tachyon.ServiceAction) => {
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/forkop',
|
||||
args: [Forkop.AvailableMethods.SERVICE_ACTION_ASYNC, action],
|
||||
command: '/usr/bin/tachyon',
|
||||
args: [Tachyon.AvailableMethods.SERVICE_ACTION_ASYNC, action],
|
||||
timeout: UI_ACTION_RPC_TIMEOUT_MS,
|
||||
});
|
||||
const parsedResponse = parseUiActionStartResult(response);
|
||||
@@ -387,12 +387,12 @@ export const ForkopShellMethods = {
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Forkop.MethodSuccessResponse<Forkop.UiActionStartResult>;
|
||||
} as Tachyon.MethodSuccessResponse<Tachyon.UiActionStartResult>;
|
||||
},
|
||||
serviceActionStatus: async (jobId: string) => {
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/forkop',
|
||||
args: [Forkop.AvailableMethods.SERVICE_ACTION_STATUS, jobId],
|
||||
command: '/usr/bin/tachyon',
|
||||
args: [Tachyon.AvailableMethods.SERVICE_ACTION_STATUS, jobId],
|
||||
timeout: UI_ACTION_RPC_TIMEOUT_MS,
|
||||
});
|
||||
const parsedResponse = parseServiceActionState(response);
|
||||
@@ -408,13 +408,13 @@ export const ForkopShellMethods = {
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Forkop.MethodSuccessResponse<Forkop.ServiceActionState>;
|
||||
} as Tachyon.MethodSuccessResponse<Tachyon.ServiceActionState>;
|
||||
},
|
||||
waitServiceActionJob: async (jobId: string, startedAt = Date.now()) => {
|
||||
while (Date.now() - startedAt < SERVICE_ACTION_TIMEOUT_MS) {
|
||||
await sleep(SERVICE_ACTION_POLL_INTERVAL_MS);
|
||||
|
||||
const response = await ForkopShellMethods.serviceActionStatus(jobId);
|
||||
const response = await TachyonShellMethods.serviceActionStatus(jobId);
|
||||
|
||||
if (!response.success) {
|
||||
return response;
|
||||
@@ -430,18 +430,18 @@ export const ForkopShellMethods = {
|
||||
return {
|
||||
success: false,
|
||||
error: _('Operation timed out'),
|
||||
} as Forkop.MethodFailureResponse;
|
||||
} as Tachyon.MethodFailureResponse;
|
||||
},
|
||||
latencyTestStart: async (
|
||||
latencyType: Forkop.LatencyActionState['latency_type'],
|
||||
latencyType: Tachyon.LatencyActionState['latency_type'],
|
||||
section: string,
|
||||
tag: string,
|
||||
timeout?: string,
|
||||
) => {
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/forkop',
|
||||
command: '/usr/bin/tachyon',
|
||||
args: [
|
||||
Forkop.AvailableMethods.LATENCY_TEST_ASYNC,
|
||||
Tachyon.AvailableMethods.LATENCY_TEST_ASYNC,
|
||||
latencyType,
|
||||
section,
|
||||
tag,
|
||||
@@ -466,12 +466,12 @@ export const ForkopShellMethods = {
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Forkop.MethodSuccessResponse<Forkop.UiActionStartResult>;
|
||||
} as Tachyon.MethodSuccessResponse<Tachyon.UiActionStartResult>;
|
||||
},
|
||||
latencyTestStatus: async (jobId: string) => {
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/forkop',
|
||||
args: [Forkop.AvailableMethods.LATENCY_TEST_STATUS, jobId],
|
||||
command: '/usr/bin/tachyon',
|
||||
args: [Tachyon.AvailableMethods.LATENCY_TEST_STATUS, jobId],
|
||||
timeout: UI_ACTION_RPC_TIMEOUT_MS,
|
||||
});
|
||||
const parsedResponse = parseLatencyActionState(response);
|
||||
@@ -487,7 +487,7 @@ export const ForkopShellMethods = {
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Forkop.MethodSuccessResponse<Forkop.LatencyActionState>;
|
||||
} as Tachyon.MethodSuccessResponse<Tachyon.LatencyActionState>;
|
||||
},
|
||||
waitLatencyTestJob: async (jobId: string, startedAt = Date.now()) => {
|
||||
const transientRpc = createTransientRpcGraceTracker(
|
||||
@@ -497,7 +497,7 @@ export const ForkopShellMethods = {
|
||||
while (Date.now() - startedAt < LATENCY_TEST_TIMEOUT_MS) {
|
||||
await sleep(LATENCY_TEST_POLL_INTERVAL_MS);
|
||||
|
||||
const response = await ForkopShellMethods.latencyTestStatus(jobId);
|
||||
const response = await TachyonShellMethods.latencyTestStatus(jobId);
|
||||
|
||||
if (!response.success) {
|
||||
if (transientRpc.shouldContinue(response.error)) {
|
||||
@@ -518,15 +518,15 @@ export const ForkopShellMethods = {
|
||||
return {
|
||||
success: false,
|
||||
error: _('Operation timed out'),
|
||||
} as Forkop.MethodFailureResponse;
|
||||
} as Tachyon.MethodFailureResponse;
|
||||
},
|
||||
uiActionAck: async (
|
||||
kind: 'service' | 'latency' | 'component' | 'subscription',
|
||||
jobId: string,
|
||||
) => {
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/forkop',
|
||||
args: [Forkop.AvailableMethods.UI_ACTION_ACK, kind, jobId],
|
||||
command: '/usr/bin/tachyon',
|
||||
args: [Tachyon.AvailableMethods.UI_ACTION_ACK, kind, jobId],
|
||||
timeout: UI_ACTION_RPC_TIMEOUT_MS,
|
||||
});
|
||||
const parsedResponse = parseUiActionStartResult(response);
|
||||
@@ -538,15 +538,15 @@ export const ForkopShellMethods = {
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Forkop.MethodSuccessResponse<Forkop.UiActionStartResult>;
|
||||
} as Tachyon.MethodSuccessResponse<Tachyon.UiActionStartResult>;
|
||||
},
|
||||
componentActionStart: async (
|
||||
component: Forkop.ComponentName,
|
||||
action: Forkop.ComponentAction,
|
||||
component: Tachyon.ComponentName,
|
||||
action: Tachyon.ComponentAction,
|
||||
) => {
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/forkop',
|
||||
args: [Forkop.AvailableMethods.COMPONENT_ACTION_ASYNC, component, action],
|
||||
command: '/usr/bin/tachyon',
|
||||
args: [Tachyon.AvailableMethods.COMPONENT_ACTION_ASYNC, component, action],
|
||||
timeout: COMPONENT_ACTION_RPC_TIMEOUT_MS,
|
||||
});
|
||||
const parsedResponse = parseComponentActionStartResult(response);
|
||||
@@ -562,12 +562,12 @@ export const ForkopShellMethods = {
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Forkop.MethodSuccessResponse<Forkop.ComponentActionStartResult>;
|
||||
} as Tachyon.MethodSuccessResponse<Tachyon.ComponentActionStartResult>;
|
||||
},
|
||||
componentActionStatus: async (jobId: string) => {
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/forkop',
|
||||
args: [Forkop.AvailableMethods.COMPONENT_ACTION_STATUS, jobId],
|
||||
command: '/usr/bin/tachyon',
|
||||
args: [Tachyon.AvailableMethods.COMPONENT_ACTION_STATUS, jobId],
|
||||
timeout: COMPONENT_ACTION_RPC_TIMEOUT_MS,
|
||||
});
|
||||
const parsedResponse = parseComponentActionResult(response);
|
||||
@@ -579,16 +579,16 @@ export const ForkopShellMethods = {
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Forkop.MethodSuccessResponse<Forkop.ComponentActionResult>;
|
||||
} as Tachyon.MethodSuccessResponse<Tachyon.ComponentActionResult>;
|
||||
},
|
||||
componentUpdateCheckCache: async () =>
|
||||
callBaseMethod<Forkop.ComponentUpdateCheckCache>(
|
||||
Forkop.AvailableMethods.COMPONENT_UPDATE_CHECK_CACHE,
|
||||
callBaseMethod<Tachyon.ComponentUpdateCheckCache>(
|
||||
Tachyon.AvailableMethods.COMPONENT_UPDATE_CHECK_CACHE,
|
||||
),
|
||||
waitComponentActionJob: async (
|
||||
jobId: string,
|
||||
component: Forkop.ComponentName,
|
||||
action: Forkop.ComponentAction,
|
||||
component: Tachyon.ComponentName,
|
||||
action: Tachyon.ComponentAction,
|
||||
expectedLatestVersion?: string,
|
||||
) => {
|
||||
let selfUpdateVersionMatchedAt = 0;
|
||||
@@ -608,7 +608,7 @@ export const ForkopShellMethods = {
|
||||
return {
|
||||
success: true,
|
||||
data: stateResponse,
|
||||
} as Forkop.MethodSuccessResponse<Forkop.ComponentActionResult>;
|
||||
} as Tachyon.MethodSuccessResponse<Tachyon.ComponentActionResult>;
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -621,8 +621,8 @@ export const ForkopShellMethods = {
|
||||
|
||||
lastStatusRefreshAt = Date.now();
|
||||
const statusResponse = await executeShellCommand({
|
||||
command: '/usr/bin/forkop',
|
||||
args: [Forkop.AvailableMethods.COMPONENT_ACTION_STATUS, jobId],
|
||||
command: '/usr/bin/tachyon',
|
||||
args: [Tachyon.AvailableMethods.COMPONENT_ACTION_STATUS, jobId],
|
||||
timeout: COMPONENT_ACTION_RPC_TIMEOUT_MS,
|
||||
});
|
||||
const parsedResponse = parseComponentActionResult(statusResponse);
|
||||
@@ -644,9 +644,9 @@ export const ForkopShellMethods = {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (component === 'forkop' && action === 'install') {
|
||||
if (component === 'tachyon' && action === 'install') {
|
||||
const installedVersion = expectedLatestVersion
|
||||
? await readForkopVersion()
|
||||
? await readTachyonVersion()
|
||||
: '';
|
||||
|
||||
if (
|
||||
@@ -667,13 +667,13 @@ export const ForkopShellMethods = {
|
||||
success: true,
|
||||
component,
|
||||
action,
|
||||
message: translate('Forkop has been installed'),
|
||||
message: translate('Tachyon has been installed'),
|
||||
current_version: installedVersion,
|
||||
latest_version: expectedLatestVersion,
|
||||
changed: true,
|
||||
status: 'latest',
|
||||
},
|
||||
} as Forkop.MethodSuccessResponse<Forkop.ComponentActionResult>;
|
||||
} as Tachyon.MethodSuccessResponse<Tachyon.ComponentActionResult>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -691,17 +691,17 @@ export const ForkopShellMethods = {
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Forkop.MethodSuccessResponse<Forkop.ComponentActionResult>;
|
||||
} as Tachyon.MethodSuccessResponse<Tachyon.ComponentActionResult>;
|
||||
}
|
||||
},
|
||||
subscriptionUpdateStart: async (section?: string, sourceIndex?: number) => {
|
||||
const startArgs = [
|
||||
Forkop.AvailableMethods.SUBSCRIPTION_UPDATE_ASYNC,
|
||||
Tachyon.AvailableMethods.SUBSCRIPTION_UPDATE_ASYNC,
|
||||
...(section ? [section] : []),
|
||||
...(section && sourceIndex !== undefined ? [String(sourceIndex)] : []),
|
||||
];
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/forkop',
|
||||
command: '/usr/bin/tachyon',
|
||||
args: startArgs,
|
||||
timeout: SUBSCRIPTION_UPDATE_RPC_TIMEOUT_MS,
|
||||
});
|
||||
@@ -718,18 +718,18 @@ export const ForkopShellMethods = {
|
||||
parsedResponse?.message ||
|
||||
response.stderr ||
|
||||
_('Subscription update failed'),
|
||||
} as Forkop.MethodFailureResponse;
|
||||
} as Tachyon.MethodFailureResponse;
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Forkop.MethodSuccessResponse<Forkop.SubscriptionUpdateStartResult>;
|
||||
} as Tachyon.MethodSuccessResponse<Tachyon.SubscriptionUpdateStartResult>;
|
||||
},
|
||||
subscriptionUpdateStatus: async (jobId: string) => {
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/forkop',
|
||||
args: [Forkop.AvailableMethods.SUBSCRIPTION_UPDATE_STATUS, jobId],
|
||||
command: '/usr/bin/tachyon',
|
||||
args: [Tachyon.AvailableMethods.SUBSCRIPTION_UPDATE_STATUS, jobId],
|
||||
timeout: SUBSCRIPTION_UPDATE_RPC_TIMEOUT_MS,
|
||||
});
|
||||
const parsedResponse = parseSubscriptionUpdateJobState(response);
|
||||
@@ -738,13 +738,13 @@ export const ForkopShellMethods = {
|
||||
return {
|
||||
success: false,
|
||||
error: response.stderr || _('Subscription update failed'),
|
||||
} as Forkop.MethodFailureResponse;
|
||||
} as Tachyon.MethodFailureResponse;
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Forkop.MethodSuccessResponse<Forkop.SubscriptionUpdateJobState>;
|
||||
} as Tachyon.MethodSuccessResponse<Tachyon.SubscriptionUpdateJobState>;
|
||||
},
|
||||
waitSubscriptionUpdateJob: async (jobId: string) => {
|
||||
const transientRpc = createTransientRpcGraceTracker(
|
||||
@@ -754,7 +754,7 @@ export const ForkopShellMethods = {
|
||||
while (true) {
|
||||
await sleep(SUBSCRIPTION_UPDATE_POLL_INTERVAL_MS);
|
||||
|
||||
const response = await ForkopShellMethods.subscriptionUpdateStatus(jobId);
|
||||
const response = await TachyonShellMethods.subscriptionUpdateStatus(jobId);
|
||||
|
||||
if (!response.success) {
|
||||
if (transientRpc.shouldContinue(response.error)) {
|
||||
|
||||
@@ -8,7 +8,7 @@ vi.mock('../../../../helpers', () => ({
|
||||
executeShellCommand: mocks.executeShellCommand,
|
||||
}));
|
||||
|
||||
import { Forkop } from '../../../types';
|
||||
import { Tachyon } from '../../../types';
|
||||
import { callBaseMethod } from '../callBaseMethod';
|
||||
|
||||
describe('callBaseMethod', () => {
|
||||
@@ -24,7 +24,7 @@ describe('callBaseMethod', () => {
|
||||
});
|
||||
|
||||
const response = await callBaseMethod(
|
||||
Forkop.AvailableMethods.CHECK_DNS_AVAILABLE,
|
||||
Tachyon.AvailableMethods.CHECK_DNS_AVAILABLE,
|
||||
);
|
||||
|
||||
expect(response).toEqual({
|
||||
@@ -41,9 +41,9 @@ describe('callBaseMethod', () => {
|
||||
});
|
||||
|
||||
const response = await callBaseMethod(
|
||||
Forkop.AvailableMethods.GLOBAL_CHECK,
|
||||
Tachyon.AvailableMethods.GLOBAL_CHECK,
|
||||
[],
|
||||
'/usr/bin/forkop',
|
||||
'/usr/bin/tachyon',
|
||||
{ allowNonZeroWithStdout: true },
|
||||
);
|
||||
|
||||
@@ -61,14 +61,14 @@ describe('callBaseMethod', () => {
|
||||
});
|
||||
|
||||
await callBaseMethod(
|
||||
Forkop.AvailableMethods.GLOBAL_CHECK,
|
||||
Tachyon.AvailableMethods.GLOBAL_CHECK,
|
||||
[],
|
||||
'/usr/bin/forkop',
|
||||
'/usr/bin/tachyon',
|
||||
{ timeout: 60000 },
|
||||
);
|
||||
|
||||
expect(mocks.executeShellCommand).toHaveBeenCalledWith({
|
||||
command: '/usr/bin/forkop',
|
||||
command: '/usr/bin/tachyon',
|
||||
args: ['global_check'],
|
||||
timeout: 60000,
|
||||
});
|
||||
|
||||
@@ -9,9 +9,9 @@ vi.mock('../../../../helpers', () => ({
|
||||
executeShellCommand: mocks.executeShellCommand,
|
||||
}));
|
||||
|
||||
import { ForkopShellMethods } from '../index';
|
||||
import { TachyonShellMethods } from '../index';
|
||||
|
||||
describe('ForkopShellMethods.componentAction', () => {
|
||||
describe('TachyonShellMethods.componentAction', () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
mocks.executeShellCommand.mockReset();
|
||||
@@ -26,7 +26,7 @@ describe('ForkopShellMethods.componentAction', () => {
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it('does not fail Forkop self-update when status polling disappears after package replacement', async () => {
|
||||
it('does not fail Tachyon self-update when status polling disappears after package replacement', async () => {
|
||||
mocks.fsRead.mockRejectedValue(new Error('Access denied'));
|
||||
mocks.executeShellCommand.mockImplementation(({ args }) => {
|
||||
if (args[0] === 'component_action_status') {
|
||||
@@ -52,9 +52,9 @@ describe('ForkopShellMethods.componentAction', () => {
|
||||
});
|
||||
});
|
||||
|
||||
const responsePromise = ForkopShellMethods.waitComponentActionJob(
|
||||
const responsePromise = TachyonShellMethods.waitComponentActionJob(
|
||||
'job-1',
|
||||
'forkop',
|
||||
'tachyon',
|
||||
'install',
|
||||
'0.7.17.11',
|
||||
);
|
||||
@@ -65,9 +65,9 @@ describe('ForkopShellMethods.componentAction', () => {
|
||||
success: true,
|
||||
data: {
|
||||
success: true,
|
||||
component: 'forkop',
|
||||
component: 'tachyon',
|
||||
action: 'install',
|
||||
message: 'Forkop has been installed',
|
||||
message: 'Tachyon has been installed',
|
||||
current_version: '0.7.17.11',
|
||||
latest_version: '0.7.17.11',
|
||||
changed: true,
|
||||
@@ -87,7 +87,7 @@ describe('ForkopShellMethods.componentAction', () => {
|
||||
});
|
||||
|
||||
await expect(
|
||||
ForkopShellMethods.componentActionStart('zapret', 'install'),
|
||||
TachyonShellMethods.componentActionStart('zapret', 'install'),
|
||||
).resolves.toEqual({
|
||||
success: false,
|
||||
error: 'Another component action is already running',
|
||||
@@ -147,7 +147,7 @@ describe('ForkopShellMethods.componentAction', () => {
|
||||
});
|
||||
});
|
||||
|
||||
const responsePromise = ForkopShellMethods.waitComponentActionJob(
|
||||
const responsePromise = TachyonShellMethods.waitComponentActionJob(
|
||||
'job-1',
|
||||
'sing_box',
|
||||
'check_update',
|
||||
@@ -201,7 +201,7 @@ describe('ForkopShellMethods.componentAction', () => {
|
||||
return Promise.resolve({
|
||||
stdout: JSON.stringify({
|
||||
service: {
|
||||
forkop: {
|
||||
tachyon: {
|
||||
running: 0,
|
||||
enabled: 1,
|
||||
status: 'stopped but enabled',
|
||||
@@ -251,7 +251,7 @@ describe('ForkopShellMethods.componentAction', () => {
|
||||
});
|
||||
});
|
||||
|
||||
const responsePromise = ForkopShellMethods.waitComponentActionJob(
|
||||
const responsePromise = TachyonShellMethods.waitComponentActionJob(
|
||||
'job-1',
|
||||
'sing_box',
|
||||
'install_extended',
|
||||
@@ -274,7 +274,7 @@ describe('ForkopShellMethods.componentAction', () => {
|
||||
},
|
||||
});
|
||||
expect(mocks.executeShellCommand).toHaveBeenCalledWith({
|
||||
command: '/usr/bin/forkop',
|
||||
command: '/usr/bin/tachyon',
|
||||
args: ['get_ui_state'],
|
||||
timeout: 3000,
|
||||
});
|
||||
@@ -321,7 +321,7 @@ describe('ForkopShellMethods.componentAction', () => {
|
||||
});
|
||||
});
|
||||
|
||||
const responsePromise = ForkopShellMethods.waitComponentActionJob(
|
||||
const responsePromise = TachyonShellMethods.waitComponentActionJob(
|
||||
'job-1',
|
||||
'zapret',
|
||||
'check_update',
|
||||
|
||||
@@ -8,9 +8,9 @@ vi.mock('../../../../helpers', () => ({
|
||||
executeShellCommand: mocks.executeShellCommand,
|
||||
}));
|
||||
|
||||
import { ForkopShellMethods } from '../index';
|
||||
import { TachyonShellMethods } from '../index';
|
||||
|
||||
describe('ForkopShellMethods.latencyAction', () => {
|
||||
describe('TachyonShellMethods.latencyAction', () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
mocks.executeShellCommand.mockReset();
|
||||
@@ -52,7 +52,7 @@ describe('ForkopShellMethods.latencyAction', () => {
|
||||
});
|
||||
});
|
||||
|
||||
const responsePromise = ForkopShellMethods.waitLatencyTestJob('job-1');
|
||||
const responsePromise = TachyonShellMethods.waitLatencyTestJob('job-1');
|
||||
|
||||
await vi.advanceTimersByTimeAsync(2000);
|
||||
|
||||
@@ -76,7 +76,7 @@ describe('ForkopShellMethods.latencyAction', () => {
|
||||
code: 0,
|
||||
});
|
||||
|
||||
await ForkopShellMethods.latencyTestStart(
|
||||
await TachyonShellMethods.latencyTestStart(
|
||||
'proxy',
|
||||
'AWG',
|
||||
'AWG-out',
|
||||
@@ -84,7 +84,7 @@ describe('ForkopShellMethods.latencyAction', () => {
|
||||
);
|
||||
|
||||
expect(mocks.executeShellCommand).toHaveBeenCalledWith({
|
||||
command: '/usr/bin/forkop',
|
||||
command: '/usr/bin/tachyon',
|
||||
args: ['latency_test_async', 'proxy', 'AWG', 'AWG-out', '10000'],
|
||||
timeout: 15000,
|
||||
});
|
||||
|
||||
@@ -8,9 +8,9 @@ vi.mock('../../../../helpers', () => ({
|
||||
executeShellCommand: mocks.executeShellCommand,
|
||||
}));
|
||||
|
||||
import { ForkopShellMethods } from '../index';
|
||||
import { TachyonShellMethods } from '../index';
|
||||
|
||||
describe('ForkopShellMethods.serviceAction', () => {
|
||||
describe('TachyonShellMethods.serviceAction', () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
mocks.executeShellCommand.mockReset();
|
||||
@@ -44,7 +44,7 @@ describe('ForkopShellMethods.serviceAction', () => {
|
||||
});
|
||||
});
|
||||
|
||||
const responsePromise = ForkopShellMethods.waitServiceActionJob('job-1');
|
||||
const responsePromise = TachyonShellMethods.waitServiceActionJob('job-1');
|
||||
|
||||
await vi.advanceTimersByTimeAsync(1000);
|
||||
|
||||
@@ -72,7 +72,7 @@ describe('ForkopShellMethods.serviceAction', () => {
|
||||
});
|
||||
|
||||
await expect(
|
||||
ForkopShellMethods.serviceActionStart('restart'),
|
||||
TachyonShellMethods.serviceActionStart('restart'),
|
||||
).resolves.toEqual({
|
||||
success: false,
|
||||
error: 'Another service action is already running',
|
||||
|
||||
@@ -8,9 +8,9 @@ vi.mock('../../../../helpers', () => ({
|
||||
executeShellCommand: mocks.executeShellCommand,
|
||||
}));
|
||||
|
||||
import { ForkopShellMethods } from '../index';
|
||||
import { TachyonShellMethods } from '../index';
|
||||
|
||||
describe('ForkopShellMethods.subscriptionUpdate', () => {
|
||||
describe('TachyonShellMethods.subscriptionUpdate', () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
mocks.executeShellCommand.mockReset();
|
||||
@@ -55,7 +55,7 @@ describe('ForkopShellMethods.subscriptionUpdate', () => {
|
||||
});
|
||||
|
||||
await expect(
|
||||
ForkopShellMethods.subscriptionUpdateStart('main'),
|
||||
TachyonShellMethods.subscriptionUpdateStart('main'),
|
||||
).resolves.toEqual({
|
||||
success: true,
|
||||
data: {
|
||||
@@ -66,7 +66,7 @@ describe('ForkopShellMethods.subscriptionUpdate', () => {
|
||||
});
|
||||
|
||||
const responsePromise =
|
||||
ForkopShellMethods.waitSubscriptionUpdateJob('job-1');
|
||||
TachyonShellMethods.waitSubscriptionUpdateJob('job-1');
|
||||
|
||||
await vi.advanceTimersByTimeAsync(1500);
|
||||
|
||||
@@ -80,12 +80,12 @@ describe('ForkopShellMethods.subscriptionUpdate', () => {
|
||||
},
|
||||
});
|
||||
expect(mocks.executeShellCommand).toHaveBeenNthCalledWith(1, {
|
||||
command: '/usr/bin/forkop',
|
||||
command: '/usr/bin/tachyon',
|
||||
args: ['subscription_update_async', 'main'],
|
||||
timeout: 15000,
|
||||
});
|
||||
expect(mocks.executeShellCommand).toHaveBeenNthCalledWith(2, {
|
||||
command: '/usr/bin/forkop',
|
||||
command: '/usr/bin/tachyon',
|
||||
args: ['subscription_update_status', 'job-1'],
|
||||
timeout: 15000,
|
||||
});
|
||||
@@ -102,7 +102,7 @@ describe('ForkopShellMethods.subscriptionUpdate', () => {
|
||||
});
|
||||
|
||||
await expect(
|
||||
ForkopShellMethods.subscriptionUpdateStart('main'),
|
||||
TachyonShellMethods.subscriptionUpdateStart('main'),
|
||||
).resolves.toEqual({
|
||||
success: false,
|
||||
error: 'Subscription update is already running',
|
||||
@@ -134,7 +134,7 @@ describe('ForkopShellMethods.subscriptionUpdate', () => {
|
||||
});
|
||||
|
||||
const responsePromise =
|
||||
ForkopShellMethods.waitSubscriptionUpdateJob('job-1');
|
||||
TachyonShellMethods.waitSubscriptionUpdateJob('job-1');
|
||||
|
||||
await vi.advanceTimersByTimeAsync(1500);
|
||||
|
||||
@@ -189,7 +189,7 @@ describe('ForkopShellMethods.subscriptionUpdate', () => {
|
||||
});
|
||||
|
||||
const responsePromise =
|
||||
ForkopShellMethods.waitSubscriptionUpdateJob('job-1');
|
||||
TachyonShellMethods.waitSubscriptionUpdateJob('job-1');
|
||||
|
||||
await vi.advanceTimersByTimeAsync(10 * 60 * 1000 + 3000);
|
||||
|
||||
@@ -239,7 +239,7 @@ describe('ForkopShellMethods.subscriptionUpdate', () => {
|
||||
});
|
||||
|
||||
const responsePromise =
|
||||
ForkopShellMethods.waitSubscriptionUpdateJob('job-1');
|
||||
TachyonShellMethods.waitSubscriptionUpdateJob('job-1');
|
||||
|
||||
await vi.advanceTimersByTimeAsync(3000);
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { TabServiceInstance } from './tab.service';
|
||||
import { store } from './store.service';
|
||||
import { logger } from './logger.service';
|
||||
import { ForkopLogWatcher } from './forkopLogWatcher.service';
|
||||
import { TachyonLogWatcher } from './tachyonLogWatcher.service';
|
||||
import {
|
||||
getForkopLogNotification,
|
||||
getTachyonLogNotification,
|
||||
LogNotificationDeduper,
|
||||
ForkopLogNotification,
|
||||
TachyonLogNotification,
|
||||
} from './logNotificationDeduper.service';
|
||||
import { ForkopShellMethods } from '../methods';
|
||||
import { TachyonShellMethods } from '../methods';
|
||||
import {
|
||||
registerRuntimeStateResumeRefresh,
|
||||
startRuntimeUiStatePolling,
|
||||
@@ -23,7 +23,7 @@ const LOG_WATCHER_START_DELAY_MS = 5000;
|
||||
|
||||
function componentDisplayName(component: string) {
|
||||
const names: Record<string, string> = {
|
||||
forkop: 'Forkop',
|
||||
tachyon: 'Tachyon',
|
||||
sing_box: 'sing-box',
|
||||
zapret: 'Zapret',
|
||||
zapret2: 'Zapret2',
|
||||
@@ -33,7 +33,7 @@ function componentDisplayName(component: string) {
|
||||
return names[component] || component;
|
||||
}
|
||||
|
||||
function showLogNotification(notification: ForkopLogNotification) {
|
||||
function showLogNotification(notification: TachyonLogNotification) {
|
||||
if (notification.kind === 'component-update') {
|
||||
const message = _('New version %s is available for %s')
|
||||
.replace('%s', notification.version)
|
||||
@@ -49,7 +49,7 @@ function showLogNotification(notification: ForkopLogNotification) {
|
||||
}
|
||||
|
||||
ui.addNotification(
|
||||
_('Forkop Error'),
|
||||
_('Tachyon Error'),
|
||||
E('div', {}, notification.line),
|
||||
'error',
|
||||
'fkp-log-error-notification',
|
||||
@@ -67,12 +67,12 @@ export function coreService(options: CoreServiceOptions = {}) {
|
||||
});
|
||||
});
|
||||
|
||||
const watcher = ForkopLogWatcher.getInstance();
|
||||
const watcher = TachyonLogWatcher.getInstance();
|
||||
const logNotificationDeduper = new LogNotificationDeduper();
|
||||
|
||||
watcher.init(
|
||||
async () => {
|
||||
const logs = await ForkopShellMethods.checkLogs();
|
||||
const logs = await TachyonShellMethods.checkLogs();
|
||||
|
||||
if (logs.success) {
|
||||
return logs.data as string;
|
||||
@@ -84,7 +84,7 @@ export function coreService(options: CoreServiceOptions = {}) {
|
||||
intervalMs: LOG_WATCHER_INTERVAL_MS,
|
||||
onNewLog: (line) => {
|
||||
if (logNotificationDeduper.shouldNotify(line)) {
|
||||
const notification = getForkopLogNotification(line);
|
||||
const notification = getTachyonLogNotification(line);
|
||||
if (notification) {
|
||||
showLogNotification(notification);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const LOG_NOTIFICATION_STORAGE_KEY = 'forkop:shown-log-error-notifications:v1';
|
||||
const LOG_NOTIFICATION_STORAGE_KEY = 'tachyon:shown-log-error-notifications:v1';
|
||||
const MAX_STORED_LOG_NOTIFICATIONS = 500;
|
||||
|
||||
export type ForkopLogNotification =
|
||||
export type TachyonLogNotification =
|
||||
| { kind: 'error'; line: string }
|
||||
| {
|
||||
kind: 'component-update';
|
||||
@@ -60,15 +60,15 @@ export function isErrorLogLine(line: string) {
|
||||
return lower.includes('[error]') || lower.includes('[fatal]');
|
||||
}
|
||||
|
||||
export function getForkopLogNotification(
|
||||
export function getTachyonLogNotification(
|
||||
line: string,
|
||||
): ForkopLogNotification | null {
|
||||
): TachyonLogNotification | null {
|
||||
if (isErrorLogLine(line)) {
|
||||
return { kind: 'error', line };
|
||||
}
|
||||
|
||||
const update = line.match(
|
||||
/\[component-update\]\s+(forkop|sing_box|zapret|zapret2|byedpi)\s+(\S+)/i,
|
||||
/\[component-update\]\s+(tachyon|sing_box|zapret|zapret2|byedpi)\s+(\S+)/i,
|
||||
);
|
||||
|
||||
if (!update) {
|
||||
@@ -97,7 +97,7 @@ export class LogNotificationDeduper {
|
||||
}
|
||||
|
||||
shouldNotify(line: string) {
|
||||
if (!getForkopLogNotification(line)) {
|
||||
if (!getTachyonLogNotification(line)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { ForkopShellMethods } from '../methods';
|
||||
import { Forkop } from '../types';
|
||||
import { TachyonShellMethods } from '../methods';
|
||||
import { Tachyon } from '../types';
|
||||
import { logger } from './logger.service';
|
||||
import { applyUiStateToStore } from './uiState.service';
|
||||
|
||||
const RUNTIME_UI_STATE_REFRESH_MIN_INTERVAL_MS = 500;
|
||||
const RUNTIME_UI_STATE_IDLE_POLL_INTERVAL_MS = 1000;
|
||||
const RUNTIME_UI_STATE_ACTIVE_POLL_INTERVAL_MS = 500;
|
||||
type RuntimeUiStateListener = (uiState: Forkop.UiState) => void;
|
||||
type RuntimeUiStateListener = (uiState: Tachyon.UiState) => void;
|
||||
|
||||
let runtimeUiStateRefreshPromise: Promise<Forkop.UiState | undefined> | null =
|
||||
let runtimeUiStateRefreshPromise: Promise<Tachyon.UiState | undefined> | null =
|
||||
null;
|
||||
let lastRuntimeUiStateRefreshAt = 0;
|
||||
let lastRuntimeUiState: Forkop.UiState | undefined;
|
||||
let lastRuntimeUiState: Tachyon.UiState | undefined;
|
||||
let runtimeStateResumeRefreshRegistered = false;
|
||||
let runtimeStatePollTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
let runtimeStatePollingStarted = false;
|
||||
@@ -26,7 +26,7 @@ function isDocumentVisible() {
|
||||
);
|
||||
}
|
||||
|
||||
function hasRunningAction(uiState: Forkop.UiState) {
|
||||
function hasRunningAction(uiState: Tachyon.UiState) {
|
||||
return Object.values(uiState.actions).some((actions) =>
|
||||
actions.some((action) => action.running),
|
||||
);
|
||||
@@ -57,7 +57,7 @@ function scheduleRuntimeUiStatePoll(delay = getNextPollDelay()) {
|
||||
}, delay);
|
||||
}
|
||||
|
||||
function notifyRuntimeUiStateListeners(uiState: Forkop.UiState) {
|
||||
function notifyRuntimeUiStateListeners(uiState: Tachyon.UiState) {
|
||||
for (const listener of runtimeUiStateListeners) {
|
||||
try {
|
||||
listener(uiState);
|
||||
@@ -69,7 +69,7 @@ function notifyRuntimeUiStateListeners(uiState: Forkop.UiState) {
|
||||
|
||||
export async function refreshRuntimeUiState({
|
||||
force = false,
|
||||
}: { force?: boolean } = {}): Promise<Forkop.UiState | undefined> {
|
||||
}: { force?: boolean } = {}): Promise<Tachyon.UiState | undefined> {
|
||||
if (!isDocumentVisible()) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -88,7 +88,7 @@ export async function refreshRuntimeUiState({
|
||||
|
||||
lastRuntimeUiStateRefreshAt = now;
|
||||
|
||||
const promise = ForkopShellMethods.getUiState()
|
||||
const promise = TachyonShellMethods.getUiState()
|
||||
.then((response) => {
|
||||
if (!response.success) {
|
||||
return undefined;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Forkop } from '../types';
|
||||
import { Tachyon } from '../types';
|
||||
import { initialDiagnosticStore } from '../tabs/diagnostic/diagnostic.store';
|
||||
|
||||
function jsonStableStringify<T, V>(obj: T): string {
|
||||
@@ -158,17 +158,17 @@ export interface StoreType {
|
||||
failed: boolean;
|
||||
data: {
|
||||
singbox: number;
|
||||
forkopRunning: number;
|
||||
forkopEnabled: number;
|
||||
forkopStatus: string;
|
||||
tachyonRunning: number;
|
||||
tachyonEnabled: number;
|
||||
tachyonStatus: string;
|
||||
};
|
||||
};
|
||||
sectionsWidget: {
|
||||
loading: boolean;
|
||||
failed: boolean;
|
||||
data: Forkop.OutboundGroup[];
|
||||
data: Tachyon.OutboundGroup[];
|
||||
latencyFetchingSections: Record<string, boolean>;
|
||||
latencyProgressSections: Record<string, Forkop.LatencyActionProgress>;
|
||||
latencyProgressSections: Record<string, Tachyon.LatencyActionProgress>;
|
||||
selectorSwitchingSections: Record<string, string>;
|
||||
subscriptionUpdatingSections: Record<string, boolean>;
|
||||
};
|
||||
@@ -190,8 +190,8 @@ export interface StoreType {
|
||||
loading: boolean;
|
||||
loaded: boolean;
|
||||
providerInfoLoaded: boolean;
|
||||
forkop_version: string;
|
||||
forkop_latest_version: string;
|
||||
tachyon_version: string;
|
||||
tachyon_latest_version: string;
|
||||
luci_app_version: string;
|
||||
sing_box_version: string;
|
||||
sing_box_extended: number;
|
||||
@@ -209,8 +209,8 @@ export interface StoreType {
|
||||
device_model: string;
|
||||
};
|
||||
updatesActions: {
|
||||
forkopCheck: { loading: boolean };
|
||||
forkopInstall: { loading: boolean };
|
||||
tachyonCheck: { loading: boolean };
|
||||
tachyonInstall: { loading: boolean };
|
||||
singBoxCheck: { loading: boolean };
|
||||
singBoxInstall: { loading: boolean };
|
||||
singBoxInstallExtended: { loading: boolean };
|
||||
@@ -228,7 +228,7 @@ export interface StoreType {
|
||||
byedpiRemove: { loading: boolean };
|
||||
};
|
||||
updatesChecks: Record<
|
||||
Forkop.ComponentName,
|
||||
Tachyon.ComponentName,
|
||||
{
|
||||
status: 'latest' | 'outdated' | 'dev' | null;
|
||||
latest_version: string;
|
||||
@@ -262,9 +262,9 @@ const initialStore: StoreType = {
|
||||
failed: false,
|
||||
data: {
|
||||
singbox: 0,
|
||||
forkopRunning: 0,
|
||||
forkopEnabled: 0,
|
||||
forkopStatus: '',
|
||||
tachyonRunning: 0,
|
||||
tachyonEnabled: 0,
|
||||
tachyonStatus: '',
|
||||
},
|
||||
},
|
||||
sectionsWidget: {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ForkopShellMethods } from '../methods';
|
||||
import { TachyonShellMethods } from '../methods';
|
||||
import { normalizeSingBoxVariantFields } from '../helpers/singBoxVariant';
|
||||
import { logger } from './logger.service';
|
||||
import { store, StoreType } from './store.service';
|
||||
@@ -7,8 +7,8 @@ const UNKNOWN_SYSTEM_INFO: StoreType['diagnosticsSystemInfo'] = {
|
||||
loading: false,
|
||||
loaded: false,
|
||||
providerInfoLoaded: false,
|
||||
forkop_version: _('unknown'),
|
||||
forkop_latest_version: _('unknown'),
|
||||
tachyon_version: _('unknown'),
|
||||
tachyon_latest_version: _('unknown'),
|
||||
luci_app_version: _('unknown'),
|
||||
sing_box_version: _('unknown'),
|
||||
sing_box_extended: 0,
|
||||
@@ -65,7 +65,7 @@ export async function ensureSystemInfo({
|
||||
|
||||
const promise = (async () => {
|
||||
try {
|
||||
const systemInfo = await ForkopShellMethods.getSystemInfo();
|
||||
const systemInfo = await TachyonShellMethods.getSystemInfo();
|
||||
|
||||
if (requestId !== latestSystemInfoRequestId) {
|
||||
return store.get().diagnosticsSystemInfo;
|
||||
|
||||
@@ -2,14 +2,14 @@ import { logger } from './logger.service';
|
||||
|
||||
type LogFetcher = () => Promise<string> | string;
|
||||
|
||||
interface ForkopLogWatcherOptions {
|
||||
interface TachyonLogWatcherOptions {
|
||||
intervalMs?: number;
|
||||
onNewLog?: (line: string) => void;
|
||||
maxTrackedLines?: number;
|
||||
}
|
||||
|
||||
export class ForkopLogWatcher {
|
||||
private static instance: ForkopLogWatcher;
|
||||
export class TachyonLogWatcher {
|
||||
private static instance: TachyonLogWatcher;
|
||||
private fetcher?: LogFetcher;
|
||||
private onNewLog?: (line: string) => void;
|
||||
private intervalMs = 5000;
|
||||
@@ -29,21 +29,21 @@ export class ForkopLogWatcher {
|
||||
}
|
||||
}
|
||||
|
||||
static getInstance(): ForkopLogWatcher {
|
||||
if (!ForkopLogWatcher.instance) {
|
||||
ForkopLogWatcher.instance = new ForkopLogWatcher();
|
||||
static getInstance(): TachyonLogWatcher {
|
||||
if (!TachyonLogWatcher.instance) {
|
||||
TachyonLogWatcher.instance = new TachyonLogWatcher();
|
||||
}
|
||||
return ForkopLogWatcher.instance;
|
||||
return TachyonLogWatcher.instance;
|
||||
}
|
||||
|
||||
init(fetcher: LogFetcher, options?: ForkopLogWatcherOptions): void {
|
||||
init(fetcher: LogFetcher, options?: TachyonLogWatcherOptions): void {
|
||||
this.fetcher = fetcher;
|
||||
this.onNewLog = options?.onNewLog;
|
||||
this.intervalMs = options?.intervalMs ?? 5000;
|
||||
this.maxTrackedLines = options?.maxTrackedLines ?? 500;
|
||||
this.lastLines = new Set();
|
||||
logger.info(
|
||||
'[ForkopLogWatcher]',
|
||||
'[TachyonLogWatcher]',
|
||||
`initialized (interval: ${this.intervalMs}ms)`,
|
||||
);
|
||||
}
|
||||
@@ -54,18 +54,18 @@ export class ForkopLogWatcher {
|
||||
|
||||
async checkOnce(): Promise<void> {
|
||||
if (!this.fetcher) {
|
||||
logger.warn('[ForkopLogWatcher]', 'fetcher not found');
|
||||
logger.warn('[TachyonLogWatcher]', 'fetcher not found');
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.paused) {
|
||||
logger.debug('[ForkopLogWatcher]', 'skipped check — tab not visible');
|
||||
logger.debug('[TachyonLogWatcher]', 'skipped check — tab not visible');
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.checking) {
|
||||
logger.debug(
|
||||
'[ForkopLogWatcher]',
|
||||
'[TachyonLogWatcher]',
|
||||
'skipped check — previous check is running',
|
||||
);
|
||||
return;
|
||||
@@ -92,7 +92,7 @@ export class ForkopLogWatcher {
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error('[ForkopLogWatcher]', 'failed to read logs:', err);
|
||||
logger.error('[TachyonLogWatcher]', 'failed to read logs:', err);
|
||||
} finally {
|
||||
this.checking = false;
|
||||
}
|
||||
@@ -101,7 +101,7 @@ export class ForkopLogWatcher {
|
||||
start(): void {
|
||||
if (this.running) return;
|
||||
if (!this.fetcher) {
|
||||
logger.warn('[ForkopLogWatcher]', 'attempted to start without fetcher');
|
||||
logger.warn('[TachyonLogWatcher]', 'attempted to start without fetcher');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ export class ForkopLogWatcher {
|
||||
void this.checkOnce();
|
||||
this.timer = setInterval(() => this.checkOnce(), this.intervalMs);
|
||||
logger.info(
|
||||
'[ForkopLogWatcher]',
|
||||
'[TachyonLogWatcher]',
|
||||
`started (interval: ${this.intervalMs}ms)`,
|
||||
);
|
||||
}
|
||||
@@ -118,25 +118,25 @@ export class ForkopLogWatcher {
|
||||
if (!this.running) return;
|
||||
this.running = false;
|
||||
if (this.timer) clearInterval(this.timer);
|
||||
logger.info('[ForkopLogWatcher]', 'stopped');
|
||||
logger.info('[TachyonLogWatcher]', 'stopped');
|
||||
}
|
||||
|
||||
pause(): void {
|
||||
if (!this.running || this.paused) return;
|
||||
this.paused = true;
|
||||
logger.info('[ForkopLogWatcher]', 'paused (tab not visible)');
|
||||
logger.info('[TachyonLogWatcher]', 'paused (tab not visible)');
|
||||
}
|
||||
|
||||
resume(): void {
|
||||
if (!this.running || !this.paused) return;
|
||||
this.paused = false;
|
||||
logger.info('[ForkopLogWatcher]', 'resumed (tab active)');
|
||||
logger.info('[TachyonLogWatcher]', 'resumed (tab active)');
|
||||
void this.checkOnce();
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
this.lastLines = new Set();
|
||||
this.checking = false;
|
||||
logger.info('[ForkopLogWatcher]', 'log history reset');
|
||||
logger.info('[TachyonLogWatcher]', 'log history reset');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest';
|
||||
|
||||
import {
|
||||
getLogNotificationKey,
|
||||
getForkopLogNotification,
|
||||
getTachyonLogNotification,
|
||||
isErrorLogLine,
|
||||
LogNotificationDeduper,
|
||||
} from '../logNotificationDeduper.service';
|
||||
@@ -37,44 +37,44 @@ class MemoryStorage implements Storage {
|
||||
|
||||
describe('LogNotificationDeduper', () => {
|
||||
it('accepts error, fatal, and component update log lines', () => {
|
||||
expect(isErrorLogLine('forkop: [info] ok')).toBe(false);
|
||||
expect(isErrorLogLine('forkop: [error] failed')).toBe(true);
|
||||
expect(isErrorLogLine('forkop: [fatal] failed')).toBe(true);
|
||||
expect(isErrorLogLine('tachyon: [info] ok')).toBe(false);
|
||||
expect(isErrorLogLine('tachyon: [error] failed')).toBe(true);
|
||||
expect(isErrorLogLine('tachyon: [fatal] failed')).toBe(true);
|
||||
expect(
|
||||
getForkopLogNotification(
|
||||
'forkop: [info] [component-update] zapret2 v1.2.3',
|
||||
getTachyonLogNotification(
|
||||
'tachyon: [info] [component-update] zapret2 v1.2.3',
|
||||
),
|
||||
).toEqual({
|
||||
kind: 'component-update',
|
||||
line: 'forkop: [info] [component-update] zapret2 v1.2.3',
|
||||
line: 'tachyon: [info] [component-update] zapret2 v1.2.3',
|
||||
component: 'zapret2',
|
||||
version: 'v1.2.3',
|
||||
});
|
||||
expect(getForkopLogNotification('forkop: [info] ok')).toBeNull();
|
||||
expect(getTachyonLogNotification('tachyon: [info] ok')).toBeNull();
|
||||
});
|
||||
|
||||
it('dedupes already shown log lines through session storage', () => {
|
||||
const storage = new MemoryStorage();
|
||||
const first = new LogNotificationDeduper(storage);
|
||||
|
||||
expect(first.shouldNotify('forkop: [error] failed')).toBe(true);
|
||||
expect(first.shouldNotify('forkop: [error] failed')).toBe(false);
|
||||
expect(first.shouldNotify('forkop: [error] another failure')).toBe(true);
|
||||
expect(first.shouldNotify('tachyon: [error] failed')).toBe(true);
|
||||
expect(first.shouldNotify('tachyon: [error] failed')).toBe(false);
|
||||
expect(first.shouldNotify('tachyon: [error] another failure')).toBe(true);
|
||||
expect(
|
||||
first.shouldNotify('forkop: [info] [component-update] forkop 1.2.3'),
|
||||
first.shouldNotify('tachyon: [info] [component-update] tachyon 1.2.3'),
|
||||
).toBe(true);
|
||||
|
||||
const afterReload = new LogNotificationDeduper(storage);
|
||||
|
||||
expect(afterReload.shouldNotify('forkop: [error] failed')).toBe(false);
|
||||
expect(afterReload.shouldNotify('forkop: [fatal] fatal failure')).toBe(
|
||||
expect(afterReload.shouldNotify('tachyon: [error] failed')).toBe(false);
|
||||
expect(afterReload.shouldNotify('tachyon: [fatal] fatal failure')).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
it('keeps the full log line as the replay key', () => {
|
||||
expect(getLogNotificationKey(' Jun 06 forkop: [error] failed ')).toBe(
|
||||
'Jun 06 forkop: [error] failed',
|
||||
expect(getLogNotificationKey(' Jun 06 tachyon: [error] failed ')).toBe(
|
||||
'Jun 06 tachyon: [error] failed',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ vi.mock('../../../helpers', () => ({
|
||||
executeShellCommand: mocks.executeShellCommand,
|
||||
}));
|
||||
|
||||
import { Forkop } from '../../types';
|
||||
import { Tachyon } from '../../types';
|
||||
import { store } from '../store.service';
|
||||
import {
|
||||
getCachedRuntimeUiState,
|
||||
@@ -19,10 +19,10 @@ import {
|
||||
function createUiState(
|
||||
status = 'running & enabled',
|
||||
running = 1,
|
||||
): Forkop.UiState {
|
||||
): Tachyon.UiState {
|
||||
return {
|
||||
service: {
|
||||
forkop: {
|
||||
tachyon: {
|
||||
running,
|
||||
enabled: 1,
|
||||
status,
|
||||
@@ -73,14 +73,14 @@ describe('refreshRuntimeUiState', () => {
|
||||
);
|
||||
|
||||
expect(mocks.executeShellCommand).toHaveBeenCalledWith({
|
||||
command: '/usr/bin/forkop',
|
||||
command: '/usr/bin/tachyon',
|
||||
args: ['get_ui_state'],
|
||||
timeout: 3000,
|
||||
});
|
||||
expect(store.get().servicesInfoWidget.data).toMatchObject({
|
||||
forkopRunning: 0,
|
||||
forkopEnabled: 1,
|
||||
forkopStatus: 'stopped but enabled',
|
||||
tachyonRunning: 0,
|
||||
tachyonEnabled: 1,
|
||||
tachyonStatus: 'stopped but enabled',
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { beforeEach, describe, expect, it } from 'vitest';
|
||||
|
||||
import { ForkopLogWatcher } from '../forkopLogWatcher.service';
|
||||
import { TachyonLogWatcher } from '../tachyonLogWatcher.service';
|
||||
|
||||
describe('ForkopLogWatcher', () => {
|
||||
const watcher = ForkopLogWatcher.getInstance();
|
||||
describe('TachyonLogWatcher', () => {
|
||||
const watcher = TachyonLogWatcher.getInstance();
|
||||
let rawLogs = '';
|
||||
let seenLines: string[] = [];
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { beforeEach, describe, expect, it } from 'vitest';
|
||||
import { applyUiStateToStore } from '../uiState.service';
|
||||
import { store } from '../store.service';
|
||||
import { Forkop } from '../../types';
|
||||
import { Tachyon } from '../../types';
|
||||
import {
|
||||
clearLocalActionOverlay,
|
||||
setLocalComponentAction,
|
||||
@@ -11,12 +11,12 @@ import {
|
||||
} from '../localActionOverlay.service';
|
||||
|
||||
function createUiState(
|
||||
actions: Partial<Forkop.UiState['actions']> = {},
|
||||
capabilities: Partial<Forkop.UiState['capabilities']> = {},
|
||||
): Forkop.UiState {
|
||||
actions: Partial<Tachyon.UiState['actions']> = {},
|
||||
capabilities: Partial<Tachyon.UiState['capabilities']> = {},
|
||||
): Tachyon.UiState {
|
||||
return {
|
||||
service: {
|
||||
forkop: {
|
||||
tachyon: {
|
||||
running: 0,
|
||||
enabled: 1,
|
||||
status: 'starting',
|
||||
@@ -114,9 +114,9 @@ describe('applyUiStateToStore', () => {
|
||||
loading: false,
|
||||
failed: false,
|
||||
data: {
|
||||
forkopEnabled: 1,
|
||||
forkopRunning: 0,
|
||||
forkopStatus: 'starting',
|
||||
tachyonEnabled: 1,
|
||||
tachyonRunning: 0,
|
||||
tachyonStatus: 'starting',
|
||||
},
|
||||
});
|
||||
expect(state.diagnosticsSystemInfo).toMatchObject({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const UI_ACTION_NOTIFICATION_STORAGE_KEY =
|
||||
'forkop:owned-ui-action-notifications:v1';
|
||||
'tachyon:owned-ui-action-notifications:v1';
|
||||
const MAX_STORED_UI_ACTION_NOTIFICATIONS = 100;
|
||||
|
||||
export type UiActionNotificationKind = 'component' | 'subscription';
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { getComponentActionKey } from '../helpers/getComponentActionKey';
|
||||
import { normalizeSingBoxVariantFields } from '../helpers/singBoxVariant';
|
||||
import type { Forkop } from '../types';
|
||||
import type { Tachyon } from '../types';
|
||||
import { getLocalActionOverlay } from './localActionOverlay.service';
|
||||
import { store } from './store.service';
|
||||
import type { StoreType } from './store.service';
|
||||
|
||||
type UiActionMap = Partial<Forkop.UiState['actions']>;
|
||||
type UiActionMap = Partial<Tachyon.UiState['actions']>;
|
||||
|
||||
function isRunningAction(state: { running?: boolean }) {
|
||||
return state.running === true;
|
||||
@@ -13,8 +13,8 @@ function isRunningAction(state: { running?: boolean }) {
|
||||
|
||||
function getEmptyUpdatesActions(): StoreType['updatesActions'] {
|
||||
return {
|
||||
forkopCheck: { loading: false },
|
||||
forkopInstall: { loading: false },
|
||||
tachyonCheck: { loading: false },
|
||||
tachyonInstall: { loading: false },
|
||||
singBoxCheck: { loading: false },
|
||||
singBoxInstall: { loading: false },
|
||||
singBoxInstallExtended: { loading: false },
|
||||
@@ -43,8 +43,8 @@ function getEmptyDiagnosticsActions(): StoreType['diagnosticsActions'] {
|
||||
}
|
||||
|
||||
function normalizeLatencyProgress(
|
||||
progress?: Forkop.LatencyActionProgress,
|
||||
): Forkop.LatencyActionProgress | undefined {
|
||||
progress?: Tachyon.LatencyActionProgress,
|
||||
): Tachyon.LatencyActionProgress | undefined {
|
||||
const total = Math.trunc(Number(progress?.total ?? 0));
|
||||
|
||||
if (!Number.isFinite(total) || total <= 0) {
|
||||
@@ -65,7 +65,7 @@ function normalizeLatencyProgress(
|
||||
};
|
||||
}
|
||||
|
||||
function applyServiceState(uiState: Forkop.UiState) {
|
||||
function applyServiceState(uiState: Tachyon.UiState) {
|
||||
const currentSystemInfo = store.get().diagnosticsSystemInfo;
|
||||
const nextSystemInfo = {
|
||||
...currentSystemInfo,
|
||||
@@ -88,9 +88,9 @@ function applyServiceState(uiState: Forkop.UiState) {
|
||||
failed: false,
|
||||
data: {
|
||||
singbox: uiState.service.sing_box.running,
|
||||
forkopRunning: uiState.service.forkop.running,
|
||||
forkopEnabled: uiState.service.forkop.enabled,
|
||||
forkopStatus: uiState.service.forkop.status,
|
||||
tachyonRunning: uiState.service.tachyon.running,
|
||||
tachyonEnabled: uiState.service.tachyon.enabled,
|
||||
tachyonStatus: uiState.service.tachyon.status,
|
||||
},
|
||||
},
|
||||
diagnosticsSystemInfo: normalizeSingBoxVariantFields(nextSystemInfo),
|
||||
@@ -104,7 +104,7 @@ function applyActionState(actions: UiActionMap = {}) {
|
||||
current.sectionsWidget.latencyProgressSections;
|
||||
const subscriptionUpdatingSections: Record<string, boolean> = {};
|
||||
const latencyFetchingSections: Record<string, boolean> = {};
|
||||
const latencyProgressSections: Record<string, Forkop.LatencyActionProgress> =
|
||||
const latencyProgressSections: Record<string, Tachyon.LatencyActionProgress> =
|
||||
{};
|
||||
const updatesActions = getEmptyUpdatesActions();
|
||||
const diagnosticsActions = getEmptyDiagnosticsActions();
|
||||
@@ -188,7 +188,7 @@ function applyActionState(actions: UiActionMap = {}) {
|
||||
});
|
||||
}
|
||||
|
||||
export function applyUiStateToStore(uiState: Forkop.UiState) {
|
||||
export function applyUiStateToStore(uiState: Tachyon.UiState) {
|
||||
applyServiceState(uiState);
|
||||
applyActionState(uiState.actions);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { copyToClipboard } from '../../../helpers/copyToClipboard';
|
||||
import { showToast } from '../../../helpers/showToast';
|
||||
import { prettyBytes } from '../../../helpers/prettyBytes';
|
||||
import { renderCopyIcon24 } from '../../../icons';
|
||||
import { CustomForkopMethods, ForkopShellMethods } from '../../methods';
|
||||
import { CustomTachyonMethods, TachyonShellMethods } from '../../methods';
|
||||
import {
|
||||
logger,
|
||||
markUiActionOwned,
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
import { getLatencyTestLabel, renderSections, renderWidget } from './partials';
|
||||
import { fetchServicesInfo } from '../../fetchers/fetchServicesInfo';
|
||||
import { getClashApiSecret } from '../../methods/custom/getClashApiSecret';
|
||||
import { Forkop } from '../../types';
|
||||
import { Tachyon } from '../../types';
|
||||
import {
|
||||
getCachedRuntimeUiState,
|
||||
refreshRuntimeUiState,
|
||||
@@ -79,7 +79,7 @@ async function fetchDashboardSectionsOnce(mountId: number) {
|
||||
});
|
||||
|
||||
try {
|
||||
const { data, success } = await CustomForkopMethods.getDashboardSections();
|
||||
const { data, success } = await CustomTachyonMethods.getDashboardSections();
|
||||
|
||||
if (
|
||||
!dashboardMounted ||
|
||||
@@ -219,7 +219,7 @@ function setLatencyFetching(
|
||||
sectionName: string,
|
||||
fetching: boolean,
|
||||
local = false,
|
||||
progress?: Forkop.LatencyActionProgress,
|
||||
progress?: Tachyon.LatencyActionProgress,
|
||||
) {
|
||||
if (local || !fetching) {
|
||||
setLocalLatencyAction(sectionName, fetching && local);
|
||||
@@ -255,7 +255,7 @@ function setLatencyFetching(
|
||||
async function completeSubscriptionUpdateJob(
|
||||
jobId: string,
|
||||
sectionName: string,
|
||||
response: Forkop.MethodResponse<Forkop.SubscriptionUpdateJobState>,
|
||||
response: Tachyon.MethodResponse<Tachyon.SubscriptionUpdateJobState>,
|
||||
) {
|
||||
if (pageUnloading) {
|
||||
setSubscriptionUpdating(sectionName, false);
|
||||
@@ -287,7 +287,7 @@ async function completeSubscriptionUpdateJob(
|
||||
setSubscriptionUpdating(sectionName, false);
|
||||
|
||||
if (jobId && response.success) {
|
||||
void ForkopShellMethods.uiActionAck('subscription', jobId);
|
||||
void TachyonShellMethods.uiActionAck('subscription', jobId);
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
@@ -305,7 +305,7 @@ async function completeSubscriptionUpdateJob(
|
||||
}
|
||||
|
||||
async function followSubscriptionUpdateState(
|
||||
state: Forkop.SubscriptionUpdateJobState,
|
||||
state: Tachyon.SubscriptionUpdateJobState,
|
||||
) {
|
||||
const jobId = state.job_id;
|
||||
const sectionName = state.section || '';
|
||||
@@ -325,11 +325,11 @@ async function followSubscriptionUpdateState(
|
||||
|
||||
try {
|
||||
const response = state.running
|
||||
? await ForkopShellMethods.waitSubscriptionUpdateJob(jobId)
|
||||
? await TachyonShellMethods.waitSubscriptionUpdateJob(jobId)
|
||||
: ({
|
||||
success: true,
|
||||
data: state,
|
||||
} as Forkop.MethodSuccessResponse<Forkop.SubscriptionUpdateJobState>);
|
||||
} as Tachyon.MethodSuccessResponse<Tachyon.SubscriptionUpdateJobState>);
|
||||
|
||||
await completeSubscriptionUpdateJob(jobId, sectionName, response);
|
||||
} catch (error) {
|
||||
@@ -366,13 +366,13 @@ async function completeLatencyTestJob(jobId: string, sectionName: string) {
|
||||
}
|
||||
|
||||
if (jobId) {
|
||||
void ForkopShellMethods.uiActionAck('latency', jobId);
|
||||
void TachyonShellMethods.uiActionAck('latency', jobId);
|
||||
}
|
||||
|
||||
void fetchDashboardSections({ force: true });
|
||||
}
|
||||
|
||||
async function followLatencyTestState(state: Forkop.LatencyActionState) {
|
||||
async function followLatencyTestState(state: Tachyon.LatencyActionState) {
|
||||
const jobId = state.job_id;
|
||||
const sectionName = state.section || '';
|
||||
|
||||
@@ -391,7 +391,7 @@ async function followLatencyTestState(state: Forkop.LatencyActionState) {
|
||||
|
||||
try {
|
||||
if (state.running) {
|
||||
await ForkopShellMethods.waitLatencyTestJob(jobId);
|
||||
await TachyonShellMethods.waitLatencyTestJob(jobId);
|
||||
}
|
||||
|
||||
await completeLatencyTestJob(jobId, sectionName);
|
||||
@@ -405,13 +405,13 @@ async function followLatencyTestState(state: Forkop.LatencyActionState) {
|
||||
}
|
||||
}
|
||||
|
||||
function followDashboardActionsFromUiState(uiState: Forkop.UiState) {
|
||||
function followDashboardActionsFromUiState(uiState: Tachyon.UiState) {
|
||||
for (const state of uiState.actions.subscription || []) {
|
||||
if (state.running || (state.job_id && state.section)) {
|
||||
void followSubscriptionUpdateState(state);
|
||||
} else if (state.job_id && !handledSubscriptionJobs.has(state.job_id)) {
|
||||
handledSubscriptionJobs.add(state.job_id);
|
||||
void ForkopShellMethods.uiActionAck('subscription', state.job_id);
|
||||
void TachyonShellMethods.uiActionAck('subscription', state.job_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,7 +420,7 @@ function followDashboardActionsFromUiState(uiState: Forkop.UiState) {
|
||||
void followLatencyTestState(state);
|
||||
} else if (state.job_id && !handledLatencyJobs.has(state.job_id)) {
|
||||
handledLatencyJobs.add(state.job_id);
|
||||
void ForkopShellMethods.uiActionAck('latency', state.job_id);
|
||||
void TachyonShellMethods.uiActionAck('latency', state.job_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -571,7 +571,7 @@ function getDashboardServiceAvailability() {
|
||||
return getServiceAvailability({
|
||||
loading: service.loading,
|
||||
failed: service.failed,
|
||||
running: service.data.forkopRunning,
|
||||
running: service.data.tachyonRunning,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -646,7 +646,7 @@ async function handleChooseOutbound(
|
||||
setSelectorSwitching(sectionName, tag);
|
||||
|
||||
try {
|
||||
await ForkopShellMethods.setClashApiGroupProxy(selector, tag);
|
||||
await TachyonShellMethods.setClashApiGroupProxy(selector, tag);
|
||||
await fetchDashboardSections({ force: true });
|
||||
} finally {
|
||||
setSelectorSwitching(sectionName);
|
||||
@@ -654,9 +654,9 @@ async function handleChooseOutbound(
|
||||
}
|
||||
|
||||
function getInitialLatencyProgress(
|
||||
latencyType: Forkop.LatencyActionState['latency_type'],
|
||||
latencyType: Tachyon.LatencyActionState['latency_type'],
|
||||
tag: string,
|
||||
): Forkop.LatencyActionProgress | undefined {
|
||||
): Tachyon.LatencyActionProgress | undefined {
|
||||
if (latencyType !== 'proxy_list') {
|
||||
return undefined;
|
||||
}
|
||||
@@ -678,7 +678,7 @@ function getInitialLatencyProgress(
|
||||
}
|
||||
|
||||
async function handleTestLatency(
|
||||
latencyType: Forkop.LatencyActionState['latency_type'],
|
||||
latencyType: Tachyon.LatencyActionState['latency_type'],
|
||||
sectionName: string,
|
||||
tag: string,
|
||||
timeout?: string,
|
||||
@@ -698,7 +698,7 @@ async function handleTestLatency(
|
||||
let completed = false;
|
||||
|
||||
try {
|
||||
const startResponse = await ForkopShellMethods.latencyTestStart(
|
||||
const startResponse = await TachyonShellMethods.latencyTestStart(
|
||||
latencyType,
|
||||
sectionName,
|
||||
tag,
|
||||
@@ -717,7 +717,7 @@ async function handleTestLatency(
|
||||
|
||||
followedLatencyJobs.add(jobId);
|
||||
ownsJobFollow = true;
|
||||
await ForkopShellMethods.waitLatencyTestJob(jobId);
|
||||
await TachyonShellMethods.waitLatencyTestJob(jobId);
|
||||
await completeLatencyTestJob(jobId, sectionName);
|
||||
completed = true;
|
||||
} catch (error) {
|
||||
@@ -734,8 +734,8 @@ async function handleTestLatency(
|
||||
}
|
||||
|
||||
async function handleCopyOutbound(
|
||||
section: Forkop.OutboundGroup,
|
||||
outbound: Forkop.Outbound,
|
||||
section: Tachyon.OutboundGroup,
|
||||
outbound: Tachyon.Outbound,
|
||||
) {
|
||||
const link = outbound.link;
|
||||
|
||||
@@ -744,7 +744,7 @@ async function handleCopyOutbound(
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await ForkopShellMethods.getOutboundLink(
|
||||
const response = await TachyonShellMethods.getOutboundLink(
|
||||
section.sectionName,
|
||||
outbound.code,
|
||||
);
|
||||
@@ -817,7 +817,7 @@ function getDetectedCountryFlag(country?: string) {
|
||||
);
|
||||
}
|
||||
|
||||
function renderDetailsMemberName(member: Forkop.UrlTestMember) {
|
||||
function renderDetailsMemberName(member: Tachyon.UrlTestMember) {
|
||||
const countryFlag = getDetectedCountryFlag(member.country);
|
||||
if (!countryFlag) {
|
||||
return member.displayName;
|
||||
@@ -833,7 +833,7 @@ function renderDetailsMemberName(member: Forkop.UrlTestMember) {
|
||||
];
|
||||
}
|
||||
|
||||
function renderUrlTestSelectedValue(info: Forkop.UrlTestInfo) {
|
||||
function renderUrlTestSelectedValue(info: Tachyon.UrlTestInfo) {
|
||||
const selectedMember = info.outbounds.find((member) => member.selected);
|
||||
const selectedName =
|
||||
selectedMember?.displayName || info.selectedName || info.selectedCode || '';
|
||||
@@ -892,8 +892,8 @@ function renderUrlTestCopyButton(
|
||||
}
|
||||
|
||||
function renderUrlTestInfoModal(
|
||||
section: Forkop.OutboundGroup,
|
||||
outbound: Forkop.Outbound,
|
||||
section: Tachyon.OutboundGroup,
|
||||
outbound: Tachyon.Outbound,
|
||||
) {
|
||||
const info = outbound.urlTestInfo;
|
||||
|
||||
@@ -1031,8 +1031,8 @@ function renderUrlTestInfoModal(
|
||||
}
|
||||
|
||||
function handleShowUrlTestInfo(
|
||||
section: Forkop.OutboundGroup,
|
||||
outbound: Forkop.Outbound,
|
||||
section: Tachyon.OutboundGroup,
|
||||
outbound: Tachyon.Outbound,
|
||||
) {
|
||||
if (!outbound.urlTestInfo) {
|
||||
return;
|
||||
@@ -1046,7 +1046,7 @@ function handleShowUrlTestInfo(
|
||||
);
|
||||
}
|
||||
|
||||
function renderPrioritySelectedValue(info: Forkop.PriorityInfo) {
|
||||
function renderPrioritySelectedValue(info: Tachyon.PriorityInfo) {
|
||||
const selectedMember = info.outbounds.find((member) => member.selected);
|
||||
const selectedName =
|
||||
selectedMember?.displayName || info.selectedName || info.selectedCode || '';
|
||||
@@ -1096,7 +1096,7 @@ function renderPrioritySelectedValue(info: Forkop.PriorityInfo) {
|
||||
);
|
||||
}
|
||||
|
||||
function renderPriorityMemberName(member: Forkop.PriorityMember) {
|
||||
function renderPriorityMemberName(member: Tachyon.PriorityMember) {
|
||||
const levelName = member.levelName || _('Level');
|
||||
|
||||
return [
|
||||
@@ -1119,8 +1119,8 @@ function renderPriorityMemberName(member: Forkop.PriorityMember) {
|
||||
}
|
||||
|
||||
function renderPriorityInfoModal(
|
||||
section: Forkop.OutboundGroup,
|
||||
outbound: Forkop.Outbound,
|
||||
section: Tachyon.OutboundGroup,
|
||||
outbound: Tachyon.Outbound,
|
||||
) {
|
||||
const info = outbound.priorityInfo;
|
||||
|
||||
@@ -1287,8 +1287,8 @@ function renderPriorityInfoModal(
|
||||
}
|
||||
|
||||
function handleShowPriorityInfo(
|
||||
section: Forkop.OutboundGroup,
|
||||
outbound: Forkop.Outbound,
|
||||
section: Tachyon.OutboundGroup,
|
||||
outbound: Tachyon.Outbound,
|
||||
) {
|
||||
if (!outbound.priorityInfo) {
|
||||
return;
|
||||
@@ -1302,7 +1302,7 @@ function handleShowPriorityInfo(
|
||||
);
|
||||
}
|
||||
|
||||
async function handleUpdateSubscription(section: Forkop.OutboundGroup) {
|
||||
async function handleUpdateSubscription(section: Tachyon.OutboundGroup) {
|
||||
if (
|
||||
store.get().sectionsWidget.subscriptionUpdatingSections[section.sectionName]
|
||||
) {
|
||||
@@ -1314,7 +1314,7 @@ async function handleUpdateSubscription(section: Forkop.OutboundGroup) {
|
||||
let ownsJobFollow = false;
|
||||
|
||||
try {
|
||||
const startResponse = await ForkopShellMethods.subscriptionUpdateStart(
|
||||
const startResponse = await TachyonShellMethods.subscriptionUpdateStart(
|
||||
section.sectionName,
|
||||
);
|
||||
|
||||
@@ -1330,7 +1330,7 @@ async function handleUpdateSubscription(section: Forkop.OutboundGroup) {
|
||||
|
||||
followedSubscriptionJobs.add(jobId);
|
||||
ownsJobFollow = true;
|
||||
const response = await ForkopShellMethods.waitSubscriptionUpdateJob(jobId);
|
||||
const response = await TachyonShellMethods.waitSubscriptionUpdateJob(jobId);
|
||||
await completeSubscriptionUpdateJob(jobId, section.sectionName, response);
|
||||
} catch (error) {
|
||||
logger.error('[DASHBOARD]', 'handleUpdateSubscription: failed', error);
|
||||
@@ -1670,12 +1670,12 @@ async function renderServicesInfoWidget() {
|
||||
title: _('Services info'),
|
||||
items: [
|
||||
{
|
||||
key: 'Forkop',
|
||||
value: servicesInfoWidget.data.forkopRunning
|
||||
key: 'Tachyon',
|
||||
value: servicesInfoWidget.data.tachyonRunning
|
||||
? _('✔ Running')
|
||||
: _('✘ Stopped'),
|
||||
attributes: {
|
||||
class: servicesInfoWidget.data.forkopRunning
|
||||
class: servicesInfoWidget.data.tachyonRunning
|
||||
? 'fkp_dashboard-page__widgets-section__item__row--success'
|
||||
: 'fkp_dashboard-page__widgets-section__item__row--error',
|
||||
},
|
||||
|
||||
@@ -6,12 +6,12 @@ import {
|
||||
} from '../../../../icons';
|
||||
import { isCopyableProxyLink, svgEl } from '../../../../helpers';
|
||||
import { prettyBytes } from '../../../../helpers/prettyBytes';
|
||||
import { Forkop } from '../../../types';
|
||||
import { Tachyon } from '../../../types';
|
||||
|
||||
interface IRenderSectionsProps {
|
||||
loading: boolean;
|
||||
failed: boolean;
|
||||
section: Forkop.OutboundGroup;
|
||||
section: Tachyon.OutboundGroup;
|
||||
onTestLatency: (tag: string | string[]) => void;
|
||||
onChooseOutbound: (
|
||||
sectionName: string,
|
||||
@@ -19,20 +19,20 @@ interface IRenderSectionsProps {
|
||||
tag: string,
|
||||
) => void;
|
||||
onCopyOutbound: (
|
||||
section: Forkop.OutboundGroup,
|
||||
outbound: Forkop.Outbound,
|
||||
section: Tachyon.OutboundGroup,
|
||||
outbound: Tachyon.Outbound,
|
||||
) => void;
|
||||
onShowUrlTestInfo: (
|
||||
section: Forkop.OutboundGroup,
|
||||
outbound: Forkop.Outbound,
|
||||
section: Tachyon.OutboundGroup,
|
||||
outbound: Tachyon.Outbound,
|
||||
) => void;
|
||||
onShowPriorityInfo: (
|
||||
section: Forkop.OutboundGroup,
|
||||
outbound: Forkop.Outbound,
|
||||
section: Tachyon.OutboundGroup,
|
||||
outbound: Tachyon.Outbound,
|
||||
) => void;
|
||||
onUpdateSubscription: (section: Forkop.OutboundGroup) => void;
|
||||
onUpdateSubscription: (section: Tachyon.OutboundGroup) => void;
|
||||
latencyFetching: boolean;
|
||||
latencyProgress?: Forkop.LatencyActionProgress;
|
||||
latencyProgress?: Tachyon.LatencyActionProgress;
|
||||
subscriptionUpdating: boolean;
|
||||
selectorSwitchingTag?: string;
|
||||
}
|
||||
@@ -109,7 +109,7 @@ function renderMetadataAction(label: string, url?: string) {
|
||||
}
|
||||
|
||||
function renderSubscriptionMetadata(
|
||||
metadata: Forkop.SubscriptionMetadata | undefined,
|
||||
metadata: Tachyon.SubscriptionMetadata | undefined,
|
||||
) {
|
||||
if (!metadata || Object.keys(metadata).length <= 1) {
|
||||
return undefined;
|
||||
@@ -203,9 +203,9 @@ function renderSubscriptionMetadata(
|
||||
}
|
||||
|
||||
function renderSubscriptionUpdateAction(
|
||||
section: Forkop.OutboundGroup,
|
||||
section: Tachyon.OutboundGroup,
|
||||
subscriptionUpdating: boolean,
|
||||
onUpdateSubscription: (section: Forkop.OutboundGroup) => void,
|
||||
onUpdateSubscription: (section: Tachyon.OutboundGroup) => void,
|
||||
) {
|
||||
if (!section.subscriptionSourceCount) {
|
||||
return undefined;
|
||||
@@ -235,7 +235,7 @@ function renderSubscriptionUpdateAction(
|
||||
}
|
||||
|
||||
export function getLatencyTestLabel(
|
||||
latencyProgress?: Forkop.LatencyActionProgress,
|
||||
latencyProgress?: Tachyon.LatencyActionProgress,
|
||||
) {
|
||||
const total = Math.trunc(Number(latencyProgress?.total ?? 0));
|
||||
if (!Number.isFinite(total) || total <= 0) {
|
||||
@@ -280,7 +280,7 @@ function renderDefaultState({
|
||||
}
|
||||
}
|
||||
|
||||
function renderOutbound(outbound: Forkop.Outbound) {
|
||||
function renderOutbound(outbound: Tachyon.Outbound) {
|
||||
function getLatencyClass() {
|
||||
if (!outbound.latency) {
|
||||
return 'fkp_dashboard-page__outbound-grid__item__latency--empty';
|
||||
|
||||
@@ -15,7 +15,7 @@ export function render() {
|
||||
role: 'status',
|
||||
},
|
||||
_(
|
||||
'Forkop service is stopped. Start the service to display the dashboard.',
|
||||
'Tachyon service is stopped. Start the service to display the dashboard.',
|
||||
),
|
||||
),
|
||||
E('div', { class: 'fkp_dashboard-page__content' }, [
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
// language=CSS
|
||||
import { FORKOP_UCI_PACKAGE as FORKOP_CBI_PREFIX } from '../../../constants';
|
||||
import { TACHYON_UCI_PACKAGE as TACHYON_CBI_PREFIX } from '../../../constants';
|
||||
|
||||
export const styles = `
|
||||
#cbi-${FORKOP_CBI_PREFIX}-dashboard-_mount_node > .cbi-value-title {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-dashboard-_mount_node > .cbi-value-title {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#cbi-${FORKOP_CBI_PREFIX}-dashboard-_mount_node > .cbi-value-field {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-dashboard-_mount_node > .cbi-value-field {
|
||||
margin-left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#cbi-${FORKOP_CBI_PREFIX}-dashboard-_mount_node > div {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-dashboard-_mount_node > div {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#cbi-${FORKOP_CBI_PREFIX}-dashboard > h3 {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-dashboard > h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { Forkop } from '../../../types';
|
||||
import type { Tachyon } from '../../../types';
|
||||
import { getMeta } from '../helpers/getMeta';
|
||||
|
||||
type DnsCheckState = 'error' | 'success' | 'warning';
|
||||
|
||||
export function getDnsCheckPresentation(data: Forkop.DnsCheckResult) {
|
||||
export function getDnsCheckPresentation(data: Tachyon.DnsCheckResult) {
|
||||
const dhcpManagedManually = Boolean(data.dont_touch_dhcp);
|
||||
const dhcpCheckOk = dhcpManagedManually || Boolean(data.dhcp_config_status);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||
import { ForkopShellMethods } from '../../../methods';
|
||||
import { TachyonShellMethods } from '../../../methods';
|
||||
import { updateCheckStore } from './updateCheckStore';
|
||||
import { IDiagnosticsChecksItem } from '../../../services';
|
||||
import { getCheckItemsMeta } from './getCheckItemsMeta';
|
||||
@@ -16,7 +16,7 @@ export async function runByedpiCheck() {
|
||||
items: [],
|
||||
});
|
||||
|
||||
const byedpiStatus = await ForkopShellMethods.getByedpiStatus();
|
||||
const byedpiStatus = await TachyonShellMethods.getByedpiStatus();
|
||||
|
||||
if (!byedpiStatus.success) {
|
||||
updateCheckStore({
|
||||
@@ -40,7 +40,7 @@ export async function runByedpiCheck() {
|
||||
const supervisorProcesses = Number(data.supervisor_process_count || 0);
|
||||
const restartCount = Number(data.restart_count || 0);
|
||||
const runtimeUnstable = Boolean(data.runtime_unstable);
|
||||
const forkopRuntimeReady =
|
||||
const tachyonRuntimeReady =
|
||||
!hasByedpiRules ||
|
||||
(runningProcesses === expectedProcesses &&
|
||||
supervisorProcesses === expectedProcesses);
|
||||
@@ -81,20 +81,20 @@ export async function runByedpiCheck() {
|
||||
},
|
||||
{
|
||||
state:
|
||||
unexpectedRuntime || !forkopRuntimeReady
|
||||
unexpectedRuntime || !tachyonRuntimeReady
|
||||
? 'error'
|
||||
: runtimeUnstable
|
||||
? 'warning'
|
||||
: 'success',
|
||||
key: hasByedpiRules
|
||||
? runtimeUnstable
|
||||
? _('Forkop-managed ciadpi runtime has restarted')
|
||||
: forkopRuntimeReady
|
||||
? _('Forkop-managed ciadpi runtime is ready')
|
||||
: _('Forkop-managed ciadpi runtime is not ready')
|
||||
? _('Tachyon-managed ciadpi runtime has restarted')
|
||||
: tachyonRuntimeReady
|
||||
? _('Tachyon-managed ciadpi runtime is ready')
|
||||
: _('Tachyon-managed ciadpi runtime is not ready')
|
||||
: unexpectedRuntime
|
||||
? _('Unexpected Forkop-managed ciadpi runtime is running')
|
||||
: _('Forkop-managed ciadpi runtime is not running'),
|
||||
? _('Unexpected Tachyon-managed ciadpi runtime is running')
|
||||
: _('Tachyon-managed ciadpi runtime is not running'),
|
||||
value: hasByedpiRules
|
||||
? runtimeUnstable
|
||||
? `${restartCount}`
|
||||
@@ -116,7 +116,7 @@ export async function runByedpiCheck() {
|
||||
: 'success',
|
||||
key: standaloneServiceRunning
|
||||
? hasByedpiRules
|
||||
? _('Standalone ByeDPI is active together with Forkop ByeDPI rules')
|
||||
? _('Standalone ByeDPI is active together with Tachyon ByeDPI rules')
|
||||
: _('Standalone ByeDPI service is active')
|
||||
: standaloneAutostartRisk
|
||||
? _('Standalone ByeDPI autostart is enabled')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { insertIf } from '../../../../helpers';
|
||||
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||
import { ForkopShellMethods } from '../../../methods';
|
||||
import { TachyonShellMethods } from '../../../methods';
|
||||
import type { IDiagnosticsChecksItem } from '../../../services';
|
||||
import { updateCheckStore } from './updateCheckStore';
|
||||
import { getDnsCheckPresentation } from './getDnsCheckPresentation';
|
||||
@@ -17,7 +17,7 @@ export async function runDnsCheck() {
|
||||
items: [],
|
||||
});
|
||||
|
||||
const dnsChecks = await ForkopShellMethods.checkDNSAvailable();
|
||||
const dnsChecks = await TachyonShellMethods.checkDNSAvailable();
|
||||
|
||||
if (!dnsChecks.success) {
|
||||
updateCheckStore({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { insertIf } from '../../../../helpers';
|
||||
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||
import { ForkopShellMethods, RemoteFakeIPMethods } from '../../../methods';
|
||||
import { TachyonShellMethods, RemoteFakeIPMethods } from '../../../methods';
|
||||
import type { IDiagnosticsChecksItem } from '../../../services';
|
||||
import { updateCheckStore } from './updateCheckStore';
|
||||
import { getMeta } from '../helpers/getMeta';
|
||||
@@ -17,7 +17,7 @@ export async function runFakeIPCheck() {
|
||||
items: [],
|
||||
});
|
||||
|
||||
const routerFakeIPResponse = await ForkopShellMethods.checkFakeIP();
|
||||
const routerFakeIPResponse = await TachyonShellMethods.checkFakeIP();
|
||||
const checkFakeIPResponse = await RemoteFakeIPMethods.getFakeIpCheck();
|
||||
const checkIPResponse = await RemoteFakeIPMethods.getIpCheck();
|
||||
const browserFakeIPCheckUnavailable = !checkFakeIPResponse.success;
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||
import { ForkopShellMethods } from '../../../methods';
|
||||
import { TachyonShellMethods } from '../../../methods';
|
||||
import { updateCheckStore } from './updateCheckStore';
|
||||
import { getMeta } from '../helpers/getMeta';
|
||||
import { IDiagnosticsChecksItem } from '../../../services';
|
||||
import { Forkop } from '../../../types';
|
||||
import { Tachyon } from '../../../types';
|
||||
|
||||
function serverPrefix(item: Forkop.InboundCheckItem) {
|
||||
function serverPrefix(item: Tachyon.InboundCheckItem) {
|
||||
return `${item.label}:`;
|
||||
}
|
||||
|
||||
function formatListen(item: Forkop.InboundCheckItem) {
|
||||
function formatListen(item: Tachyon.InboundCheckItem) {
|
||||
return `${item.listen}:${Number(item.listen_port || 0)} [${item.required_proto}]`;
|
||||
}
|
||||
|
||||
function getPortConflictItem(
|
||||
item: Forkop.InboundCheckItem,
|
||||
item: Tachyon.InboundCheckItem,
|
||||
): IDiagnosticsChecksItem {
|
||||
const key = `${serverPrefix(item)} ${_('Port conflict')}`;
|
||||
|
||||
@@ -34,7 +34,7 @@ function getPortConflictItem(
|
||||
}
|
||||
|
||||
function getPublicHostItem(
|
||||
item: Forkop.InboundCheckItem,
|
||||
item: Tachyon.InboundCheckItem,
|
||||
wanIp: string,
|
||||
): IDiagnosticsChecksItem {
|
||||
const key = `${serverPrefix(item)} ${_('Public host')}`;
|
||||
@@ -79,7 +79,7 @@ function getPublicHostItem(
|
||||
}
|
||||
|
||||
function getServerItems(
|
||||
item: Forkop.InboundCheckItem,
|
||||
item: Tachyon.InboundCheckItem,
|
||||
wanIp: string,
|
||||
): IDiagnosticsChecksItem[] {
|
||||
const prefix = serverPrefix(item);
|
||||
@@ -162,7 +162,7 @@ export async function runInboundsCheck() {
|
||||
items: [],
|
||||
});
|
||||
|
||||
const inboundsChecks = await ForkopShellMethods.checkInbounds();
|
||||
const inboundsChecks = await TachyonShellMethods.checkInbounds();
|
||||
|
||||
if (!inboundsChecks.success) {
|
||||
updateCheckStore({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||
import { RemoteFakeIPMethods, ForkopShellMethods } from '../../../methods';
|
||||
import { RemoteFakeIPMethods, TachyonShellMethods } from '../../../methods';
|
||||
import { updateCheckStore } from './updateCheckStore';
|
||||
import { getMeta } from '../helpers/getMeta';
|
||||
|
||||
@@ -18,7 +18,7 @@ export async function runNftCheck() {
|
||||
await RemoteFakeIPMethods.getFakeIpCheck();
|
||||
await RemoteFakeIPMethods.getIpCheck();
|
||||
|
||||
const nftablesChecks = await ForkopShellMethods.checkNftRules();
|
||||
const nftablesChecks = await TachyonShellMethods.checkNftRules();
|
||||
|
||||
if (!nftablesChecks.success) {
|
||||
updateCheckStore({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||
import { ForkopShellMethods } from '../../../methods';
|
||||
import { TachyonShellMethods } from '../../../methods';
|
||||
import { updateCheckStore } from './updateCheckStore';
|
||||
import { getMeta } from '../helpers/getMeta';
|
||||
import { getDashboardSections } from '../../../methods/custom/getDashboardSections';
|
||||
@@ -71,7 +71,7 @@ export async function runSectionsCheck() {
|
||||
const isSubscription = section.proxyConfigType === 'subscription';
|
||||
|
||||
if (selectedOutbound?.code) {
|
||||
const latencyProxy = await ForkopShellMethods.getClashApiProxyLatency(
|
||||
const latencyProxy = await TachyonShellMethods.getClashApiProxyLatency(
|
||||
selectedOutbound.code,
|
||||
section.latencyTestTimeout,
|
||||
);
|
||||
@@ -91,7 +91,7 @@ export async function runSectionsCheck() {
|
||||
};
|
||||
}
|
||||
|
||||
const latencyGroup = await ForkopShellMethods.getClashApiGroupLatency(
|
||||
const latencyGroup = await TachyonShellMethods.getClashApiGroupLatency(
|
||||
section.code,
|
||||
);
|
||||
const success = latencyGroup.success && !latencyGroup.data.message;
|
||||
@@ -125,7 +125,7 @@ export async function runSectionsCheck() {
|
||||
}
|
||||
|
||||
const selectedOutbound = section.outbounds[0];
|
||||
const latencyProxy = await ForkopShellMethods.getClashApiProxyLatency(
|
||||
const latencyProxy = await TachyonShellMethods.getClashApiProxyLatency(
|
||||
section.code,
|
||||
section.latencyTestTimeout,
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||
import { ForkopShellMethods } from '../../../methods';
|
||||
import { TachyonShellMethods } from '../../../methods';
|
||||
import { updateCheckStore } from './updateCheckStore';
|
||||
import { getMeta } from '../helpers/getMeta';
|
||||
|
||||
@@ -15,7 +15,7 @@ export async function runSingBoxCheck() {
|
||||
items: [],
|
||||
});
|
||||
|
||||
const singBoxChecks = await ForkopShellMethods.checkSingBox();
|
||||
const singBoxChecks = await TachyonShellMethods.checkSingBox();
|
||||
|
||||
if (!singBoxChecks.success) {
|
||||
updateCheckStore({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||
import { ForkopShellMethods } from '../../../methods';
|
||||
import { TachyonShellMethods } from '../../../methods';
|
||||
import { updateCheckStore } from './updateCheckStore';
|
||||
import { IDiagnosticsChecksItem } from '../../../services';
|
||||
import { getCheckItemsMeta } from './getCheckItemsMeta';
|
||||
@@ -16,7 +16,7 @@ export async function runZapret2Check() {
|
||||
items: [],
|
||||
});
|
||||
|
||||
const zapret2Status = await ForkopShellMethods.getZapret2Status();
|
||||
const zapret2Status = await TachyonShellMethods.getZapret2Status();
|
||||
|
||||
if (!zapret2Status.success) {
|
||||
updateCheckStore({
|
||||
@@ -39,7 +39,7 @@ export async function runZapret2Check() {
|
||||
const expectedProcesses = Number(data.expected_process_count || 0);
|
||||
const runningProcesses = Number(data.running_process_count || 0);
|
||||
const supervisorProcesses = Number(data.supervisor_process_count || 0);
|
||||
const forkopRuntimeReady =
|
||||
const tachyonRuntimeReady =
|
||||
!hasZapret2Rules ||
|
||||
(runningProcesses === expectedProcesses &&
|
||||
supervisorProcesses === expectedProcesses);
|
||||
@@ -83,14 +83,14 @@ export async function runZapret2Check() {
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
state: unexpectedRuntime || !forkopRuntimeReady ? 'error' : 'success',
|
||||
state: unexpectedRuntime || !tachyonRuntimeReady ? 'error' : 'success',
|
||||
key: hasZapret2Rules
|
||||
? forkopRuntimeReady
|
||||
? _('Forkop-managed nfqws2 runtime is ready')
|
||||
: _('Forkop-managed nfqws2 runtime is not ready')
|
||||
? tachyonRuntimeReady
|
||||
? _('Tachyon-managed nfqws2 runtime is ready')
|
||||
: _('Tachyon-managed nfqws2 runtime is not ready')
|
||||
: unexpectedRuntime
|
||||
? _('Unexpected Forkop-managed nfqws2 runtime is running')
|
||||
: _('Forkop-managed nfqws2 runtime is not running'),
|
||||
? _('Unexpected Tachyon-managed nfqws2 runtime is running')
|
||||
: _('Tachyon-managed nfqws2 runtime is not running'),
|
||||
value: hasZapret2Rules ? `${runningProcesses}/${expectedProcesses}` : '',
|
||||
},
|
||||
{
|
||||
@@ -115,7 +115,7 @@ export async function runZapret2Check() {
|
||||
: 'success',
|
||||
key: standaloneServiceRunning
|
||||
? hasZapret2Rules
|
||||
? _('Standalone Zapret2 is active together with Forkop Zapret2 rules')
|
||||
? _('Standalone Zapret2 is active together with Tachyon Zapret2 rules')
|
||||
: _('Standalone Zapret2 service is active')
|
||||
: standaloneAutostartRisk
|
||||
? _('Standalone Zapret2 autostart is enabled')
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||
import { ForkopShellMethods } from '../../../methods';
|
||||
import { TachyonShellMethods } from '../../../methods';
|
||||
import { updateCheckStore } from './updateCheckStore';
|
||||
import { IDiagnosticsChecksItem } from '../../../services';
|
||||
import { getCheckItemsMeta } from './getCheckItemsMeta';
|
||||
@@ -16,7 +16,7 @@ export async function runZapretCheck() {
|
||||
items: [],
|
||||
});
|
||||
|
||||
const zapretStatus = await ForkopShellMethods.getZapretStatus();
|
||||
const zapretStatus = await TachyonShellMethods.getZapretStatus();
|
||||
|
||||
if (!zapretStatus.success) {
|
||||
updateCheckStore({
|
||||
@@ -41,7 +41,7 @@ export async function runZapretCheck() {
|
||||
const expectedProcesses = Number(data.expected_process_count || 0);
|
||||
const runningProcesses = Number(data.running_process_count || 0);
|
||||
const supervisorProcesses = Number(data.supervisor_process_count || 0);
|
||||
const forkopRuntimeReady =
|
||||
const tachyonRuntimeReady =
|
||||
!hasZapretRules ||
|
||||
(runningProcesses === expectedProcesses &&
|
||||
supervisorProcesses === expectedProcesses);
|
||||
@@ -80,14 +80,14 @@ export async function runZapretCheck() {
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
state: unexpectedRuntime || !forkopRuntimeReady ? 'error' : 'success',
|
||||
state: unexpectedRuntime || !tachyonRuntimeReady ? 'error' : 'success',
|
||||
key: hasZapretRules
|
||||
? forkopRuntimeReady
|
||||
? _('Forkop-managed nfqws runtime is ready')
|
||||
: _('Forkop-managed nfqws runtime is not ready')
|
||||
? tachyonRuntimeReady
|
||||
? _('Tachyon-managed nfqws runtime is ready')
|
||||
: _('Tachyon-managed nfqws runtime is not ready')
|
||||
: unexpectedRuntime
|
||||
? _('Unexpected Forkop-managed nfqws runtime is running')
|
||||
: _('Forkop-managed nfqws runtime is not running'),
|
||||
? _('Unexpected Tachyon-managed nfqws runtime is running')
|
||||
: _('Tachyon-managed nfqws runtime is not running'),
|
||||
value: hasZapretRules ? `${runningProcesses}/${expectedProcesses}` : '',
|
||||
},
|
||||
{
|
||||
@@ -108,7 +108,7 @@ export async function runZapretCheck() {
|
||||
state: standaloneConflict ? 'warning' : 'success',
|
||||
key: standaloneServiceRunning
|
||||
? hasZapretRules
|
||||
? _('Standalone Zapret is active together with Forkop Zapret rules')
|
||||
? _('Standalone Zapret is active together with Tachyon Zapret rules')
|
||||
: _('Standalone Zapret service is active')
|
||||
: _('Standalone Zapret service is inactive'),
|
||||
value: '',
|
||||
|
||||
@@ -8,7 +8,7 @@ const mocks = vi.hoisted(() => ({
|
||||
}));
|
||||
|
||||
vi.mock('../../../../methods', () => ({
|
||||
ForkopShellMethods: {
|
||||
TachyonShellMethods: {
|
||||
getZapretStatus: mocks.getZapretStatus,
|
||||
getZapret2Status: mocks.getZapret2Status,
|
||||
getByedpiStatus: mocks.getByedpiStatus,
|
||||
|
||||
@@ -12,7 +12,7 @@ vi.mock('../../../../methods/custom/getDashboardSections', () => ({
|
||||
}));
|
||||
|
||||
vi.mock('../../../../methods', () => ({
|
||||
ForkopShellMethods: {
|
||||
TachyonShellMethods: {
|
||||
getClashApiProxyLatency: mocks.getClashApiProxyLatency,
|
||||
getClashApiGroupLatency: mocks.getClashApiGroupLatency,
|
||||
},
|
||||
|
||||
@@ -77,8 +77,8 @@ export const initialDiagnosticStore: Pick<
|
||||
loading: true,
|
||||
loaded: false,
|
||||
providerInfoLoaded: false,
|
||||
forkop_version: 'loading',
|
||||
forkop_latest_version: 'loading',
|
||||
tachyon_version: 'loading',
|
||||
tachyon_latest_version: 'loading',
|
||||
luci_app_version: 'loading',
|
||||
sing_box_version: 'loading',
|
||||
sing_box_extended: 0,
|
||||
@@ -124,8 +124,8 @@ export const initialDiagnosticStore: Pick<
|
||||
diagnosticsRunAction: { loading: false },
|
||||
diagnosticsChecks: getDiagnosticsChecks(_('Not running')),
|
||||
updatesActions: {
|
||||
forkopCheck: { loading: false },
|
||||
forkopInstall: { loading: false },
|
||||
tachyonCheck: { loading: false },
|
||||
tachyonInstall: { loading: false },
|
||||
singBoxCheck: { loading: false },
|
||||
singBoxInstall: { loading: false },
|
||||
singBoxInstallExtended: { loading: false },
|
||||
@@ -143,7 +143,7 @@ export const initialDiagnosticStore: Pick<
|
||||
byedpiRemove: { loading: false },
|
||||
},
|
||||
updatesChecks: {
|
||||
forkop: { status: null, latest_version: '', release_url: '' },
|
||||
tachyon: { status: null, latest_version: '', release_url: '' },
|
||||
sing_box: { status: null, latest_version: '', release_url: '' },
|
||||
zapret: { status: null, latest_version: '', release_url: '' },
|
||||
zapret2: { status: null, latest_version: '', release_url: '' },
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { StoreType } from '../../services';
|
||||
import type { DiagnosticsProviderOptions } from './diagnostic.store';
|
||||
import { DIAGNOSTICS_CHECKS } from './checks/contstants';
|
||||
|
||||
const DIAGNOSTIC_RUN_STORAGE_KEY = 'forkop:diagnostic-run:v1';
|
||||
const DIAGNOSTIC_RUN_STORAGE_KEY = 'tachyon:diagnostic-run:v1';
|
||||
const DIAGNOSTIC_RUN_TTL_MS = 30 * 60 * 1000;
|
||||
const CHECK_STATES = ['loading', 'warning', 'success', 'error', 'skipped'];
|
||||
const CHECK_ITEM_STATES = ['error', 'warning', 'success'];
|
||||
|
||||
@@ -28,7 +28,7 @@ const SING_BOX_MASKED_KEYS = new Set([
|
||||
'source_ip_cidr',
|
||||
]);
|
||||
|
||||
const FORKOP_MASK_AFTER_TOKEN = [
|
||||
const TACHYON_MASK_AFTER_TOKEN = [
|
||||
'option proxy_string',
|
||||
'option subscription_url',
|
||||
'list subscription_urls',
|
||||
@@ -47,7 +47,7 @@ const FORKOP_MASK_AFTER_TOKEN = [
|
||||
'option yacd_secret_key',
|
||||
];
|
||||
|
||||
const FORKOP_MASK_AFTER_TOKEN_SPACE = [
|
||||
const TACHYON_MASK_AFTER_TOKEN_SPACE = [
|
||||
'option outbound_json',
|
||||
'list domain',
|
||||
'list domain_suffix',
|
||||
@@ -149,11 +149,11 @@ function maskOptionPath(line: string, token: string) {
|
||||
function maskGlobalCheckLine(line: string) {
|
||||
let maskedLine = line;
|
||||
|
||||
for (const token of FORKOP_MASK_AFTER_TOKEN) {
|
||||
for (const token of TACHYON_MASK_AFTER_TOKEN) {
|
||||
maskedLine = maskAfterToken(maskedLine, token);
|
||||
}
|
||||
|
||||
for (const token of FORKOP_MASK_AFTER_TOKEN_SPACE) {
|
||||
for (const token of TACHYON_MASK_AFTER_TOKEN_SPACE) {
|
||||
maskedLine = maskAfterTokenSpace(maskedLine, token);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,14 +32,14 @@ import {
|
||||
renderRunAction,
|
||||
renderSystemInfo,
|
||||
} from './partials';
|
||||
import { ForkopShellMethods } from '../../methods';
|
||||
import { TachyonShellMethods } from '../../methods';
|
||||
import { fetchServicesInfo } from '../../fetchers/fetchServicesInfo';
|
||||
import { normalizeCompiledVersion } from '../../../helpers/normalizeCompiledVersion';
|
||||
import { renderModal } from '../../../partials';
|
||||
import { FORKOP_LUCI_APP_VERSION } from '../../../constants';
|
||||
import { TACHYON_LUCI_APP_VERSION } from '../../../constants';
|
||||
import { renderWikiDisclaimer } from './partials/renderWikiDisclaimer';
|
||||
import { runSectionsCheck } from './checks/runSectionsCheck';
|
||||
import { Forkop } from '../../types';
|
||||
import { Tachyon } from '../../types';
|
||||
import {
|
||||
getAvailableActionsDisabledState,
|
||||
getServiceTransition,
|
||||
@@ -156,11 +156,11 @@ function isLocalMutatingServiceActionLoading() {
|
||||
function isMutatingServiceActionLoading() {
|
||||
return (
|
||||
isLocalMutatingServiceActionLoading() ||
|
||||
isServiceTransitionStatus(store.get().servicesInfoWidget.data.forkopStatus)
|
||||
isServiceTransitionStatus(store.get().servicesInfoWidget.data.tachyonStatus)
|
||||
);
|
||||
}
|
||||
|
||||
function getForkopStatusText(running: boolean, enabled: boolean) {
|
||||
function getTachyonStatusText(running: boolean, enabled: boolean) {
|
||||
if (running) {
|
||||
return enabled ? 'running & enabled' : 'running but disabled';
|
||||
}
|
||||
@@ -168,9 +168,9 @@ function getForkopStatusText(running: boolean, enabled: boolean) {
|
||||
return enabled ? 'stopped but enabled' : 'stopped & disabled';
|
||||
}
|
||||
|
||||
function setDisplayedForkopRunning(running: boolean) {
|
||||
function setDisplayedTachyonRunning(running: boolean) {
|
||||
const servicesInfoWidget = store.get().servicesInfoWidget;
|
||||
const enabled = Boolean(servicesInfoWidget.data.forkopEnabled);
|
||||
const enabled = Boolean(servicesInfoWidget.data.tachyonEnabled);
|
||||
|
||||
store.set({
|
||||
servicesInfoWidget: {
|
||||
@@ -178,8 +178,8 @@ function setDisplayedForkopRunning(running: boolean) {
|
||||
loading: false,
|
||||
data: {
|
||||
...servicesInfoWidget.data,
|
||||
forkopRunning: running ? 1 : 0,
|
||||
forkopStatus: getForkopStatusText(running, enabled),
|
||||
tachyonRunning: running ? 1 : 0,
|
||||
tachyonStatus: getTachyonStatusText(running, enabled),
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -232,17 +232,17 @@ async function refreshDiagnosticServicesInfo({
|
||||
return promise;
|
||||
}
|
||||
|
||||
async function waitForForkopRunningState(expectedRunning: boolean) {
|
||||
async function waitForTachyonRunningState(expectedRunning: boolean) {
|
||||
const startedAt = Date.now();
|
||||
|
||||
while (Date.now() - startedAt < SERVICE_ACTION_STATUS_TIMEOUT_MS) {
|
||||
await refreshDiagnosticServicesInfo({ force: true, allowInactive: true });
|
||||
|
||||
const forkopRunning = Boolean(
|
||||
store.get().servicesInfoWidget.data.forkopRunning,
|
||||
const tachyonRunning = Boolean(
|
||||
store.get().servicesInfoWidget.data.tachyonRunning,
|
||||
);
|
||||
|
||||
if (forkopRunning === expectedRunning) {
|
||||
if (tachyonRunning === expectedRunning) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -274,13 +274,13 @@ function stopServiceActionStateWatcher() {
|
||||
}
|
||||
|
||||
function isVisibleServiceRuntimeAction(
|
||||
action: Forkop.ServiceActionState['action'],
|
||||
action: Tachyon.ServiceActionState['action'],
|
||||
): action is ServiceRuntimeAction {
|
||||
return action === 'restart' || action === 'start' || action === 'stop';
|
||||
}
|
||||
|
||||
function setServiceActionStateLoading(
|
||||
state: Forkop.ServiceActionState,
|
||||
state: Tachyon.ServiceActionState,
|
||||
loading: boolean,
|
||||
) {
|
||||
if (!isVisibleServiceRuntimeAction(state.action)) {
|
||||
@@ -290,7 +290,7 @@ function setServiceActionStateLoading(
|
||||
setDiagnosticActionLoading(state.action, loading);
|
||||
}
|
||||
|
||||
async function followServiceActionState(state: Forkop.ServiceActionState) {
|
||||
async function followServiceActionState(state: Tachyon.ServiceActionState) {
|
||||
const jobId = state.job_id;
|
||||
|
||||
if (!jobId || followedServiceActionJobs.has(jobId)) {
|
||||
@@ -308,7 +308,7 @@ async function followServiceActionState(state: Forkop.ServiceActionState) {
|
||||
|
||||
try {
|
||||
if (state.running) {
|
||||
await ForkopShellMethods.waitServiceActionJob(jobId);
|
||||
await TachyonShellMethods.waitServiceActionJob(jobId);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('[DIAGNOSTIC]', 'followServiceActionState failed', error);
|
||||
@@ -316,13 +316,13 @@ async function followServiceActionState(state: Forkop.ServiceActionState) {
|
||||
handledServiceActionJobs.add(jobId);
|
||||
setServiceActionStateLoading(state, false);
|
||||
await refreshDiagnosticServicesInfo({ force: true, allowInactive: true });
|
||||
void ForkopShellMethods.uiActionAck('service', jobId);
|
||||
void TachyonShellMethods.uiActionAck('service', jobId);
|
||||
followedServiceActionJobs.delete(jobId);
|
||||
resetDiagnosticsChecks();
|
||||
}
|
||||
}
|
||||
|
||||
function followServiceActionsFromUiState(uiState?: Forkop.UiState) {
|
||||
function followServiceActionsFromUiState(uiState?: Tachyon.UiState) {
|
||||
if (!uiState) {
|
||||
return;
|
||||
}
|
||||
@@ -411,10 +411,10 @@ async function fetchDiagnosticsProviderInfo({
|
||||
|
||||
const [zapretRuntime, zapret2Runtime, byedpiRuntime, inboundsConfig] =
|
||||
await Promise.all([
|
||||
ForkopShellMethods.checkZapretRuntime(),
|
||||
ForkopShellMethods.checkZapret2Runtime(),
|
||||
ForkopShellMethods.checkByedpiRuntime(),
|
||||
ForkopShellMethods.checkInboundsConfig(),
|
||||
TachyonShellMethods.checkZapretRuntime(),
|
||||
TachyonShellMethods.checkZapret2Runtime(),
|
||||
TachyonShellMethods.checkByedpiRuntime(),
|
||||
TachyonShellMethods.checkInboundsConfig(),
|
||||
]);
|
||||
|
||||
if (requestId !== latestProviderInfoRequestId) {
|
||||
@@ -532,7 +532,7 @@ function renderDiagnosticRunActionWidget() {
|
||||
const providerInfoLoaded =
|
||||
store.get().diagnosticsSystemInfo.providerInfoLoaded;
|
||||
const servicesInfoWidget = store.get().servicesInfoWidget;
|
||||
const forkopRunning = Boolean(servicesInfoWidget.data.forkopRunning);
|
||||
const tachyonRunning = Boolean(servicesInfoWidget.data.tachyonRunning);
|
||||
const container = document.getElementById('fkp_diagnostic-page-run-check');
|
||||
|
||||
const renderedAction = renderRunAction({
|
||||
@@ -540,7 +540,7 @@ function renderDiagnosticRunActionWidget() {
|
||||
disabled: shouldDisableDiagnosticRunAction({
|
||||
providerInfoLoaded,
|
||||
servicesInfoLoading: servicesInfoWidget.loading,
|
||||
forkopRunning,
|
||||
tachyonRunning,
|
||||
mutatingServiceActionLoading: isMutatingServiceActionLoading(),
|
||||
}),
|
||||
click: () => runChecks(),
|
||||
@@ -566,11 +566,11 @@ async function handleServiceRuntimeAction({
|
||||
let delegatedToWatcher = false;
|
||||
|
||||
if (optimisticRunning !== undefined) {
|
||||
setDisplayedForkopRunning(optimisticRunning);
|
||||
setDisplayedTachyonRunning(optimisticRunning);
|
||||
}
|
||||
|
||||
try {
|
||||
const startResponse = await ForkopShellMethods.serviceActionStart(action);
|
||||
const startResponse = await TachyonShellMethods.serviceActionStart(action);
|
||||
|
||||
if (!startResponse.success) {
|
||||
throw new Error(startResponse.error);
|
||||
@@ -584,7 +584,7 @@ async function handleServiceRuntimeAction({
|
||||
|
||||
followedServiceActionJobs.add(jobId);
|
||||
ownsJobFollow = true;
|
||||
const result = await ForkopShellMethods.waitServiceActionJob(jobId);
|
||||
const result = await TachyonShellMethods.waitServiceActionJob(jobId);
|
||||
|
||||
if (!result.success) {
|
||||
throw new Error(result.error);
|
||||
@@ -594,7 +594,7 @@ async function handleServiceRuntimeAction({
|
||||
throw new Error(result.data.message || _('Service action failed'));
|
||||
}
|
||||
|
||||
await waitForForkopRunningState(expectedRunning);
|
||||
await waitForTachyonRunningState(expectedRunning);
|
||||
} catch (e) {
|
||||
logger.error('[DIAGNOSTIC]', `handleServiceRuntimeAction(${action})`, e);
|
||||
} finally {
|
||||
@@ -607,7 +607,7 @@ async function handleServiceRuntimeAction({
|
||||
await refreshDiagnosticServicesInfo({ force: true, allowInactive: true });
|
||||
if (jobId) {
|
||||
handledServiceActionJobs.add(jobId);
|
||||
void ForkopShellMethods.uiActionAck('service', jobId);
|
||||
void TachyonShellMethods.uiActionAck('service', jobId);
|
||||
}
|
||||
resetDiagnosticsChecks();
|
||||
}
|
||||
@@ -640,7 +640,7 @@ async function handleEnable() {
|
||||
setDiagnosticActionLoading('enable', true);
|
||||
|
||||
try {
|
||||
await ForkopShellMethods.enable();
|
||||
await TachyonShellMethods.enable();
|
||||
} catch (e) {
|
||||
logger.error('[DIAGNOSTIC]', 'handleEnable - e', e);
|
||||
} finally {
|
||||
@@ -656,7 +656,7 @@ async function handleDisable() {
|
||||
setDiagnosticActionLoading('disable', true);
|
||||
|
||||
try {
|
||||
await ForkopShellMethods.disable();
|
||||
await TachyonShellMethods.disable();
|
||||
} catch (e) {
|
||||
logger.error('[DIAGNOSTIC]', 'handleDisable - e', e);
|
||||
} finally {
|
||||
@@ -672,7 +672,7 @@ async function handleShowGlobalCheck() {
|
||||
setDiagnosticActionLoading('globalCheck', true);
|
||||
|
||||
try {
|
||||
const globalCheck = await ForkopShellMethods.globalCheck(false);
|
||||
const globalCheck = await TachyonShellMethods.globalCheck(false);
|
||||
|
||||
if (globalCheck.success) {
|
||||
const rawGlobalCheckText = (globalCheck.data as string) ?? '';
|
||||
@@ -700,11 +700,11 @@ async function handleViewLogs() {
|
||||
setDiagnosticActionLoading('viewLogs', true);
|
||||
|
||||
try {
|
||||
const viewLogs = await ForkopShellMethods.checkLogs();
|
||||
const viewLogs = await TachyonShellMethods.checkLogs();
|
||||
|
||||
if (viewLogs.success) {
|
||||
const getLatestLogs = async () => {
|
||||
const latestLogs = await ForkopShellMethods.checkLogs();
|
||||
const latestLogs = await TachyonShellMethods.checkLogs();
|
||||
|
||||
if (!latestLogs.success) {
|
||||
throw latestLogs;
|
||||
@@ -737,7 +737,7 @@ async function handleShowSingBoxConfig() {
|
||||
setDiagnosticActionLoading('showSingBoxConfig', true);
|
||||
|
||||
try {
|
||||
const showSingBoxConfig = await ForkopShellMethods.showSingBoxConfig(false);
|
||||
const showSingBoxConfig = await TachyonShellMethods.showSingBoxConfig(false);
|
||||
|
||||
if (showSingBoxConfig.success) {
|
||||
const rawSingBoxConfigText = stringifySingBoxConfig(
|
||||
@@ -799,10 +799,10 @@ function renderDiagnosticAvailableActionsWidget() {
|
||||
const servicesInfoWidget = store.get().servicesInfoWidget;
|
||||
logger.debug('[DIAGNOSTIC]', 'renderDiagnosticAvailableActionsWidget');
|
||||
|
||||
const forkopEnabled = Boolean(servicesInfoWidget.data.forkopEnabled);
|
||||
const forkopRunning = Boolean(servicesInfoWidget.data.forkopRunning);
|
||||
const tachyonEnabled = Boolean(servicesInfoWidget.data.tachyonEnabled);
|
||||
const tachyonRunning = Boolean(servicesInfoWidget.data.tachyonRunning);
|
||||
const serviceTransition = getServiceTransition(
|
||||
servicesInfoWidget.data.forkopStatus,
|
||||
servicesInfoWidget.data.tachyonStatus,
|
||||
);
|
||||
const restartLoading =
|
||||
diagnosticsActions.restart.loading || serviceTransition.restarting;
|
||||
@@ -824,13 +824,13 @@ function renderDiagnosticAvailableActionsWidget() {
|
||||
componentActionLoading,
|
||||
});
|
||||
const startVisible = shouldShowStartAction({
|
||||
forkopRunning,
|
||||
tachyonRunning,
|
||||
restartLoading,
|
||||
startLoading,
|
||||
stopLoading,
|
||||
});
|
||||
const stopVisible = shouldShowStopAction({
|
||||
forkopRunning,
|
||||
tachyonRunning,
|
||||
restartLoading,
|
||||
startLoading,
|
||||
stopLoading,
|
||||
@@ -842,7 +842,7 @@ function renderDiagnosticAvailableActionsWidget() {
|
||||
restart: {
|
||||
loading: restartLoading,
|
||||
visible: shouldShowRestartAction({
|
||||
forkopRunning,
|
||||
tachyonRunning,
|
||||
restartLoading,
|
||||
startLoading,
|
||||
stopLoading,
|
||||
@@ -864,13 +864,13 @@ function renderDiagnosticAvailableActionsWidget() {
|
||||
},
|
||||
enable: {
|
||||
loading: diagnosticsActions.enable.loading,
|
||||
visible: !forkopEnabled,
|
||||
visible: !tachyonEnabled,
|
||||
onClick: handleEnable,
|
||||
disabled: serviceControlsDisabled,
|
||||
},
|
||||
disable: {
|
||||
loading: diagnosticsActions.disable.loading,
|
||||
visible: forkopEnabled,
|
||||
visible: tachyonEnabled,
|
||||
onClick: handleDisable,
|
||||
disabled: serviceControlsDisabled,
|
||||
},
|
||||
@@ -907,12 +907,12 @@ function renderDiagnosticSystemInfoWidget() {
|
||||
|
||||
const items = [
|
||||
{
|
||||
key: 'Forkop',
|
||||
value: normalizeCompiledVersion(diagnosticsSystemInfo.forkop_version),
|
||||
key: 'Tachyon',
|
||||
value: normalizeCompiledVersion(diagnosticsSystemInfo.tachyon_version),
|
||||
},
|
||||
{
|
||||
key: 'Luci App',
|
||||
value: normalizeCompiledVersion(FORKOP_LUCI_APP_VERSION),
|
||||
value: normalizeCompiledVersion(TACHYON_LUCI_APP_VERSION),
|
||||
},
|
||||
{
|
||||
key: 'Sing-box',
|
||||
|
||||
@@ -46,7 +46,7 @@ export function renderAvailableActions({
|
||||
classNames: ['cbi-button-apply'],
|
||||
onClick: restart.onClick,
|
||||
icon: renderRotateCcwIcon24,
|
||||
text: _('Restart Forkop'),
|
||||
text: _('Restart Tachyon'),
|
||||
loading: restart.loading,
|
||||
disabled: restart.disabled,
|
||||
}),
|
||||
@@ -56,7 +56,7 @@ export function renderAvailableActions({
|
||||
classNames: ['cbi-button-remove'],
|
||||
onClick: stop.onClick,
|
||||
icon: renderCircleStopIcon24,
|
||||
text: _('Stop Forkop'),
|
||||
text: _('Stop Tachyon'),
|
||||
loading: stop.loading,
|
||||
disabled: stop.disabled,
|
||||
}),
|
||||
@@ -66,7 +66,7 @@ export function renderAvailableActions({
|
||||
classNames: ['cbi-button-save'],
|
||||
onClick: start.onClick,
|
||||
icon: renderCirclePlayIcon24,
|
||||
text: _('Start Forkop'),
|
||||
text: _('Start Tachyon'),
|
||||
loading: start.loading,
|
||||
disabled: start.disabled,
|
||||
}),
|
||||
|
||||
@@ -59,18 +59,18 @@ export function shouldResetDiagnosticsChecks({
|
||||
export function shouldDisableDiagnosticRunAction({
|
||||
providerInfoLoaded,
|
||||
servicesInfoLoading,
|
||||
forkopRunning,
|
||||
tachyonRunning,
|
||||
mutatingServiceActionLoading,
|
||||
}: {
|
||||
providerInfoLoaded: boolean;
|
||||
servicesInfoLoading: boolean;
|
||||
forkopRunning: boolean;
|
||||
tachyonRunning: boolean;
|
||||
mutatingServiceActionLoading: boolean;
|
||||
}) {
|
||||
return (
|
||||
!providerInfoLoaded ||
|
||||
servicesInfoLoading ||
|
||||
!forkopRunning ||
|
||||
!tachyonRunning ||
|
||||
mutatingServiceActionLoading
|
||||
);
|
||||
}
|
||||
@@ -100,43 +100,43 @@ export function getAvailableActionsDisabledState({
|
||||
}
|
||||
|
||||
export function shouldShowRestartAction({
|
||||
forkopRunning,
|
||||
tachyonRunning,
|
||||
restartLoading,
|
||||
startLoading,
|
||||
stopLoading,
|
||||
}: {
|
||||
forkopRunning: boolean;
|
||||
tachyonRunning: boolean;
|
||||
restartLoading: boolean;
|
||||
startLoading: boolean;
|
||||
stopLoading: boolean;
|
||||
}) {
|
||||
return restartLoading || (forkopRunning && !startLoading && !stopLoading);
|
||||
return restartLoading || (tachyonRunning && !startLoading && !stopLoading);
|
||||
}
|
||||
|
||||
export function shouldShowStartAction({
|
||||
forkopRunning,
|
||||
tachyonRunning,
|
||||
restartLoading,
|
||||
startLoading,
|
||||
stopLoading,
|
||||
}: {
|
||||
forkopRunning: boolean;
|
||||
tachyonRunning: boolean;
|
||||
restartLoading: boolean;
|
||||
startLoading: boolean;
|
||||
stopLoading: boolean;
|
||||
}) {
|
||||
return startLoading || (!restartLoading && !forkopRunning && !stopLoading);
|
||||
return startLoading || (!restartLoading && !tachyonRunning && !stopLoading);
|
||||
}
|
||||
|
||||
export function shouldShowStopAction({
|
||||
forkopRunning,
|
||||
tachyonRunning,
|
||||
restartLoading,
|
||||
startLoading,
|
||||
stopLoading,
|
||||
}: {
|
||||
forkopRunning: boolean;
|
||||
tachyonRunning: boolean;
|
||||
restartLoading: boolean;
|
||||
startLoading: boolean;
|
||||
stopLoading: boolean;
|
||||
}) {
|
||||
return stopLoading || restartLoading || (forkopRunning && !startLoading);
|
||||
return stopLoading || restartLoading || (tachyonRunning && !startLoading);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// language=CSS
|
||||
import { FORKOP_UCI_PACKAGE as FORKOP_CBI_PREFIX } from '../../../constants';
|
||||
import { TACHYON_UCI_PACKAGE as TACHYON_CBI_PREFIX } from '../../../constants';
|
||||
|
||||
export const styles = `
|
||||
|
||||
#cbi-${FORKOP_CBI_PREFIX}-diagnostic-_mount_node > div {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-diagnostic-_mount_node > div {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#cbi-${FORKOP_CBI_PREFIX}-diagnostic > h3 {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-diagnostic > h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ describe('diagnostic run persistence', () => {
|
||||
|
||||
it('removes invalid snapshots', () => {
|
||||
const storage = new MemoryStorage();
|
||||
storage.setItem('forkop:diagnostic-run:v1', '{broken');
|
||||
storage.setItem('tachyon:diagnostic-run:v1', '{broken');
|
||||
|
||||
expect(readPersistedDiagnosticRun(storage)).toBeNull();
|
||||
expect(storage.length).toBe(0);
|
||||
@@ -118,7 +118,7 @@ describe('diagnostic run persistence', () => {
|
||||
const storage = new MemoryStorage();
|
||||
|
||||
storage.setItem(
|
||||
'forkop:diagnostic-run:v1',
|
||||
'tachyon:diagnostic-run:v1',
|
||||
JSON.stringify({
|
||||
nextRunnerIndex: 0,
|
||||
providerOptions: {},
|
||||
@@ -144,7 +144,7 @@ describe('diagnostic run persistence', () => {
|
||||
const storage = new MemoryStorage();
|
||||
|
||||
storage.setItem(
|
||||
'forkop:diagnostic-run:v1',
|
||||
'tachyon:diagnostic-run:v1',
|
||||
JSON.stringify({
|
||||
nextRunnerIndex: 0,
|
||||
providerOptions: {},
|
||||
|
||||
@@ -94,7 +94,7 @@ describe('diagnostic service transitions', () => {
|
||||
it('shows restart while the service is running even when autostart is disabled', () => {
|
||||
expect(
|
||||
shouldShowRestartAction({
|
||||
forkopRunning: true,
|
||||
tachyonRunning: true,
|
||||
restartLoading: false,
|
||||
startLoading: false,
|
||||
stopLoading: false,
|
||||
@@ -102,7 +102,7 @@ describe('diagnostic service transitions', () => {
|
||||
).toBe(true);
|
||||
expect(
|
||||
shouldShowRestartAction({
|
||||
forkopRunning: false,
|
||||
tachyonRunning: false,
|
||||
restartLoading: false,
|
||||
startLoading: false,
|
||||
stopLoading: false,
|
||||
@@ -110,7 +110,7 @@ describe('diagnostic service transitions', () => {
|
||||
).toBe(false);
|
||||
expect(
|
||||
shouldShowRestartAction({
|
||||
forkopRunning: false,
|
||||
tachyonRunning: false,
|
||||
restartLoading: true,
|
||||
startLoading: false,
|
||||
stopLoading: false,
|
||||
@@ -121,7 +121,7 @@ describe('diagnostic service transitions', () => {
|
||||
it('does not show restart from transient running state while start or stop is active', () => {
|
||||
expect(
|
||||
shouldShowRestartAction({
|
||||
forkopRunning: true,
|
||||
tachyonRunning: true,
|
||||
restartLoading: false,
|
||||
startLoading: true,
|
||||
stopLoading: false,
|
||||
@@ -129,7 +129,7 @@ describe('diagnostic service transitions', () => {
|
||||
).toBe(false);
|
||||
expect(
|
||||
shouldShowRestartAction({
|
||||
forkopRunning: true,
|
||||
tachyonRunning: true,
|
||||
restartLoading: false,
|
||||
startLoading: false,
|
||||
stopLoading: true,
|
||||
@@ -142,7 +142,7 @@ describe('diagnostic service transitions', () => {
|
||||
shouldDisableDiagnosticRunAction({
|
||||
providerInfoLoaded: true,
|
||||
servicesInfoLoading: false,
|
||||
forkopRunning: true,
|
||||
tachyonRunning: true,
|
||||
mutatingServiceActionLoading: false,
|
||||
}),
|
||||
).toBe(false);
|
||||
@@ -150,7 +150,7 @@ describe('diagnostic service transitions', () => {
|
||||
shouldDisableDiagnosticRunAction({
|
||||
providerInfoLoaded: true,
|
||||
servicesInfoLoading: false,
|
||||
forkopRunning: false,
|
||||
tachyonRunning: false,
|
||||
mutatingServiceActionLoading: false,
|
||||
}),
|
||||
).toBe(true);
|
||||
@@ -159,7 +159,7 @@ describe('diagnostic service transitions', () => {
|
||||
it('detects running component actions', () => {
|
||||
expect(
|
||||
hasComponentActionLoading({
|
||||
forkopCheck: { loading: false },
|
||||
tachyonCheck: { loading: false },
|
||||
zapretInstall: { loading: true },
|
||||
}),
|
||||
).toBe(true);
|
||||
@@ -196,7 +196,7 @@ describe('diagnostic service transitions', () => {
|
||||
it('keeps the lower service action visible while restart is running', () => {
|
||||
expect(
|
||||
shouldShowStopAction({
|
||||
forkopRunning: false,
|
||||
tachyonRunning: false,
|
||||
restartLoading: true,
|
||||
startLoading: false,
|
||||
stopLoading: false,
|
||||
@@ -204,7 +204,7 @@ describe('diagnostic service transitions', () => {
|
||||
).toBe(true);
|
||||
expect(
|
||||
shouldShowStartAction({
|
||||
forkopRunning: false,
|
||||
tachyonRunning: false,
|
||||
restartLoading: true,
|
||||
startLoading: false,
|
||||
stopLoading: false,
|
||||
@@ -215,7 +215,7 @@ describe('diagnostic service transitions', () => {
|
||||
it('keeps the normal start and stop visibility outside restart', () => {
|
||||
expect(
|
||||
shouldShowStartAction({
|
||||
forkopRunning: false,
|
||||
tachyonRunning: false,
|
||||
restartLoading: false,
|
||||
startLoading: false,
|
||||
stopLoading: false,
|
||||
@@ -223,7 +223,7 @@ describe('diagnostic service transitions', () => {
|
||||
).toBe(true);
|
||||
expect(
|
||||
shouldShowStopAction({
|
||||
forkopRunning: false,
|
||||
tachyonRunning: false,
|
||||
restartLoading: false,
|
||||
startLoading: false,
|
||||
stopLoading: false,
|
||||
@@ -231,7 +231,7 @@ describe('diagnostic service transitions', () => {
|
||||
).toBe(false);
|
||||
expect(
|
||||
shouldShowStopAction({
|
||||
forkopRunning: true,
|
||||
tachyonRunning: true,
|
||||
restartLoading: false,
|
||||
startLoading: false,
|
||||
stopLoading: false,
|
||||
|
||||
@@ -7,11 +7,11 @@ import {
|
||||
renderSearchIcon24,
|
||||
renderXIcon24,
|
||||
} from '../../../icons';
|
||||
import { CustomForkopMethods, ForkopShellMethods } from '../../methods';
|
||||
import { CustomTachyonMethods, TachyonShellMethods } from '../../methods';
|
||||
import { getOutboundTagBySection } from '../../runtimeTags';
|
||||
import { getClashApiSecret } from '../../methods/custom/getClashApiSecret';
|
||||
import { logger, socket, store, StoreType } from '../../services';
|
||||
import { Forkop } from '../../types';
|
||||
import { Tachyon } from '../../types';
|
||||
import {
|
||||
getCachedRuntimeUiState,
|
||||
refreshRuntimeUiState,
|
||||
@@ -127,7 +127,7 @@ function getListValues(value?: string[] | string) {
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
function getUrlTestIds(section: Forkop.ConfigSection) {
|
||||
function getUrlTestIds(section: Tachyon.ConfigSection) {
|
||||
const values = getListValues(section.urltests);
|
||||
return values.length
|
||||
? values
|
||||
@@ -167,11 +167,11 @@ function formatEndpoint(address?: string, port?: string | number): string {
|
||||
return `${normalizedAddress}:${normalizedPort}`;
|
||||
}
|
||||
|
||||
function getDisplayName(section: Forkop.ConfigSection) {
|
||||
function getDisplayName(section: Tachyon.ConfigSection) {
|
||||
return normalizeString(section.label) || section['.name'];
|
||||
}
|
||||
|
||||
function buildRouteDisplayNames(sections: Forkop.ConfigSection[]) {
|
||||
function buildRouteDisplayNames(sections: Tachyon.ConfigSection[]) {
|
||||
const map: Record<string, string> = {
|
||||
'bypass-out': 'Bypass',
|
||||
'direct-out': 'direct',
|
||||
@@ -923,7 +923,7 @@ function renderConnections(options: { force?: boolean } = {}) {
|
||||
container.replaceChildren(
|
||||
renderConnectionsTable([], {
|
||||
text: _(
|
||||
'Forkop service is stopped. Start the service to display connections.',
|
||||
'Tachyon service is stopped. Start the service to display connections.',
|
||||
),
|
||||
}),
|
||||
);
|
||||
@@ -1207,7 +1207,7 @@ async function closeConnection(connectionId: string) {
|
||||
|
||||
try {
|
||||
const response =
|
||||
await ForkopShellMethods.closeClashApiConnection(connectionId);
|
||||
await TachyonShellMethods.closeClashApiConnection(connectionId);
|
||||
|
||||
if (!response.success) {
|
||||
showToast(_('Failed to close connection'), 'error');
|
||||
@@ -1241,7 +1241,7 @@ async function closeAllConnections() {
|
||||
renderControls();
|
||||
|
||||
try {
|
||||
const response = await ForkopShellMethods.closeAllClashApiConnections();
|
||||
const response = await TachyonShellMethods.closeAllClashApiConnections();
|
||||
|
||||
if (!response.success) {
|
||||
showToast(_('Failed to close connections'), 'error');
|
||||
@@ -1343,7 +1343,7 @@ async function loadLocalDevices() {
|
||||
|
||||
async function loadRouteDisplayNames() {
|
||||
try {
|
||||
buildRouteDisplayNames(await CustomForkopMethods.getConfigSections());
|
||||
buildRouteDisplayNames(await CustomTachyonMethods.getConfigSections());
|
||||
} catch (error) {
|
||||
logger.warn('[MONITORING]', 'loadRouteDisplayNames: failed', error);
|
||||
buildRouteDisplayNames([]);
|
||||
@@ -1367,7 +1367,7 @@ async function pollConnectionsSnapshot() {
|
||||
pollingConnections = true;
|
||||
|
||||
try {
|
||||
const response = await ForkopShellMethods.getClashApiConnections();
|
||||
const response = await TachyonShellMethods.getClashApiConnections();
|
||||
|
||||
if (
|
||||
!monitoringMounted ||
|
||||
@@ -1532,7 +1532,7 @@ function watchServiceState() {
|
||||
getServiceAvailability({
|
||||
loading: false,
|
||||
failed: false,
|
||||
running: uiState.service.forkop.running,
|
||||
running: uiState.service.tachyon.running,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
// language=CSS
|
||||
import { FORKOP_UCI_PACKAGE as FORKOP_CBI_PREFIX } from '../../../constants';
|
||||
import { TACHYON_UCI_PACKAGE as TACHYON_CBI_PREFIX } from '../../../constants';
|
||||
|
||||
export const styles = `
|
||||
#cbi-${FORKOP_CBI_PREFIX}-monitoring-_mount_node {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-monitoring-_mount_node {
|
||||
margin: 16px 0 22px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#cbi-${FORKOP_CBI_PREFIX}-monitoring-_mount_node > .cbi-value-title {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-monitoring-_mount_node > .cbi-value-title {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#cbi-${FORKOP_CBI_PREFIX}-monitoring-_mount_node > .cbi-value-field {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-monitoring-_mount_node > .cbi-value-field {
|
||||
margin-left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#cbi-${FORKOP_CBI_PREFIX}-monitoring-_mount_node > div {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-monitoring-_mount_node > div {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#cbi-${FORKOP_CBI_PREFIX}-monitoring > h3 {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-monitoring > h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { Forkop } from '../../types';
|
||||
import type { Tachyon } from '../../types';
|
||||
|
||||
export function shouldPreserveCompletedCheckResultOnNextMount({
|
||||
action,
|
||||
mounted,
|
||||
}: {
|
||||
action: Forkop.ComponentAction;
|
||||
action: Tachyon.ComponentAction;
|
||||
mounted: boolean;
|
||||
}) {
|
||||
return action === 'check_update' && !mounted;
|
||||
@@ -27,7 +27,7 @@ export function shouldResetCheckResultsOnMount({
|
||||
}
|
||||
|
||||
export function shouldRefreshComponentStateBeforeRender(
|
||||
uiState?: Pick<Forkop.UiState, 'actions'>,
|
||||
uiState?: Pick<Tachyon.UiState, 'actions'>,
|
||||
) {
|
||||
return Boolean(
|
||||
uiState?.actions.component.some((state) => state.running === true),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Forkop } from '../../types';
|
||||
import type { Tachyon } from '../../types';
|
||||
|
||||
export function shouldApplyCompletedComponentActionResult(
|
||||
result: Pick<Forkop.ComponentActionResult, 'action'>,
|
||||
result: Pick<Tachyon.ComponentActionResult, 'action'>,
|
||||
notify: boolean,
|
||||
) {
|
||||
return result.action !== 'check_update' || notify;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { onMount, preserveScrollForPage } from '../../../helpers';
|
||||
import { FORKOP_ACTION_PROVIDERS_AVAILABILITY_EVENT } from '../../../constants';
|
||||
import { TACHYON_ACTION_PROVIDERS_AVAILABILITY_EVENT } from '../../../constants';
|
||||
import { normalizeCompiledVersion } from '../../../helpers/normalizeCompiledVersion';
|
||||
import { showToast } from '../../../helpers/showToast';
|
||||
import {
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
shouldRefreshComponentStateBeforeRender,
|
||||
shouldResetCheckResultsOnMount,
|
||||
} from './checkResultLifecycle';
|
||||
import { ForkopShellMethods } from '../../methods';
|
||||
import { TachyonShellMethods } from '../../methods';
|
||||
import {
|
||||
logger,
|
||||
markUiActionOwned,
|
||||
@@ -44,20 +44,20 @@ import {
|
||||
refreshRuntimeUiState,
|
||||
subscribeRuntimeUiState,
|
||||
} from '../../services/runtimeUiState.service';
|
||||
import { Forkop } from '../../types';
|
||||
import { Tachyon } from '../../types';
|
||||
|
||||
type UpdateStatus = StoreType['updatesChecks'][Forkop.ComponentName]['status'];
|
||||
type UpdateStatus = StoreType['updatesChecks'][Tachyon.ComponentName]['status'];
|
||||
|
||||
interface ComponentActionButton {
|
||||
key: UpdatesActionKey;
|
||||
text: string;
|
||||
icon: () => SVGSVGElement;
|
||||
component: Forkop.ComponentName;
|
||||
action: Forkop.ComponentAction;
|
||||
component: Tachyon.ComponentName;
|
||||
action: Tachyon.ComponentAction;
|
||||
}
|
||||
|
||||
interface ComponentCard {
|
||||
component: Forkop.ComponentName;
|
||||
component: Tachyon.ComponentName;
|
||||
column: 0 | 1;
|
||||
title: string;
|
||||
version: string;
|
||||
@@ -73,9 +73,9 @@ let updatesMountId = 0;
|
||||
let pageUnloading = false;
|
||||
let preserveCheckResultsOnNextMount = false;
|
||||
let componentUpdateCheckCacheResolved = false;
|
||||
let componentUpdateCheckCacheSnapshot: Forkop.ComponentUpdateCheckCache | null =
|
||||
let componentUpdateCheckCacheSnapshot: Tachyon.ComponentUpdateCheckCache | null =
|
||||
null;
|
||||
let componentUpdateCheckCachePromise: Promise<Forkop.ComponentUpdateCheckCache> | null =
|
||||
let componentUpdateCheckCachePromise: Promise<Tachyon.ComponentUpdateCheckCache> | null =
|
||||
null;
|
||||
let componentActionStateUnsubscribe: (() => void) | null = null;
|
||||
let componentActionStateRefreshPromise: Promise<void> | null = null;
|
||||
@@ -95,13 +95,13 @@ function isNotInstalled(version: string | undefined) {
|
||||
return !version || version === 'not installed';
|
||||
}
|
||||
|
||||
function shouldShowInstallAfterCheck(component: Forkop.ComponentName) {
|
||||
function shouldShowInstallAfterCheck(component: Tachyon.ComponentName) {
|
||||
const status = getVisibleCheckResult(component)?.status;
|
||||
|
||||
return status === 'outdated' || status === 'dev';
|
||||
}
|
||||
|
||||
function getVisibleCheckResult(component: Forkop.ComponentName) {
|
||||
function getVisibleCheckResult(component: Tachyon.ComponentName) {
|
||||
if (
|
||||
!shouldExposeCheckResults({
|
||||
mounted: updatesMounted,
|
||||
@@ -114,7 +114,7 @@ function getVisibleCheckResult(component: Forkop.ComponentName) {
|
||||
return store.get().updatesChecks[component];
|
||||
}
|
||||
|
||||
function getLatestVersion(component: Forkop.ComponentName) {
|
||||
function getLatestVersion(component: Tachyon.ComponentName) {
|
||||
const checkResult = getVisibleCheckResult(component);
|
||||
|
||||
if (!checkResult || !shouldShowInstallAfterCheck(component)) {
|
||||
@@ -124,7 +124,7 @@ function getLatestVersion(component: Forkop.ComponentName) {
|
||||
return checkResult.latest_version || undefined;
|
||||
}
|
||||
|
||||
function getGitHubReleaseUrl(component: Forkop.ComponentName) {
|
||||
function getGitHubReleaseUrl(component: Tachyon.ComponentName) {
|
||||
const checkResult = getVisibleCheckResult(component);
|
||||
|
||||
if (
|
||||
@@ -147,7 +147,7 @@ function isServiceRuntimeActionLoading() {
|
||||
|
||||
return (
|
||||
hasLocalMutatingServiceActionLoading(state.diagnosticsActions) ||
|
||||
isServiceTransitionStatus(state.servicesInfoWidget.data.forkopStatus)
|
||||
isServiceTransitionStatus(state.servicesInfoWidget.data.tachyonStatus)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ function beginComponentAction(button: ComponentActionButton) {
|
||||
}
|
||||
|
||||
function setCheckResult(
|
||||
component: Forkop.ComponentName,
|
||||
component: Tachyon.ComponentName,
|
||||
status: UpdateStatus,
|
||||
latestVersion: string,
|
||||
releaseUrl: string = '',
|
||||
@@ -205,11 +205,11 @@ function setCheckResult(
|
||||
});
|
||||
}
|
||||
|
||||
function resetCheckResult(component: Forkop.ComponentName) {
|
||||
function resetCheckResult(component: Tachyon.ComponentName) {
|
||||
setCheckResult(component, null, '');
|
||||
}
|
||||
|
||||
function applyCachedCheckResults(results: Forkop.ComponentActionResult[]) {
|
||||
function applyCachedCheckResults(results: Tachyon.ComponentActionResult[]) {
|
||||
results.forEach((result) => {
|
||||
const status = result.status || null;
|
||||
|
||||
@@ -233,14 +233,14 @@ function loadComponentUpdateCheckCache({ force = false } = {}) {
|
||||
return componentUpdateCheckCachePromise;
|
||||
}
|
||||
|
||||
const promise = ForkopShellMethods.componentUpdateCheckCache()
|
||||
const promise = TachyonShellMethods.componentUpdateCheckCache()
|
||||
.then((response) =>
|
||||
response.success
|
||||
? response.data
|
||||
: ({
|
||||
enabled: false,
|
||||
results: [],
|
||||
} satisfies Forkop.ComponentUpdateCheckCache),
|
||||
} satisfies Tachyon.ComponentUpdateCheckCache),
|
||||
)
|
||||
.then((cache) => {
|
||||
componentUpdateCheckCacheSnapshot = cache;
|
||||
@@ -262,7 +262,7 @@ function getErrorMessage(error: unknown, fallback: string) {
|
||||
|
||||
async function ackComponentActionJob(jobId: string) {
|
||||
try {
|
||||
const response = await ForkopShellMethods.uiActionAck('component', jobId);
|
||||
const response = await TachyonShellMethods.uiActionAck('component', jobId);
|
||||
|
||||
if (!response.success) {
|
||||
logger.debug('[UPDATES]', 'component action ack failed', response.error);
|
||||
@@ -273,7 +273,7 @@ async function ackComponentActionJob(jobId: string) {
|
||||
}
|
||||
|
||||
function getExpectedLatestVersionForAction(button: ComponentActionButton) {
|
||||
if (button.component !== 'forkop' || button.action !== 'install') {
|
||||
if (button.component !== 'tachyon' || button.action !== 'install') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -306,7 +306,7 @@ function notifyActionProvidersAvailabilityChanged(
|
||||
}
|
||||
|
||||
window.dispatchEvent(
|
||||
new CustomEvent(FORKOP_ACTION_PROVIDERS_AVAILABILITY_EVENT, {
|
||||
new CustomEvent(TACHYON_ACTION_PROVIDERS_AVAILABILITY_EVENT, {
|
||||
detail: {
|
||||
zapretInstalled: Boolean(systemInfo.zapret_installed),
|
||||
zapret2Installed: Boolean(systemInfo.zapret2_installed),
|
||||
@@ -316,20 +316,20 @@ function notifyActionProvidersAvailabilityChanged(
|
||||
);
|
||||
}
|
||||
|
||||
function reloadPageAfterForkopUpdate() {
|
||||
function reloadPageAfterTachyonUpdate() {
|
||||
window.setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 1200);
|
||||
}
|
||||
|
||||
function patchSystemInfoAfterMutation(result: Forkop.ComponentActionResult) {
|
||||
function patchSystemInfoAfterMutation(result: Tachyon.ComponentActionResult) {
|
||||
const systemInfo = store.get().diagnosticsSystemInfo;
|
||||
const nextSystemInfo = { ...systemInfo, loading: false, loaded: true };
|
||||
const version =
|
||||
result.current_version || result.latest_version || _('unknown');
|
||||
|
||||
if (result.component === 'forkop' && result.action === 'install') {
|
||||
nextSystemInfo.forkop_version = version;
|
||||
if (result.component === 'tachyon' && result.action === 'install') {
|
||||
nextSystemInfo.tachyon_version = version;
|
||||
}
|
||||
|
||||
if (result.component === 'sing_box') {
|
||||
@@ -421,7 +421,7 @@ async function applyCompletedComponentAction({
|
||||
notify,
|
||||
}: {
|
||||
key: UpdatesActionKey;
|
||||
result: Forkop.ComponentActionResult;
|
||||
result: Tachyon.ComponentActionResult;
|
||||
notify: boolean;
|
||||
}) {
|
||||
if (result.action === 'check_update') {
|
||||
@@ -466,13 +466,13 @@ async function applyCompletedComponentAction({
|
||||
patchSystemInfoAfterMutation(result);
|
||||
setActionLoading(key, false);
|
||||
|
||||
if (result.component === 'forkop' && result.action === 'install') {
|
||||
if (result.component === 'tachyon' && result.action === 'install') {
|
||||
if (notify && result.message) {
|
||||
showToast(result.message, 'success', 1200);
|
||||
}
|
||||
|
||||
if (notify) {
|
||||
reloadPageAfterForkopUpdate();
|
||||
reloadPageAfterTachyonUpdate();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -487,7 +487,7 @@ async function applyCompletedComponentAction({
|
||||
async function completeComponentActionJob(
|
||||
key: UpdatesActionKey,
|
||||
jobId: string,
|
||||
response: Forkop.MethodResponse<Forkop.ComponentActionResult>,
|
||||
response: Tachyon.MethodResponse<Tachyon.ComponentActionResult>,
|
||||
) {
|
||||
if (pageUnloading) {
|
||||
setActionLoading(key, false);
|
||||
@@ -532,7 +532,7 @@ async function completeComponentActionJob(
|
||||
});
|
||||
}
|
||||
|
||||
async function followComponentActionState(state: Forkop.ComponentActionResult) {
|
||||
async function followComponentActionState(state: Tachyon.ComponentActionResult) {
|
||||
const jobId = state.job_id;
|
||||
const key = getComponentActionKey(state.component, state.action);
|
||||
|
||||
@@ -551,7 +551,7 @@ async function followComponentActionState(state: Forkop.ComponentActionResult) {
|
||||
|
||||
try {
|
||||
const response = state.running
|
||||
? await ForkopShellMethods.waitComponentActionJob(
|
||||
? await TachyonShellMethods.waitComponentActionJob(
|
||||
jobId,
|
||||
state.component,
|
||||
state.action,
|
||||
@@ -560,7 +560,7 @@ async function followComponentActionState(state: Forkop.ComponentActionResult) {
|
||||
: ({
|
||||
success: true,
|
||||
data: state,
|
||||
} as Forkop.MethodSuccessResponse<Forkop.ComponentActionResult>);
|
||||
} as Tachyon.MethodSuccessResponse<Tachyon.ComponentActionResult>);
|
||||
|
||||
await completeComponentActionJob(key, jobId, response);
|
||||
} catch (error) {
|
||||
@@ -611,7 +611,7 @@ function isComponentActionAlreadyRunningError(message: string | undefined) {
|
||||
);
|
||||
}
|
||||
|
||||
function handleComponentUiState(uiState: Forkop.UiState) {
|
||||
function handleComponentUiState(uiState: Tachyon.UiState) {
|
||||
for (const state of uiState.actions.component || []) {
|
||||
void followComponentActionState(state);
|
||||
}
|
||||
@@ -671,7 +671,7 @@ async function handleComponentAction(button: ComponentActionButton) {
|
||||
let ownsJobFollow = false;
|
||||
|
||||
try {
|
||||
const startResponse = await ForkopShellMethods.componentActionStart(
|
||||
const startResponse = await TachyonShellMethods.componentActionStart(
|
||||
button.component,
|
||||
button.action,
|
||||
);
|
||||
@@ -705,7 +705,7 @@ async function handleComponentAction(button: ComponentActionButton) {
|
||||
followedComponentJobs.add(jobId);
|
||||
ownsJobFollow = true;
|
||||
|
||||
const response = await ForkopShellMethods.waitComponentActionJob(
|
||||
const response = await TachyonShellMethods.waitComponentActionJob(
|
||||
jobId,
|
||||
button.component,
|
||||
button.action,
|
||||
@@ -732,7 +732,7 @@ async function handleComponentAction(button: ComponentActionButton) {
|
||||
}
|
||||
|
||||
function getCheckAction(
|
||||
component: Forkop.ComponentName,
|
||||
component: Tachyon.ComponentName,
|
||||
key: UpdatesActionKey,
|
||||
): ComponentActionButton {
|
||||
return {
|
||||
@@ -745,7 +745,7 @@ function getCheckAction(
|
||||
}
|
||||
|
||||
function getInstallAction(
|
||||
component: Forkop.ComponentName,
|
||||
component: Tachyon.ComponentName,
|
||||
key: UpdatesActionKey,
|
||||
installed: boolean,
|
||||
): ComponentActionButton {
|
||||
@@ -759,7 +759,7 @@ function getInstallAction(
|
||||
}
|
||||
|
||||
function getInstalledUpdateActions(
|
||||
component: Forkop.ComponentName,
|
||||
component: Tachyon.ComponentName,
|
||||
checkKey: UpdatesActionKey,
|
||||
installKey: UpdatesActionKey,
|
||||
installed = true,
|
||||
@@ -824,10 +824,10 @@ function getComponentCards(): ComponentCard[] {
|
||||
Boolean(systemInfo.sing_box_compressed);
|
||||
const singBoxTiny = Boolean(systemInfo.sing_box_tiny);
|
||||
|
||||
const forkopActions = getInstalledUpdateActions(
|
||||
'forkop',
|
||||
'forkopCheck',
|
||||
'forkopInstall',
|
||||
const tachyonActions = getInstalledUpdateActions(
|
||||
'tachyon',
|
||||
'tachyonCheck',
|
||||
'tachyonInstall',
|
||||
);
|
||||
const singBoxActions = getInstalledUpdateActions(
|
||||
'sing_box',
|
||||
@@ -898,15 +898,15 @@ function getComponentCards(): ComponentCard[] {
|
||||
|
||||
return [
|
||||
{
|
||||
component: 'forkop',
|
||||
component: 'tachyon',
|
||||
column: 0,
|
||||
title: 'Forkop',
|
||||
title: 'Tachyon',
|
||||
version: systemInfoLoading
|
||||
? _('Loading...')
|
||||
: normalizeCompiledVersion(systemInfo.forkop_version),
|
||||
latestVersion: getLatestVersion('forkop'),
|
||||
releaseUrl: getGitHubReleaseUrl('forkop'),
|
||||
actions: forkopActions,
|
||||
: normalizeCompiledVersion(systemInfo.tachyon_version),
|
||||
latestVersion: getLatestVersion('tachyon'),
|
||||
releaseUrl: getGitHubReleaseUrl('tachyon'),
|
||||
actions: tachyonActions,
|
||||
},
|
||||
{
|
||||
component: 'sing_box',
|
||||
@@ -1228,7 +1228,7 @@ function onStoreUpdate(
|
||||
}
|
||||
|
||||
function applyComponentUpdateCheckCache(
|
||||
componentUpdateCheckCache: Forkop.ComponentUpdateCheckCache,
|
||||
componentUpdateCheckCache: Tachyon.ComponentUpdateCheckCache,
|
||||
) {
|
||||
componentUpdateCheckCacheResolved = true;
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// language=CSS
|
||||
import { FORKOP_UCI_PACKAGE as FORKOP_CBI_PREFIX } from '../../../constants';
|
||||
import { TACHYON_UCI_PACKAGE as TACHYON_CBI_PREFIX } from '../../../constants';
|
||||
|
||||
export const styles = `
|
||||
#cbi-${FORKOP_CBI_PREFIX}-updates-_mount_node > div {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-updates-_mount_node > div {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#cbi-${FORKOP_CBI_PREFIX}-updates > h3 {
|
||||
#cbi-${TACHYON_CBI_PREFIX}-updates > h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,16 +20,16 @@ export namespace ClashAPI {
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
export namespace Forkop {
|
||||
export namespace Tachyon {
|
||||
// Available commands:
|
||||
// start Start forkop service
|
||||
// stop Stop forkop service
|
||||
// reload Reload forkop configuration
|
||||
// restart Restart forkop service
|
||||
// enable Enable forkop autostart
|
||||
// disable Disable forkop autostart
|
||||
// uninstall Remove forkop files installed outside opkg/apk
|
||||
// main Run main forkop process
|
||||
// start Start tachyon service
|
||||
// stop Stop tachyon service
|
||||
// reload Reload tachyon configuration
|
||||
// restart Restart tachyon service
|
||||
// enable Enable tachyon autostart
|
||||
// disable Disable tachyon autostart
|
||||
// uninstall Remove tachyon files installed outside opkg/apk
|
||||
// main Run main tachyon process
|
||||
// list_update Update domain lists
|
||||
// check_proxy Check proxy connectivity
|
||||
// check_nft Check NFT rules
|
||||
@@ -37,15 +37,15 @@ export namespace Forkop {
|
||||
// check_sing_box Check sing-box installation and status
|
||||
// check_inbounds_config Check whether enabled server inbounds are configured
|
||||
// check_inbounds Check server inbounds from the Servers tab
|
||||
// check_logs Show forkop logs from system journal
|
||||
// check_logs Show tachyon logs from system journal
|
||||
// check_sing_box_logs Show sing-box logs
|
||||
// check_fakeip Test sing-box FakeIP DNS
|
||||
// clash_api Clash API interface for managing proxies and groups
|
||||
// show_config Display current forkop configuration
|
||||
// show_version Show forkop version
|
||||
// show_config Display current tachyon configuration
|
||||
// show_version Show tachyon version
|
||||
// show_sing_box_config Show sing-box configuration
|
||||
// show_sing_box_version Show sing-box version
|
||||
// get_status Get forkop service status
|
||||
// get_status Get tachyon service status
|
||||
// get_sing_box_status Get sing-box service status
|
||||
// get_ui_capabilities Get lightweight UI capabilities
|
||||
// check_dns_available Check DNS server availability
|
||||
@@ -455,8 +455,8 @@ export namespace Forkop {
|
||||
}
|
||||
|
||||
export interface GetSystemInfo {
|
||||
forkop_version: string;
|
||||
forkop_latest_version: string;
|
||||
tachyon_version: string;
|
||||
tachyon_latest_version: string;
|
||||
luci_app_version: string;
|
||||
sing_box_version: string;
|
||||
sing_box_extended: 0 | 1;
|
||||
@@ -527,7 +527,7 @@ export namespace Forkop {
|
||||
|
||||
export interface UiState {
|
||||
service: {
|
||||
forkop: GetStatus;
|
||||
tachyon: GetStatus;
|
||||
sing_box: GetSingBoxStatus;
|
||||
};
|
||||
capabilities: GetUiCapabilities;
|
||||
@@ -540,7 +540,7 @@ export namespace Forkop {
|
||||
}
|
||||
|
||||
export type ComponentName =
|
||||
| 'forkop'
|
||||
| 'tachyon'
|
||||
| 'sing_box'
|
||||
| 'zapret'
|
||||
| 'zapret2'
|
||||
|
||||
@@ -8,7 +8,7 @@ const validUrls = [
|
||||
['With query', 'https://example.com/?q=test'],
|
||||
['With port', 'http://example.com:8080'],
|
||||
['With subdomain', 'https://sub.example.com'],
|
||||
['IPv4 host', 'http://127.0.0.1/forkop-subscription-test.json'],
|
||||
['IPv4 host', 'http://127.0.0.1/tachyon-subscription-test.json'],
|
||||
['IPv4 host with port', 'http://192.168.1.1:8080/sub'],
|
||||
['IPv6 host', 'https://[2001:db8::1]/sub'],
|
||||
['IPv6 host with port', 'https://[2001:db8::1]:8443/sub'],
|
||||
|
||||
@@ -5,7 +5,7 @@ import path from 'path';
|
||||
export default defineConfig({
|
||||
entry: ['src/main.ts'],
|
||||
format: ['esm'], // пусть tsup генерит export {...}
|
||||
outDir: '../luci-app-forkop/htdocs/luci-static/resources/view/forkop',
|
||||
outDir: '../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon',
|
||||
outExtension: () => ({ js: '.js' }),
|
||||
dts: false,
|
||||
clean: false,
|
||||
@@ -18,7 +18,7 @@ export default defineConfig({
|
||||
},
|
||||
onSuccess: () => {
|
||||
const outDir =
|
||||
'../luci-app-forkop/htdocs/luci-static/resources/view/forkop';
|
||||
'../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon';
|
||||
const file = path.join(outDir, 'main.js');
|
||||
let code = fs.readFileSync(file, 'utf8');
|
||||
|
||||
|
||||
@@ -18,19 +18,19 @@ const config = {
|
||||
|
||||
const syncDirs = [
|
||||
{
|
||||
local: path.resolve(process.env.LOCAL_DIR_FE ?? '../luci-app-forkop/htdocs/luci-static/resources/view/forkop'),
|
||||
remote: process.env.REMOTE_DIR_FE ?? '/www/luci-static/resources/view/forkop',
|
||||
local: path.resolve(process.env.LOCAL_DIR_FE ?? '../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon'),
|
||||
remote: process.env.REMOTE_DIR_FE ?? '/www/luci-static/resources/view/tachyon',
|
||||
},
|
||||
{
|
||||
local: path.resolve(process.env.LOCAL_DIR_BIN ?? '../forkop/files/usr/bin/'),
|
||||
local: path.resolve(process.env.LOCAL_DIR_BIN ?? '../tachyon/files/usr/bin/'),
|
||||
remote: process.env.REMOTE_DIR_BIN ?? '/usr/bin/',
|
||||
},
|
||||
{
|
||||
local: path.resolve(process.env.LOCAL_DIR_LIB ?? '../forkop/files/usr/lib/'),
|
||||
remote: process.env.REMOTE_DIR_LIB ?? '/usr/lib/forkop/',
|
||||
local: path.resolve(process.env.LOCAL_DIR_LIB ?? '../tachyon/files/usr/lib/'),
|
||||
remote: process.env.REMOTE_DIR_LIB ?? '/usr/lib/tachyon/',
|
||||
},
|
||||
{
|
||||
local: path.resolve(process.env.LOCAL_DIR_INIT ?? '../forkop/files/etc/init.d/'),
|
||||
local: path.resolve(process.env.LOCAL_DIR_INIT ?? '../tachyon/files/etc/init.d/'),
|
||||
remote: process.env.REMOTE_DIR_INIT ?? '/etc/init.d/',
|
||||
}
|
||||
];
|
||||
|
||||
+234
-197
@@ -12,25 +12,26 @@ DOWNLOAD_TIMEOUT_SECONDS=600
|
||||
PKG_IS_APK=0
|
||||
FETCHER=""
|
||||
TMP_DIR=""
|
||||
FORKOP_WAS_ENABLED=0
|
||||
FORKOP_WAS_RUNNING=0
|
||||
FORKOP_LEGACY_DETECTED=0
|
||||
FORKOP_I18N_REQUESTED=0
|
||||
TACHYON_WAS_ENABLED=0
|
||||
TACHYON_WAS_RUNNING=0
|
||||
TACHYON_LEGACY_DETECTED=0
|
||||
TACHYON_FORKOP_MIGRATION=0
|
||||
TACHYON_I18N_REQUESTED=0
|
||||
INSTALLER_LANG="en"
|
||||
SING_BOX_INSTALL_VARIANT=""
|
||||
|
||||
FORKOP_RELEASE_JSON=""
|
||||
FORKOP_RELEASE_TAG=""
|
||||
FORKOP_BACKEND_URL=""
|
||||
FORKOP_BACKEND_NAME=""
|
||||
FORKOP_BACKEND_FILE=""
|
||||
FORKOP_APP_URL=""
|
||||
FORKOP_APP_NAME=""
|
||||
FORKOP_APP_FILE=""
|
||||
FORKOP_I18N_URL=""
|
||||
FORKOP_I18N_NAME=""
|
||||
FORKOP_I18N_FILE=""
|
||||
FORKOP_PACKAGE_VERSION=""
|
||||
TACHYON_RELEASE_JSON=""
|
||||
TACHYON_RELEASE_TAG=""
|
||||
TACHYON_BACKEND_URL=""
|
||||
TACHYON_BACKEND_NAME=""
|
||||
TACHYON_BACKEND_FILE=""
|
||||
TACHYON_APP_URL=""
|
||||
TACHYON_APP_NAME=""
|
||||
TACHYON_APP_FILE=""
|
||||
TACHYON_I18N_URL=""
|
||||
TACHYON_I18N_NAME=""
|
||||
TACHYON_I18N_FILE=""
|
||||
TACHYON_PACKAGE_VERSION=""
|
||||
LEGACY_BRAND="$(printf '\160\157\144\153\157\160')"
|
||||
LEGACY_BACKEND_PACKAGE="${LEGACY_BRAND}-plus"
|
||||
LEGACY_CONFIG_PACKAGE_ALT="${LEGACY_BRAND}_plus"
|
||||
@@ -55,10 +56,10 @@ usage() {
|
||||
cat <<EOF
|
||||
Usage: $0
|
||||
|
||||
Installs or updates Forkop packages:
|
||||
- forkop
|
||||
- luci-app-forkop
|
||||
- luci-i18n-forkop-ru when requested or when LuCI language is Russian
|
||||
Installs or updates Tachyon packages:
|
||||
- tachyon
|
||||
- luci-app-tachyon
|
||||
- luci-i18n-tachyon-ru when requested or when LuCI language is Russian
|
||||
|
||||
Can also install or switch sing-box variant:
|
||||
- stable sing-box from OpenWrt feeds
|
||||
@@ -97,10 +98,10 @@ command_exists() {
|
||||
}
|
||||
|
||||
init_tmp_dir() {
|
||||
TMP_DIR="$(mktemp -d /tmp/forkop.XXXXXX 2>/dev/null || true)"
|
||||
TMP_DIR="$(mktemp -d /tmp/tachyon.XXXXXX 2>/dev/null || true)"
|
||||
|
||||
if [ -z "$TMP_DIR" ]; then
|
||||
TMP_DIR="/tmp/forkop.$$"
|
||||
TMP_DIR="/tmp/tachyon.$$"
|
||||
mkdir -p "$TMP_DIR" || fail "Failed to create temporary directory: $TMP_DIR"
|
||||
fi
|
||||
}
|
||||
@@ -116,29 +117,29 @@ detect_fetcher() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
fail "wget or curl is required to download Forkop"
|
||||
fail "wget or curl is required to download Tachyon"
|
||||
}
|
||||
|
||||
run_with_deadline() {
|
||||
forkop_deadline_seconds="$1"
|
||||
tachyon_deadline_seconds="$1"
|
||||
shift
|
||||
|
||||
"$@" &
|
||||
forkop_deadline_command_pid=$!
|
||||
tachyon_deadline_command_pid=$!
|
||||
(
|
||||
trap 'kill "$forkop_deadline_sleep_pid" 2>/dev/null || true; exit 0' TERM INT
|
||||
sleep "$forkop_deadline_seconds" &
|
||||
forkop_deadline_sleep_pid=$!
|
||||
wait "$forkop_deadline_sleep_pid"
|
||||
kill "$forkop_deadline_command_pid" 2>/dev/null || true
|
||||
trap 'kill "$tachyon_deadline_sleep_pid" 2>/dev/null || true; exit 0' TERM INT
|
||||
sleep "$tachyon_deadline_seconds" &
|
||||
tachyon_deadline_sleep_pid=$!
|
||||
wait "$tachyon_deadline_sleep_pid"
|
||||
kill "$tachyon_deadline_command_pid" 2>/dev/null || true
|
||||
) &
|
||||
forkop_deadline_watchdog_pid=$!
|
||||
tachyon_deadline_watchdog_pid=$!
|
||||
|
||||
wait "$forkop_deadline_command_pid"
|
||||
forkop_deadline_status=$?
|
||||
kill "$forkop_deadline_watchdog_pid" 2>/dev/null || true
|
||||
wait "$forkop_deadline_watchdog_pid" 2>/dev/null || true
|
||||
return "$forkop_deadline_status"
|
||||
wait "$tachyon_deadline_command_pid"
|
||||
tachyon_deadline_status=$?
|
||||
kill "$tachyon_deadline_watchdog_pid" 2>/dev/null || true
|
||||
wait "$tachyon_deadline_watchdog_pid" 2>/dev/null || true
|
||||
return "$tachyon_deadline_status"
|
||||
}
|
||||
|
||||
http_get() {
|
||||
@@ -436,53 +437,53 @@ function env(name, fallback) {
|
||||
return as_string(value);
|
||||
}
|
||||
|
||||
const INSTALLER_FORKOP_INIT = env("FORKOP_INSTALLER_INIT", "/etc/init.d/forkop");
|
||||
const INSTALLER_FORKOP_BIN = env("FORKOP_INSTALLER_BIN", "/usr/bin/forkop");
|
||||
const INSTALLER_FORKOP_LIB = env("FORKOP_INSTALLER_LIB", "/usr/lib/forkop");
|
||||
const INSTALLER_FORKOP_PERSISTENT_DIR = env("FORKOP_INSTALLER_PERSISTENT_DIR", "/etc/forkop");
|
||||
const INSTALLER_FORKOP_UCI_DEFAULTS = env("FORKOP_INSTALLER_UCI_DEFAULTS", "/etc/uci-defaults/50_luci-forkop");
|
||||
const INSTALLER_FORKOP_LUCI_VIEW = env("FORKOP_INSTALLER_LUCI_VIEW", "/www/luci-static/resources/view/forkop");
|
||||
const INSTALLER_MENU_JSON = env("FORKOP_INSTALLER_MENU_JSON", "/usr/share/luci/menu.d/luci-app-forkop.json");
|
||||
const INSTALLER_ACL_JSON = env("FORKOP_INSTALLER_ACL_JSON", "/usr/share/rpcd/acl.d/luci-app-forkop.json");
|
||||
const INSTALLER_RU_LMO = env("FORKOP_INSTALLER_RU_LMO", "/usr/lib/lua/luci/i18n/forkop.ru.lmo");
|
||||
const INSTALLER_EN_LMO = env("FORKOP_INSTALLER_EN_LMO", "/usr/lib/lua/luci/i18n/forkop.en.lmo");
|
||||
const INSTALLER_RU_LUA = env("FORKOP_INSTALLER_RU_LUA", "/usr/lib/lua/luci/i18n/forkop.ru.lua");
|
||||
const INSTALLER_EN_LUA = env("FORKOP_INSTALLER_EN_LUA", "/usr/lib/lua/luci/i18n/forkop.en.lua");
|
||||
const INSTALLER_RPCD_INIT = env("FORKOP_INSTALLER_RPCD_INIT", "/etc/init.d/rpcd");
|
||||
const LEGACY_BRAND = env("FORKOP_INSTALLER_LEGACY_BRAND", "");
|
||||
const LEGACY_BACKEND_PACKAGE = env("FORKOP_INSTALLER_LEGACY_BACKEND", LEGACY_BRAND + "-plus");
|
||||
const LEGACY_CONFIG_PACKAGE_ALT = env("FORKOP_INSTALLER_LEGACY_CONFIG_ALT", LEGACY_BRAND + "_plus");
|
||||
const INSTALLER_LEGACY_INIT = env("FORKOP_INSTALLER_LEGACY_INIT", "/etc/init.d/" + LEGACY_BACKEND_PACKAGE);
|
||||
const INSTALLER_LEGACY_BASE_INIT = env("FORKOP_INSTALLER_LEGACY_BASE_INIT", "/etc/init.d/" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_BIN = env("FORKOP_INSTALLER_LEGACY_BASE_BIN", "/usr/bin/" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_LIB = env("FORKOP_INSTALLER_LEGACY_BASE_LIB", "/usr/lib/" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_UCI_DEFAULTS = env("FORKOP_INSTALLER_LEGACY_BASE_UCI_DEFAULTS", "/etc/uci-defaults/50_luci-" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_LUCI_VIEW = env("FORKOP_INSTALLER_LEGACY_BASE_LUCI_VIEW", "/www/luci-static/resources/view/" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_MENU_JSON = env("FORKOP_INSTALLER_LEGACY_BASE_MENU_JSON", "/usr/share/luci/menu.d/luci-app-" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_ACL_JSON = env("FORKOP_INSTALLER_LEGACY_BASE_ACL_JSON", "/usr/share/rpcd/acl.d/luci-app-" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_I18N = env("FORKOP_INSTALLER_LEGACY_BASE_I18N", "/usr/lib/lua/luci/i18n/" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_CONFIG = env("FORKOP_INSTALLER_LEGACY_BASE_CONFIG", "/etc/config/" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_PERSISTENT_DIR = env("FORKOP_INSTALLER_LEGACY_BASE_PERSISTENT_DIR", "/etc/" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_RUNTIME_DIR = env("FORKOP_INSTALLER_LEGACY_BASE_RUNTIME_DIR", "/var/run/" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_TMP_DIR = env("FORKOP_INSTALLER_LEGACY_BASE_TMP_DIR", "/tmp/" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_TMP_PACKAGE_GLOB = env("FORKOP_INSTALLER_LEGACY_TMP_PACKAGE_GLOB", "/tmp/*" + LEGACY_BRAND + "*");
|
||||
const INSTALLER_LEGACY_SCAN_ROOTS = env("FORKOP_INSTALLER_LEGACY_SCAN_ROOTS", "/tmp /var/run /etc /usr/lib /usr/share/luci /usr/share/rpcd /www/luci-static/resources/view");
|
||||
const INSTALLER_LEGACY_BIN = env("FORKOP_INSTALLER_LEGACY_BIN", "/usr/bin/" + LEGACY_BACKEND_PACKAGE);
|
||||
const INSTALLER_LEGACY_LIB = env("FORKOP_INSTALLER_LEGACY_LIB", "/usr/lib/" + LEGACY_BACKEND_PACKAGE);
|
||||
const INSTALLER_LEGACY_UCI_DEFAULTS = env("FORKOP_INSTALLER_LEGACY_UCI_DEFAULTS", "/etc/uci-defaults/50_luci-" + LEGACY_BACKEND_PACKAGE);
|
||||
const INSTALLER_LEGACY_LUCI_VIEW = env("FORKOP_INSTALLER_LEGACY_LUCI_VIEW", "/www/luci-static/resources/view/" + LEGACY_CONFIG_PACKAGE_ALT);
|
||||
const INSTALLER_LEGACY_MENU_JSON = env("FORKOP_INSTALLER_LEGACY_MENU_JSON", "/usr/share/luci/menu.d/luci-app-" + LEGACY_BACKEND_PACKAGE + ".json");
|
||||
const INSTALLER_LEGACY_ACL_JSON = env("FORKOP_INSTALLER_LEGACY_ACL_JSON", "/usr/share/rpcd/acl.d/luci-app-" + LEGACY_BACKEND_PACKAGE + ".json");
|
||||
const INSTALLER_LEGACY_CONFIG = env("FORKOP_INSTALLER_LEGACY_CONFIG", "/etc/config/" + LEGACY_BACKEND_PACKAGE);
|
||||
const INSTALLER_LEGACY_CONFIG_ALT = env("FORKOP_INSTALLER_LEGACY_CONFIG_FILE_ALT", "/etc/config/" + LEGACY_CONFIG_PACKAGE_ALT);
|
||||
const INSTALLER_LEGACY_PERSISTENT_DIR = env("FORKOP_INSTALLER_LEGACY_PERSISTENT_DIR", "/etc/" + LEGACY_BACKEND_PACKAGE);
|
||||
const INSTALLER_LEGACY_RUNTIME_DIR = env("FORKOP_INSTALLER_LEGACY_RUNTIME_DIR", "/var/run/" + LEGACY_BACKEND_PACKAGE);
|
||||
const INSTALLER_LEGACY_TMP_DIR = env("FORKOP_INSTALLER_LEGACY_TMP_DIR", "/tmp/" + LEGACY_BACKEND_PACKAGE);
|
||||
const INSTALLER_LEGACY_TMP_ALT_DIR = env("FORKOP_INSTALLER_LEGACY_TMP_ALT_DIR", "/tmp/" + LEGACY_CONFIG_PACKAGE_ALT);
|
||||
const INSTALLER_TACHYON_INIT = env("TACHYON_INSTALLER_INIT", "/etc/init.d/tachyon");
|
||||
const INSTALLER_TACHYON_BIN = env("TACHYON_INSTALLER_BIN", "/usr/bin/tachyon");
|
||||
const INSTALLER_TACHYON_LIB = env("TACHYON_INSTALLER_LIB", "/usr/lib/tachyon");
|
||||
const INSTALLER_TACHYON_PERSISTENT_DIR = env("TACHYON_INSTALLER_PERSISTENT_DIR", "/etc/tachyon");
|
||||
const INSTALLER_TACHYON_UCI_DEFAULTS = env("TACHYON_INSTALLER_UCI_DEFAULTS", "/etc/uci-defaults/50_luci-tachyon");
|
||||
const INSTALLER_TACHYON_LUCI_VIEW = env("TACHYON_INSTALLER_LUCI_VIEW", "/www/luci-static/resources/view/tachyon");
|
||||
const INSTALLER_MENU_JSON = env("TACHYON_INSTALLER_MENU_JSON", "/usr/share/luci/menu.d/luci-app-tachyon.json");
|
||||
const INSTALLER_ACL_JSON = env("TACHYON_INSTALLER_ACL_JSON", "/usr/share/rpcd/acl.d/luci-app-tachyon.json");
|
||||
const INSTALLER_RU_LMO = env("TACHYON_INSTALLER_RU_LMO", "/usr/lib/lua/luci/i18n/tachyon.ru.lmo");
|
||||
const INSTALLER_EN_LMO = env("TACHYON_INSTALLER_EN_LMO", "/usr/lib/lua/luci/i18n/tachyon.en.lmo");
|
||||
const INSTALLER_RU_LUA = env("TACHYON_INSTALLER_RU_LUA", "/usr/lib/lua/luci/i18n/tachyon.ru.lua");
|
||||
const INSTALLER_EN_LUA = env("TACHYON_INSTALLER_EN_LUA", "/usr/lib/lua/luci/i18n/tachyon.en.lua");
|
||||
const INSTALLER_RPCD_INIT = env("TACHYON_INSTALLER_RPCD_INIT", "/etc/init.d/rpcd");
|
||||
const LEGACY_BRAND = env("TACHYON_INSTALLER_LEGACY_BRAND", "");
|
||||
const LEGACY_BACKEND_PACKAGE = env("TACHYON_INSTALLER_LEGACY_BACKEND", LEGACY_BRAND + "-plus");
|
||||
const LEGACY_CONFIG_PACKAGE_ALT = env("TACHYON_INSTALLER_LEGACY_CONFIG_ALT", LEGACY_BRAND + "_plus");
|
||||
const INSTALLER_LEGACY_INIT = env("TACHYON_INSTALLER_LEGACY_INIT", "/etc/init.d/" + LEGACY_BACKEND_PACKAGE);
|
||||
const INSTALLER_LEGACY_BASE_INIT = env("TACHYON_INSTALLER_LEGACY_BASE_INIT", "/etc/init.d/" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_BIN = env("TACHYON_INSTALLER_LEGACY_BASE_BIN", "/usr/bin/" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_LIB = env("TACHYON_INSTALLER_LEGACY_BASE_LIB", "/usr/lib/" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_UCI_DEFAULTS = env("TACHYON_INSTALLER_LEGACY_BASE_UCI_DEFAULTS", "/etc/uci-defaults/50_luci-" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_LUCI_VIEW = env("TACHYON_INSTALLER_LEGACY_BASE_LUCI_VIEW", "/www/luci-static/resources/view/" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_MENU_JSON = env("TACHYON_INSTALLER_LEGACY_BASE_MENU_JSON", "/usr/share/luci/menu.d/luci-app-" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_ACL_JSON = env("TACHYON_INSTALLER_LEGACY_BASE_ACL_JSON", "/usr/share/rpcd/acl.d/luci-app-" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_I18N = env("TACHYON_INSTALLER_LEGACY_BASE_I18N", "/usr/lib/lua/luci/i18n/" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_CONFIG = env("TACHYON_INSTALLER_LEGACY_BASE_CONFIG", "/etc/config/" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_PERSISTENT_DIR = env("TACHYON_INSTALLER_LEGACY_BASE_PERSISTENT_DIR", "/etc/" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_RUNTIME_DIR = env("TACHYON_INSTALLER_LEGACY_BASE_RUNTIME_DIR", "/var/run/" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_BASE_TMP_DIR = env("TACHYON_INSTALLER_LEGACY_BASE_TMP_DIR", "/tmp/" + LEGACY_BRAND);
|
||||
const INSTALLER_LEGACY_TMP_PACKAGE_GLOB = env("TACHYON_INSTALLER_LEGACY_TMP_PACKAGE_GLOB", "/tmp/*" + LEGACY_BRAND + "*");
|
||||
const INSTALLER_LEGACY_SCAN_ROOTS = env("TACHYON_INSTALLER_LEGACY_SCAN_ROOTS", "/tmp /var/run /etc /usr/lib /usr/share/luci /usr/share/rpcd /www/luci-static/resources/view");
|
||||
const INSTALLER_LEGACY_BIN = env("TACHYON_INSTALLER_LEGACY_BIN", "/usr/bin/" + LEGACY_BACKEND_PACKAGE);
|
||||
const INSTALLER_LEGACY_LIB = env("TACHYON_INSTALLER_LEGACY_LIB", "/usr/lib/" + LEGACY_BACKEND_PACKAGE);
|
||||
const INSTALLER_LEGACY_UCI_DEFAULTS = env("TACHYON_INSTALLER_LEGACY_UCI_DEFAULTS", "/etc/uci-defaults/50_luci-" + LEGACY_BACKEND_PACKAGE);
|
||||
const INSTALLER_LEGACY_LUCI_VIEW = env("TACHYON_INSTALLER_LEGACY_LUCI_VIEW", "/www/luci-static/resources/view/" + LEGACY_CONFIG_PACKAGE_ALT);
|
||||
const INSTALLER_LEGACY_MENU_JSON = env("TACHYON_INSTALLER_LEGACY_MENU_JSON", "/usr/share/luci/menu.d/luci-app-" + LEGACY_BACKEND_PACKAGE + ".json");
|
||||
const INSTALLER_LEGACY_ACL_JSON = env("TACHYON_INSTALLER_LEGACY_ACL_JSON", "/usr/share/rpcd/acl.d/luci-app-" + LEGACY_BACKEND_PACKAGE + ".json");
|
||||
const INSTALLER_LEGACY_CONFIG = env("TACHYON_INSTALLER_LEGACY_CONFIG", "/etc/config/" + LEGACY_BACKEND_PACKAGE);
|
||||
const INSTALLER_LEGACY_CONFIG_ALT = env("TACHYON_INSTALLER_LEGACY_CONFIG_FILE_ALT", "/etc/config/" + LEGACY_CONFIG_PACKAGE_ALT);
|
||||
const INSTALLER_LEGACY_PERSISTENT_DIR = env("TACHYON_INSTALLER_LEGACY_PERSISTENT_DIR", "/etc/" + LEGACY_BACKEND_PACKAGE);
|
||||
const INSTALLER_LEGACY_RUNTIME_DIR = env("TACHYON_INSTALLER_LEGACY_RUNTIME_DIR", "/var/run/" + LEGACY_BACKEND_PACKAGE);
|
||||
const INSTALLER_LEGACY_TMP_DIR = env("TACHYON_INSTALLER_LEGACY_TMP_DIR", "/tmp/" + LEGACY_BACKEND_PACKAGE);
|
||||
const INSTALLER_LEGACY_TMP_ALT_DIR = env("TACHYON_INSTALLER_LEGACY_TMP_ALT_DIR", "/tmp/" + LEGACY_CONFIG_PACKAGE_ALT);
|
||||
|
||||
let dns_owner_config = "forkop";
|
||||
let dns_owner_section = "forkop";
|
||||
let dns_owner_option_prefix = "forkop_";
|
||||
let dns_owner_config = "tachyon";
|
||||
let dns_owner_section = "tachyon";
|
||||
let dns_owner_option_prefix = "tachyon_";
|
||||
|
||||
function path_exists(path) {
|
||||
return fs.stat(as_string(path)) != null;
|
||||
@@ -667,9 +668,9 @@ function select_dns_owner(legacy) {
|
||||
dns_owner_option_prefix = LEGACY_BRAND + "_";
|
||||
}
|
||||
else {
|
||||
dns_owner_config = "forkop";
|
||||
dns_owner_section = "forkop";
|
||||
dns_owner_option_prefix = "forkop_";
|
||||
dns_owner_config = "tachyon";
|
||||
dns_owner_section = "tachyon";
|
||||
dns_owner_option_prefix = "tachyon_";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -686,21 +687,21 @@ function installer_deactivate_legacy_base() {
|
||||
return;
|
||||
|
||||
if (installer_service_running(INSTALLER_LEGACY_BASE_INIT)) {
|
||||
warn("Detected a running legacy service. Stopping it before installing Forkop.\n");
|
||||
warn("Detected a running legacy service. Stopping it before installing Tachyon.\n");
|
||||
run_args([ INSTALLER_LEGACY_BASE_INIT, "stop" ]);
|
||||
}
|
||||
|
||||
if (installer_service_enabled(INSTALLER_LEGACY_BASE_INIT)) {
|
||||
warn("Detected an enabled legacy autostart. Disabling it before installing Forkop.\n");
|
||||
warn("Detected an enabled legacy autostart. Disabling it before installing Tachyon.\n");
|
||||
run_args([ INSTALLER_LEGACY_BASE_INIT, "disable" ]);
|
||||
}
|
||||
}
|
||||
|
||||
function installer_cleanup_legacy() {
|
||||
let forkop_installed = installer_package_installed("forkop");
|
||||
let tachyon_installed = installer_package_installed("tachyon");
|
||||
let legacy_installed = LEGACY_BRAND != "" && installer_package_installed(LEGACY_BACKEND_PACKAGE);
|
||||
let active_init = legacy_installed ? INSTALLER_LEGACY_INIT : INSTALLER_FORKOP_INIT;
|
||||
let active_bin = legacy_installed ? INSTALLER_LEGACY_BIN : INSTALLER_FORKOP_BIN;
|
||||
let active_init = legacy_installed ? INSTALLER_LEGACY_INIT : INSTALLER_TACHYON_INIT;
|
||||
let active_bin = legacy_installed ? INSTALLER_LEGACY_BIN : INSTALLER_TACHYON_BIN;
|
||||
let was_enabled = installer_service_enabled(active_init);
|
||||
let was_running = installer_service_running(active_init) || installer_backend_status_running(active_bin);
|
||||
|
||||
@@ -732,9 +733,18 @@ function installer_cleanup_legacy() {
|
||||
packages_removed = false;
|
||||
}
|
||||
|
||||
if (!installer_remove_package_prefix("luci-i18n-forkop"))
|
||||
if (installer_package_installed("forkop")) {
|
||||
if (!installer_remove_package_prefix("luci-i18n-forkop"))
|
||||
packages_removed = false;
|
||||
if (!installer_remove_package("luci-app-forkop"))
|
||||
packages_removed = false;
|
||||
if (!installer_remove_package("forkop"))
|
||||
packages_removed = false;
|
||||
}
|
||||
|
||||
if (!installer_remove_package_prefix("luci-i18n-tachyon"))
|
||||
packages_removed = false;
|
||||
if (!installer_remove_package("luci-app-forkop"))
|
||||
if (!installer_remove_package("luci-app-tachyon"))
|
||||
packages_removed = false;
|
||||
|
||||
if (!packages_removed) {
|
||||
@@ -755,17 +765,17 @@ function installer_cleanup_legacy() {
|
||||
remove_path(path);
|
||||
}
|
||||
|
||||
if (!forkop_installed) {
|
||||
remove_path(INSTALLER_FORKOP_LIB);
|
||||
remove_path(INSTALLER_FORKOP_INIT);
|
||||
remove_path(INSTALLER_FORKOP_BIN);
|
||||
if (!tachyon_installed) {
|
||||
remove_path(INSTALLER_TACHYON_LIB);
|
||||
remove_path(INSTALLER_TACHYON_INIT);
|
||||
remove_path(INSTALLER_TACHYON_BIN);
|
||||
}
|
||||
|
||||
for (let path in [
|
||||
INSTALLER_FORKOP_LUCI_VIEW,
|
||||
INSTALLER_TACHYON_LUCI_VIEW,
|
||||
INSTALLER_MENU_JSON,
|
||||
INSTALLER_ACL_JSON,
|
||||
INSTALLER_FORKOP_UCI_DEFAULTS,
|
||||
INSTALLER_TACHYON_UCI_DEFAULTS,
|
||||
INSTALLER_RU_LMO,
|
||||
INSTALLER_EN_LMO,
|
||||
INSTALLER_RU_LUA,
|
||||
@@ -773,9 +783,9 @@ function installer_cleanup_legacy() {
|
||||
])
|
||||
remove_path(path);
|
||||
|
||||
print("FORKOP_WAS_ENABLED=", was_enabled ? "1" : "0", "\n");
|
||||
print("FORKOP_WAS_RUNNING=", was_running ? "1" : "0", "\n");
|
||||
print("FORKOP_LEGACY_DETECTED=", legacy_installed ? "1" : "0", "\n");
|
||||
print("TACHYON_WAS_ENABLED=", was_enabled ? "1" : "0", "\n");
|
||||
print("TACHYON_WAS_RUNNING=", was_running ? "1" : "0", "\n");
|
||||
print("TACHYON_LEGACY_DETECTED=", legacy_installed ? "1" : "0", "\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -786,8 +796,8 @@ function installer_finalize_legacy() {
|
||||
let legacy_tailscale_dir = INSTALLER_LEGACY_PERSISTENT_DIR + "/tailscale";
|
||||
if (path_exists(legacy_tailscale_dir)) {
|
||||
let entries = fs.lsdir(legacy_tailscale_dir);
|
||||
let forkop_tailscale_dir = INSTALLER_FORKOP_PERSISTENT_DIR + "/tailscale";
|
||||
if (type(entries) != "array" || !run_args([ "mkdir", "-p", forkop_tailscale_dir ])) {
|
||||
let tachyon_tailscale_dir = INSTALLER_TACHYON_PERSISTENT_DIR + "/tailscale";
|
||||
if (type(entries) != "array" || !run_args([ "mkdir", "-p", tachyon_tailscale_dir ])) {
|
||||
warn("Failed to prepare legacy Tailscale state migration; the legacy directory was preserved.\n");
|
||||
return false;
|
||||
}
|
||||
@@ -795,11 +805,11 @@ function installer_finalize_legacy() {
|
||||
for (let entry in entries) {
|
||||
entry = as_string(entry);
|
||||
let source = legacy_tailscale_dir + "/" + entry;
|
||||
let target = forkop_tailscale_dir + "/" + entry;
|
||||
let target = tachyon_tailscale_dir + "/" + entry;
|
||||
if (path_exists(target))
|
||||
continue;
|
||||
|
||||
let temporary = forkop_tailscale_dir + "/." + entry + ".forkop-migrate";
|
||||
let temporary = tachyon_tailscale_dir + "/." + entry + ".tachyon-migrate";
|
||||
if (!remove_path(temporary) ||
|
||||
!run_args([ "cp", "-a", source, temporary ]) ||
|
||||
!run_args([ "mv", temporary, target ])) {
|
||||
@@ -863,26 +873,26 @@ function installer_finalize_legacy() {
|
||||
}
|
||||
|
||||
function installer_post_install() {
|
||||
remove_globs(env("FORKOP_INSTALLER_LUCI_CACHE_GLOBS", "/var/luci-indexcache* /tmp/luci-indexcache*"));
|
||||
remove_globs(env("TACHYON_INSTALLER_LUCI_CACHE_GLOBS", "/var/luci-indexcache* /tmp/luci-indexcache*"));
|
||||
for (let path in [
|
||||
env("FORKOP_INSTALLER_LATEST_VERSION_CACHE", "/tmp/forkop.latest-version.cache"),
|
||||
env("FORKOP_INSTALLER_SYSTEM_INFO_CACHE", "/var/run/forkop/system-info.json"),
|
||||
env("FORKOP_INSTALLER_SERVER_COUNTRY_CACHE", "/var/run/forkop/server-country-cache.json"),
|
||||
env("FORKOP_INSTALLER_SING_BOX_VERSION_CACHE", "/var/run/forkop/ui-state/sing-box-version"),
|
||||
env("FORKOP_INSTALLER_TMP_SYSTEM_INFO_CACHE", "/tmp/forkop/system-info.json")
|
||||
env("TACHYON_INSTALLER_LATEST_VERSION_CACHE", "/tmp/tachyon.latest-version.cache"),
|
||||
env("TACHYON_INSTALLER_SYSTEM_INFO_CACHE", "/var/run/tachyon/system-info.json"),
|
||||
env("TACHYON_INSTALLER_SERVER_COUNTRY_CACHE", "/var/run/tachyon/server-country-cache.json"),
|
||||
env("TACHYON_INSTALLER_SING_BOX_VERSION_CACHE", "/var/run/tachyon/ui-state/sing-box-version"),
|
||||
env("TACHYON_INSTALLER_TMP_SYSTEM_INFO_CACHE", "/tmp/tachyon/system-info.json")
|
||||
])
|
||||
remove_path(path);
|
||||
|
||||
if (path_executable(INSTALLER_RPCD_INIT))
|
||||
run_args([ INSTALLER_RPCD_INIT, "reload" ]);
|
||||
|
||||
if (env("FORKOP_WAS_ENABLED", "0") == "1" && path_executable(INSTALLER_FORKOP_INIT))
|
||||
run_args([ INSTALLER_FORKOP_INIT, "enable" ]);
|
||||
if (env("TACHYON_WAS_ENABLED", "0") == "1" && path_executable(INSTALLER_TACHYON_INIT))
|
||||
run_args([ INSTALLER_TACHYON_INIT, "enable" ]);
|
||||
|
||||
if (env("FORKOP_WAS_RUNNING", "0") == "1" && path_executable(INSTALLER_FORKOP_INIT)) {
|
||||
if (!run_args([ INSTALLER_FORKOP_INIT, "start" ]) &&
|
||||
!run_args([ INSTALLER_FORKOP_INIT, "restart" ]))
|
||||
warn("Failed to start Forkop after upgrade.\n");
|
||||
if (env("TACHYON_WAS_RUNNING", "0") == "1" && path_executable(INSTALLER_TACHYON_INIT)) {
|
||||
if (!run_args([ INSTALLER_TACHYON_INIT, "start" ]) &&
|
||||
!run_args([ INSTALLER_TACHYON_INIT, "restart" ]))
|
||||
warn("Failed to start Tachyon after upgrade.\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1024,11 +1034,11 @@ function asset_matches(name, kind, ext, version) {
|
||||
return false;
|
||||
|
||||
if (kind == "backend")
|
||||
return name == "forkop_" + version + "." + ext;
|
||||
return name == "tachyon_" + version + "." + ext;
|
||||
if (kind == "app")
|
||||
return name == "luci-app-forkop_" + version + "." + ext;
|
||||
return name == "luci-app-tachyon_" + version + "." + ext;
|
||||
if (kind == "i18n")
|
||||
return name == "luci-i18n-forkop-ru_" + version + "." + ext;
|
||||
return name == "luci-i18n-tachyon-ru_" + version + "." + ext;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1092,9 +1102,9 @@ EOF
|
||||
|
||||
|
||||
install_json_ucode() {
|
||||
FORKOP_INSTALLER_LEGACY_BRAND="$LEGACY_BRAND" \
|
||||
FORKOP_INSTALLER_LEGACY_BACKEND="$LEGACY_BACKEND_PACKAGE" \
|
||||
FORKOP_INSTALLER_LEGACY_CONFIG_ALT="$LEGACY_CONFIG_PACKAGE_ALT" \
|
||||
TACHYON_INSTALLER_LEGACY_BRAND="$LEGACY_BRAND" \
|
||||
TACHYON_INSTALLER_LEGACY_BACKEND="$LEGACY_BACKEND_PACKAGE" \
|
||||
TACHYON_INSTALLER_LEGACY_CONFIG_ALT="$LEGACY_CONFIG_PACKAGE_ALT" \
|
||||
ucode "$(install_json_helper_path)" "$@"
|
||||
}
|
||||
|
||||
@@ -1244,7 +1254,7 @@ check_system() {
|
||||
major="$(printf '%s' "$release" | sed 's/[^0-9].*$//' | cut -d. -f1)"
|
||||
|
||||
if [ -n "$major" ] && [ "$major" -lt 24 ]; then
|
||||
fail "Forkop requires OpenWrt 24.10 or newer"
|
||||
fail "Tachyon requires OpenWrt 24.10 or newer"
|
||||
fi
|
||||
|
||||
available_space="$(df /overlay 2>/dev/null | awk 'NR==2 {print $4}')"
|
||||
@@ -1302,7 +1312,7 @@ detect_installer_language() {
|
||||
luci_lang="$(get_luci_main_lang)"
|
||||
|
||||
INSTALLER_LANG="en"
|
||||
if pkg_is_installed "luci-i18n-forkop-ru"; then
|
||||
if pkg_is_installed "luci-i18n-tachyon-ru"; then
|
||||
INSTALLER_LANG="ru"
|
||||
return 0
|
||||
fi
|
||||
@@ -1357,14 +1367,14 @@ extract_package_version() {
|
||||
package_name="$1"
|
||||
|
||||
case "$package_name" in
|
||||
forkop_*.ipk|forkop_*.apk)
|
||||
printf '%s\n' "$package_name" | sed 's/^forkop_//;s/\.ipk$//;s/\.apk$//'
|
||||
tachyon_*.ipk|tachyon_*.apk)
|
||||
printf '%s\n' "$package_name" | sed 's/^tachyon_//;s/\.ipk$//;s/\.apk$//'
|
||||
;;
|
||||
luci-app-forkop_*.ipk|luci-app-forkop_*.apk)
|
||||
printf '%s\n' "$package_name" | sed 's/^luci-app-forkop_//;s/\.ipk$//;s/\.apk$//'
|
||||
luci-app-tachyon_*.ipk|luci-app-tachyon_*.apk)
|
||||
printf '%s\n' "$package_name" | sed 's/^luci-app-tachyon_//;s/\.ipk$//;s/\.apk$//'
|
||||
;;
|
||||
luci-i18n-forkop-ru_*.ipk|luci-i18n-forkop-ru_*.apk)
|
||||
printf '%s\n' "$package_name" | sed 's/^luci-i18n-forkop-ru_//;s/\.ipk$//;s/\.apk$//'
|
||||
luci-i18n-tachyon-ru_*.ipk|luci-i18n-tachyon-ru_*.apk)
|
||||
printf '%s\n' "$package_name" | sed 's/^luci-i18n-tachyon-ru_//;s/\.ipk$//;s/\.apk$//'
|
||||
;;
|
||||
*)
|
||||
printf '%s\n' "$package_name"
|
||||
@@ -1396,32 +1406,32 @@ fetch_github_latest_release_json() {
|
||||
printf '%s' "$response"
|
||||
}
|
||||
|
||||
resolve_forkop_release() {
|
||||
resolve_tachyon_release() {
|
||||
asset_ext="ipk"
|
||||
|
||||
[ "$PKG_IS_APK" -eq 1 ] && asset_ext="apk"
|
||||
|
||||
FORKOP_RELEASE_JSON="$(fetch_github_latest_release_json "$REPO_OWNER" "$REPO_NAME")"
|
||||
FORKOP_RELEASE_TAG="$(printf '%s' "$FORKOP_RELEASE_JSON" | install_json_ucode release-tag 2>/dev/null)"
|
||||
[ -n "$FORKOP_RELEASE_TAG" ] || fail "Failed to detect the Forkop release tag"
|
||||
TACHYON_RELEASE_JSON="$(fetch_github_latest_release_json "$REPO_OWNER" "$REPO_NAME")"
|
||||
TACHYON_RELEASE_TAG="$(printf '%s' "$TACHYON_RELEASE_JSON" | install_json_ucode release-tag 2>/dev/null)"
|
||||
[ -n "$TACHYON_RELEASE_TAG" ] || fail "Failed to detect the Tachyon release tag"
|
||||
|
||||
FORKOP_BACKEND_URL="$(printf '%s' "$FORKOP_RELEASE_JSON" | install_json_ucode release-asset-url backend "$asset_ext" 2>/dev/null)"
|
||||
[ -n "$FORKOP_BACKEND_URL" ] || fail "The Forkop release does not contain a forkop .$asset_ext package"
|
||||
TACHYON_BACKEND_URL="$(printf '%s' "$TACHYON_RELEASE_JSON" | install_json_ucode release-asset-url backend "$asset_ext" 2>/dev/null)"
|
||||
[ -n "$TACHYON_BACKEND_URL" ] || fail "The Tachyon release does not contain a tachyon .$asset_ext package"
|
||||
|
||||
FORKOP_APP_URL="$(printf '%s' "$FORKOP_RELEASE_JSON" | install_json_ucode release-asset-url app "$asset_ext" 2>/dev/null)"
|
||||
[ -n "$FORKOP_APP_URL" ] || fail "The Forkop release does not contain a luci-app-forkop .$asset_ext package"
|
||||
TACHYON_APP_URL="$(printf '%s' "$TACHYON_RELEASE_JSON" | install_json_ucode release-asset-url app "$asset_ext" 2>/dev/null)"
|
||||
[ -n "$TACHYON_APP_URL" ] || fail "The Tachyon release does not contain a luci-app-tachyon .$asset_ext package"
|
||||
|
||||
FORKOP_BACKEND_NAME="$(basename "$FORKOP_BACKEND_URL")"
|
||||
FORKOP_APP_NAME="$(basename "$FORKOP_APP_URL")"
|
||||
FORKOP_PACKAGE_VERSION="$(extract_package_version "$FORKOP_BACKEND_NAME")"
|
||||
TACHYON_BACKEND_NAME="$(basename "$TACHYON_BACKEND_URL")"
|
||||
TACHYON_APP_NAME="$(basename "$TACHYON_APP_URL")"
|
||||
TACHYON_PACKAGE_VERSION="$(extract_package_version "$TACHYON_BACKEND_NAME")"
|
||||
|
||||
FORKOP_I18N_URL=""
|
||||
FORKOP_I18N_NAME=""
|
||||
TACHYON_I18N_URL=""
|
||||
TACHYON_I18N_NAME=""
|
||||
|
||||
if [ "$FORKOP_I18N_REQUESTED" -eq 1 ]; then
|
||||
FORKOP_I18N_URL="$(printf '%s' "$FORKOP_RELEASE_JSON" | install_json_ucode release-asset-url i18n "$asset_ext" 2>/dev/null)"
|
||||
[ -n "$FORKOP_I18N_URL" ] || fail "The Forkop release does not contain a luci-i18n-forkop-ru .$asset_ext package"
|
||||
FORKOP_I18N_NAME="$(basename "$FORKOP_I18N_URL")"
|
||||
if [ "$TACHYON_I18N_REQUESTED" -eq 1 ]; then
|
||||
TACHYON_I18N_URL="$(printf '%s' "$TACHYON_RELEASE_JSON" | install_json_ucode release-asset-url i18n "$asset_ext" 2>/dev/null)"
|
||||
[ -n "$TACHYON_I18N_URL" ] || fail "The Tachyon release does not contain a luci-i18n-tachyon-ru .$asset_ext package"
|
||||
TACHYON_I18N_NAME="$(basename "$TACHYON_I18N_URL")"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -1436,11 +1446,11 @@ select_sing_box_installation() {
|
||||
answer=""
|
||||
default_choice=1
|
||||
|
||||
if [ "$FORKOP_LEGACY_DETECTED" -eq 1 ] &&
|
||||
if [ "$TACHYON_LEGACY_DETECTED" -eq 1 ] &&
|
||||
[ -r /etc/init.d/sing-box ] &&
|
||||
grep -Fq 'managed sing-box service for binary variants' /etc/init.d/sing-box; then
|
||||
SING_BOX_INSTALL_VARIANT="extended-compressed"
|
||||
msg "The legacy binary-managed sing-box variant will be reinstalled for Forkop"
|
||||
msg "The legacy binary-managed sing-box variant will be reinstalled for Tachyon"
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -1499,9 +1509,9 @@ install_selected_sing_box() {
|
||||
;;
|
||||
esac
|
||||
|
||||
[ -x /usr/bin/forkop ] || fail "forkop backend must be installed before sing-box component action"
|
||||
msg "Installing selected sing-box variant through Forkop ucode backend"
|
||||
if ! /usr/bin/forkop component_action sing_box "$action" >"$output_file" 2>&1; then
|
||||
[ -x /usr/bin/tachyon ] || fail "tachyon backend must be installed before sing-box component action"
|
||||
msg "Installing selected sing-box variant through Tachyon ucode backend"
|
||||
if ! /usr/bin/tachyon component_action sing_box "$action" >"$output_file" 2>&1; then
|
||||
cat "$output_file" >&2 2>/dev/null || true
|
||||
fail "Failed to install selected sing-box variant"
|
||||
fi
|
||||
@@ -1511,31 +1521,53 @@ cleanup_legacy_installation() {
|
||||
state_file="$TMP_DIR/install-state.env"
|
||||
|
||||
install_json_ucode installer-cleanup-legacy >"$state_file" ||
|
||||
fail "Failed to prepare the system before Forkop package installation"
|
||||
fail "Failed to prepare the system before Tachyon package installation"
|
||||
|
||||
# shellcheck disable=SC1090
|
||||
. "$state_file"
|
||||
}
|
||||
|
||||
detect_legacy_installation() {
|
||||
FORKOP_LEGACY_DETECTED=0
|
||||
TACHYON_LEGACY_DETECTED=0
|
||||
TACHYON_FORKOP_MIGRATION=0
|
||||
LEGACY_CONFIG_BACKUP=""
|
||||
|
||||
pkg_is_installed "$LEGACY_BACKEND_PACKAGE" || return 0
|
||||
if pkg_is_installed "forkop" || pkg_is_installed "luci-app-forkop"; then
|
||||
TACHYON_LEGACY_DETECTED=1
|
||||
TACHYON_FORKOP_MIGRATION=1
|
||||
fi
|
||||
|
||||
FORKOP_LEGACY_DETECTED=1
|
||||
for legacy_config_path in \
|
||||
"/etc/config/$LEGACY_BACKEND_PACKAGE" \
|
||||
"/etc/config/$LEGACY_CONFIG_PACKAGE_ALT"; do
|
||||
for legacy_config_path in "/etc/config/forkop" "/etc/config/forkop_plus"; do
|
||||
if [ -r "$legacy_config_path" ]; then
|
||||
LEGACY_CONFIG_BACKUP="$TMP_DIR/legacy-config.backup"
|
||||
cp "$legacy_config_path" "$LEGACY_CONFIG_BACKUP" ||
|
||||
fail "Failed to back up the legacy configuration"
|
||||
TACHYON_LEGACY_DETECTED=1
|
||||
TACHYON_FORKOP_MIGRATION=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
msg "Legacy installation detected; its packages will be removed and its configuration will be upgraded"
|
||||
if [ "$TACHYON_LEGACY_DETECTED" -eq 0 ]; then
|
||||
if pkg_is_installed "$LEGACY_BACKEND_PACKAGE"; then
|
||||
TACHYON_LEGACY_DETECTED=1
|
||||
fi
|
||||
for legacy_config_path in \
|
||||
"/etc/config/$LEGACY_BACKEND_PACKAGE" \
|
||||
"/etc/config/$LEGACY_CONFIG_PACKAGE_ALT"; do
|
||||
if [ -r "$legacy_config_path" ]; then
|
||||
LEGACY_CONFIG_BACKUP="$TMP_DIR/legacy-config.backup"
|
||||
cp "$legacy_config_path" "$LEGACY_CONFIG_BACKUP" ||
|
||||
fail "Failed to back up the legacy configuration"
|
||||
TACHYON_LEGACY_DETECTED=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$TACHYON_LEGACY_DETECTED" -eq 1 ]; then
|
||||
msg "Legacy installation detected; its packages will be removed and its configuration will be upgraded"
|
||||
fi
|
||||
}
|
||||
|
||||
decide_i18n_installation() {
|
||||
@@ -1543,22 +1575,22 @@ decide_i18n_installation() {
|
||||
|
||||
detect_installer_language
|
||||
|
||||
if pkg_is_installed "luci-i18n-forkop-ru"; then
|
||||
FORKOP_I18N_REQUESTED=1
|
||||
if pkg_is_installed "luci-i18n-tachyon-ru"; then
|
||||
TACHYON_I18N_REQUESTED=1
|
||||
msg "$(installer_text i18n_installed)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ "$FORKOP_LEGACY_DETECTED" -eq 1 ] &&
|
||||
if [ "$TACHYON_LEGACY_DETECTED" -eq 1 ] &&
|
||||
pkg_is_installed "luci-i18n-${LEGACY_BACKEND_PACKAGE}-ru"; then
|
||||
FORKOP_I18N_REQUESTED=1
|
||||
TACHYON_I18N_REQUESTED=1
|
||||
msg "$(installer_text i18n_installed)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
case "$luci_lang" in
|
||||
ru|ru_*|ru-*)
|
||||
FORKOP_I18N_REQUESTED=1
|
||||
TACHYON_I18N_REQUESTED=1
|
||||
INSTALLER_LANG="ru"
|
||||
msg "$(installer_text luci_ru)"
|
||||
return 0
|
||||
@@ -1566,7 +1598,7 @@ decide_i18n_installation() {
|
||||
esac
|
||||
|
||||
if confirm_prompt "$(installer_text i18n_prompt)"; then
|
||||
FORKOP_I18N_REQUESTED=1
|
||||
TACHYON_I18N_REQUESTED=1
|
||||
INSTALLER_LANG="ru"
|
||||
return 0
|
||||
fi
|
||||
@@ -1574,42 +1606,47 @@ decide_i18n_installation() {
|
||||
warn "$(installer_text i18n_skip)"
|
||||
}
|
||||
|
||||
download_forkop_packages() {
|
||||
FORKOP_BACKEND_FILE="$TMP_DIR/$FORKOP_BACKEND_NAME"
|
||||
FORKOP_APP_FILE="$TMP_DIR/$FORKOP_APP_NAME"
|
||||
FORKOP_I18N_FILE=""
|
||||
download_tachyon_packages() {
|
||||
TACHYON_BACKEND_FILE="$TMP_DIR/$TACHYON_BACKEND_NAME"
|
||||
TACHYON_APP_FILE="$TMP_DIR/$TACHYON_APP_NAME"
|
||||
TACHYON_I18N_FILE=""
|
||||
|
||||
download_with_retry "$FORKOP_BACKEND_URL" "$FORKOP_BACKEND_FILE" "$FORKOP_BACKEND_NAME" || fail "Failed to download $FORKOP_BACKEND_NAME"
|
||||
download_with_retry "$FORKOP_APP_URL" "$FORKOP_APP_FILE" "$FORKOP_APP_NAME" || fail "Failed to download $FORKOP_APP_NAME"
|
||||
download_with_retry "$TACHYON_BACKEND_URL" "$TACHYON_BACKEND_FILE" "$TACHYON_BACKEND_NAME" || fail "Failed to download $TACHYON_BACKEND_NAME"
|
||||
download_with_retry "$TACHYON_APP_URL" "$TACHYON_APP_FILE" "$TACHYON_APP_NAME" || fail "Failed to download $TACHYON_APP_NAME"
|
||||
|
||||
if [ -n "$FORKOP_I18N_URL" ]; then
|
||||
FORKOP_I18N_FILE="$TMP_DIR/$FORKOP_I18N_NAME"
|
||||
download_with_retry "$FORKOP_I18N_URL" "$FORKOP_I18N_FILE" "$FORKOP_I18N_NAME" || fail "Failed to download $FORKOP_I18N_NAME"
|
||||
if [ -n "$TACHYON_I18N_URL" ]; then
|
||||
TACHYON_I18N_FILE="$TMP_DIR/$TACHYON_I18N_NAME"
|
||||
download_with_retry "$TACHYON_I18N_URL" "$TACHYON_I18N_FILE" "$TACHYON_I18N_NAME" || fail "Failed to download $TACHYON_I18N_NAME"
|
||||
fi
|
||||
}
|
||||
|
||||
install_backend_package() {
|
||||
pkg_install_files "$FORKOP_BACKEND_FILE" || fail "forkop installation failed"
|
||||
pkg_install_files "$TACHYON_BACKEND_FILE" || fail "tachyon installation failed"
|
||||
}
|
||||
|
||||
migrate_legacy_configuration() {
|
||||
[ "$FORKOP_LEGACY_DETECTED" -eq 1 ] || return 0
|
||||
[ "$TACHYON_LEGACY_DETECTED" -eq 1 ] || return 0
|
||||
|
||||
if [ -n "$LEGACY_CONFIG_BACKUP" ]; then
|
||||
cp "$LEGACY_CONFIG_BACKUP" /etc/config/forkop ||
|
||||
cp "$LEGACY_CONFIG_BACKUP" /etc/config/tachyon ||
|
||||
fail "Failed to restore the legacy configuration for migration"
|
||||
chmod 0644 /etc/config/forkop ||
|
||||
fail "Failed to set permissions on the Forkop configuration"
|
||||
chmod 0644 /etc/config/tachyon ||
|
||||
fail "Failed to set permissions on the Tachyon configuration"
|
||||
|
||||
msg "Migrating the legacy configuration to Forkop"
|
||||
if ! FORKOP_CONFIG_NAME="forkop" \
|
||||
FORKOP_LIB="/usr/lib/forkop" \
|
||||
ucode -L /usr/lib/forkop /usr/lib/forkop/config/migration.uc migrate-podkop; then
|
||||
cp "$LEGACY_CONFIG_BACKUP" /etc/config/forkop 2>/dev/null || true
|
||||
msg "Migrating the legacy configuration to Tachyon"
|
||||
local migration_mode="migrate-podkop"
|
||||
if [ "$TACHYON_FORKOP_MIGRATION" -eq 1 ]; then
|
||||
migration_mode="migrate"
|
||||
fi
|
||||
|
||||
if ! TACHYON_CONFIG_NAME="tachyon" \
|
||||
TACHYON_LIB="/usr/lib/tachyon" \
|
||||
ucode -L /usr/lib/tachyon /usr/lib/tachyon/config/migration.uc "$migration_mode"; then
|
||||
cp "$LEGACY_CONFIG_BACKUP" /etc/config/tachyon 2>/dev/null || true
|
||||
fail "Legacy configuration migration failed; the original configuration was restored"
|
||||
fi
|
||||
else
|
||||
warn "The legacy package had no readable configuration; Forkop defaults will be used"
|
||||
warn "The legacy package had no readable configuration; Tachyon defaults will be used"
|
||||
fi
|
||||
|
||||
install_json_ucode installer-finalize-legacy ||
|
||||
@@ -1617,17 +1654,17 @@ migrate_legacy_configuration() {
|
||||
}
|
||||
|
||||
install_ui_packages() {
|
||||
pkg_install_files "$FORKOP_APP_FILE" || fail "luci-app-forkop installation failed"
|
||||
pkg_install_files "$TACHYON_APP_FILE" || fail "luci-app-tachyon installation failed"
|
||||
|
||||
if [ -n "$FORKOP_I18N_FILE" ]; then
|
||||
pkg_install_files "$FORKOP_I18N_FILE" || fail "luci-i18n-forkop-ru installation failed"
|
||||
if [ -n "$TACHYON_I18N_FILE" ]; then
|
||||
pkg_install_files "$TACHYON_I18N_FILE" || fail "luci-i18n-tachyon-ru installation failed"
|
||||
fi
|
||||
}
|
||||
|
||||
post_install() {
|
||||
FORKOP_WAS_ENABLED="$FORKOP_WAS_ENABLED" FORKOP_WAS_RUNNING="$FORKOP_WAS_RUNNING" \
|
||||
TACHYON_WAS_ENABLED="$TACHYON_WAS_ENABLED" TACHYON_WAS_RUNNING="$TACHYON_WAS_RUNNING" \
|
||||
install_json_ucode installer-post-install ||
|
||||
fail "Failed to complete Forkop post-install actions"
|
||||
fail "Failed to complete Tachyon post-install actions"
|
||||
}
|
||||
|
||||
main() {
|
||||
@@ -1647,8 +1684,8 @@ main() {
|
||||
pkg_list_update || fail "Failed to update package lists"
|
||||
ensure_bootstrap_ucode_runtime
|
||||
|
||||
resolve_forkop_release
|
||||
download_forkop_packages
|
||||
resolve_tachyon_release
|
||||
download_tachyon_packages
|
||||
|
||||
cleanup_legacy_installation
|
||||
install_backend_package
|
||||
@@ -1657,9 +1694,9 @@ main() {
|
||||
install_selected_sing_box
|
||||
post_install
|
||||
|
||||
msg "Forkop $FORKOP_PACKAGE_VERSION has been installed successfully"
|
||||
msg "Source release: ${REPO_OWNER}/${REPO_NAME}@${FORKOP_RELEASE_TAG}"
|
||||
warn "Open LuCI and review your rules before enabling Forkop"
|
||||
msg "Tachyon $TACHYON_PACKAGE_VERSION has been installed successfully"
|
||||
msg "Source release: ${REPO_OWNER}/${REPO_NAME}@${TACHYON_RELEASE_TAG}"
|
||||
warn "Open LuCI and review your rules before enabling Tachyon"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
+12
-12
@@ -1,34 +1,34 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-forkop
|
||||
PKG_NAME:=luci-app-tachyon
|
||||
|
||||
FORKOP_SOURCE_VERSION:=$(or $(FORKOP_PACKAGE_VERSION),$(FORKOP_VERSION))
|
||||
FORKOP_HAS_RELEASE_VERSION:=$(if $(filter dev,$(FORKOP_SOURCE_VERSION)),,$(FORKOP_SOURCE_VERSION))
|
||||
FORKOP_COMPILED_VERSION:=$(if $(FORKOP_HAS_RELEASE_VERSION),$(FORKOP_SOURCE_VERSION),$(or $(FORKOP_SOURCE_VERSION),dev))
|
||||
FORKOP_RELEASE_VERSION_VALID:=$(if $(FORKOP_HAS_RELEASE_VERSION),$(shell printf '%s\n' '$(FORKOP_SOURCE_VERSION)' | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$$' && printf '1'),1)
|
||||
TACHYON_SOURCE_VERSION:=$(or $(TACHYON_PACKAGE_VERSION),$(TACHYON_VERSION))
|
||||
TACHYON_HAS_RELEASE_VERSION:=$(if $(filter dev,$(TACHYON_SOURCE_VERSION)),,$(TACHYON_SOURCE_VERSION))
|
||||
TACHYON_COMPILED_VERSION:=$(if $(TACHYON_HAS_RELEASE_VERSION),$(TACHYON_SOURCE_VERSION),$(or $(TACHYON_SOURCE_VERSION),dev))
|
||||
TACHYON_RELEASE_VERSION_VALID:=$(if $(TACHYON_HAS_RELEASE_VERSION),$(shell printf '%s\n' '$(TACHYON_SOURCE_VERSION)' | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$$' && printf '1'),1)
|
||||
|
||||
ifeq ($(FORKOP_RELEASE_VERSION_VALID),)
|
||||
$(error FORKOP_PACKAGE_VERSION and FORKOP_VERSION must use x.y.z format)
|
||||
ifeq ($(TACHYON_RELEASE_VERSION_VALID),)
|
||||
$(error TACHYON_PACKAGE_VERSION and TACHYON_VERSION must use x.y.z format)
|
||||
endif
|
||||
|
||||
PKG_VERSION:=$(or $(FORKOP_HAS_RELEASE_VERSION),0.0.0)
|
||||
PKG_VERSION:=$(or $(TACHYON_HAS_RELEASE_VERSION),0.0.0)
|
||||
PKG_RELEASE:=
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
LUCI_TITLE:=LuCI Forkop app
|
||||
LUCI_DEPENDS:=+luci-base +forkop
|
||||
LUCI_TITLE:=LuCI Tachyon app
|
||||
LUCI_DEPENDS:=+luci-base +tachyon
|
||||
LUCI_PKGARCH:=all
|
||||
LUCI_LANG.ru:=Русский (Russian)
|
||||
LUCI_LANG.en:=English
|
||||
LUCI_MAINTAINER:=Dushnilin <dushnilin@gmail.com>
|
||||
LUCI_DESCRIPTION:=Rule-based Forkop LuCI app with hybrid sing-box + zapret orchestration
|
||||
LUCI_DESCRIPTION:=Rule-based Tachyon LuCI app with hybrid sing-box + zapret orchestration
|
||||
LUCI_MINIFY_JS:=0
|
||||
|
||||
PKG_LICENSE:=GPL-2.0-or-later
|
||||
LUCI_LANGUAGES:=en ru
|
||||
|
||||
define Build/Prepare/$(PKG_NAME)
|
||||
sed -i -e 's/__COMPILED_VERSION_VARIABLE__/$(FORKOP_COMPILED_VERSION)/g' $(PKG_BUILD_DIR)/htdocs/luci-static/resources/view/forkop/main.js || true
|
||||
sed -i -e 's/__COMPILED_VERSION_VARIABLE__/$(TACHYON_COMPILED_VERSION)/g' $(PKG_BUILD_DIR)/htdocs/luci-static/resources/view/tachyon/main.js || true
|
||||
endef
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"require ui";
|
||||
"require uci";
|
||||
"require fs";
|
||||
"require view.forkop.main as main";
|
||||
"require view.tachyon.main as main";
|
||||
|
||||
function createDashboardContent(section) {
|
||||
const o = section.option(form.DummyValue, "_mount_node");
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"require ui";
|
||||
"require uci";
|
||||
"require fs";
|
||||
"require view.forkop.main as main";
|
||||
"require view.tachyon.main as main";
|
||||
|
||||
function createDiagnosticContent(section) {
|
||||
const o = section.option(form.DummyValue, "_mount_node");
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"require baseclass";
|
||||
"require rpc";
|
||||
"require ui";
|
||||
"require view.forkop.main as main";
|
||||
"require view.tachyon.main as main";
|
||||
|
||||
const callHostHints = rpc.declare({
|
||||
object: "luci-rpc",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,8 @@
|
||||
"use strict";
|
||||
"require baseclass";
|
||||
"require form";
|
||||
"require view.forkop.local_devices as localDevices";
|
||||
"require view.forkop.main as main";
|
||||
"require view.tachyon.local_devices as localDevices";
|
||||
"require view.tachyon.main as main";
|
||||
|
||||
function createMonitoringContent(section) {
|
||||
const o = section.option(form.DummyValue, "_mount_node");
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
"require network";
|
||||
"require ui";
|
||||
"require uci";
|
||||
"require view.forkop.local_devices as localDevices";
|
||||
"require view.forkop.main as main";
|
||||
"require view.tachyon.local_devices as localDevices";
|
||||
"require view.tachyon.main as main";
|
||||
|
||||
const UCI_PACKAGE = main.FORKOP_UCI_PACKAGE;
|
||||
const UCI_PACKAGE = main.TACHYON_UCI_PACKAGE;
|
||||
const ACTION_PROVIDERS_AVAILABILITY_EVENT =
|
||||
main.FORKOP_ACTION_PROVIDERS_AVAILABILITY_EVENT ||
|
||||
"forkop:action-providers-availability";
|
||||
main.TACHYON_ACTION_PROVIDERS_AVAILABILITY_EVENT ||
|
||||
"tachyon:action-providers-availability";
|
||||
const RULE_SET_ITEM_SETTINGS_KEY = "rule_set_settings";
|
||||
const ROUTING_ACTIONS = [
|
||||
"connection",
|
||||
@@ -165,7 +165,7 @@ const BYEDPI_DEFAULT_CMD_OPTS = "-o 2 --auto=t,r,a,s -d 2";
|
||||
const ANNOTATED_TEXTAREA_STYLE_ID = "fkp-annotated-textarea-styles";
|
||||
const CONNECTIONS_DYNLIST_STYLE_ID = "fkp-connections-dynlist-styles";
|
||||
const NFQWS_REMOTE_VALIDATION_DEBOUNCE_MS = 500;
|
||||
const NFQWS_VALIDATION_COMMAND = "/usr/bin/forkop";
|
||||
const NFQWS_VALIDATION_COMMAND = "/usr/bin/tachyon";
|
||||
const nfqwsRemoteValidationCache = new Map();
|
||||
const nfqwsRemoteValidationInflight = new Map();
|
||||
const nfqws2RemoteValidationCache = new Map();
|
||||
@@ -431,7 +431,7 @@ let actionProvidersAvailabilityLoader = null;
|
||||
const outboundNameChoicesCache = new Map();
|
||||
const outboundNameChoicesInflight = new Map();
|
||||
const outboundNameSourceOptions = new Map();
|
||||
const SECTION_CACHE_DIR = "/var/run/forkop/section-cache";
|
||||
const SECTION_CACHE_DIR = "/var/run/tachyon/section-cache";
|
||||
const COUNTRY_CODES =
|
||||
"AD AE AF AG AI AL AM AO AQ AR AS AT AU AW AX AZ BA BB BD BE BF BG BH BI BJ BL BM BN BO BQ BR BS BT BV BW BY BZ CA CC CD CF CG CH CI CK CL CM CN CO CR CU CV CW CX CY CZ DE DJ DK DM DO DZ EC EE EG EH ER ES ET FI FJ FK FM FO FR GA GB GD GE GF GG GH GI GL GM GN GP GQ GR GS GT GU GW GY HK HM HN HR HT HU ID IE IL IM IN IO IQ IR IS IT JE JM JO JP KE KG KH KI KM KN KP KR KW KY KZ LA LB LC LI LK LR LS LT LU LV LY MA MC MD ME MF MG MH MK ML MM MN MO MP MQ MR MS MT MU MV MW MX MY MZ NA NC NE NF NG NI NL NO NP NR NU NZ OM PA PE PF PG PH PK PL PM PN PR PS PT PW PY QA RE RO RS RU RW SA SB SC SD SE SG SH SI SJ SK SL SM SN SO SR SS ST SV SX SY SZ TC TD TF TG TH TJ TK TL TM TN TO TR TT TV TW TZ UA UG UM US UY UZ VA VC VE VG VI VN VU WF WS YE YT ZA ZM ZW XK".split(
|
||||
" ",
|
||||
@@ -3550,9 +3550,9 @@ function ensureActionProvidersAvailabilityLoaded() {
|
||||
}
|
||||
|
||||
actionProvidersAvailabilityPromise = Promise.allSettled([
|
||||
main.ForkopShellMethods.checkZapretRuntime(),
|
||||
main.ForkopShellMethods.checkZapret2Runtime(),
|
||||
main.ForkopShellMethods.checkByedpiRuntime(),
|
||||
main.TachyonShellMethods.checkZapretRuntime(),
|
||||
main.TachyonShellMethods.checkZapret2Runtime(),
|
||||
main.TachyonShellMethods.checkByedpiRuntime(),
|
||||
])
|
||||
.then(([zapretResult, zapret2Result, byedpiResult]) => {
|
||||
const zapret =
|
||||
@@ -4441,9 +4441,9 @@ function attachAnnotatedTextarea(textarea, analyzer) {
|
||||
|
||||
ensureAnnotatedTextareaStyles();
|
||||
|
||||
if (textarea.__forkopAnnotatedTextareaController) {
|
||||
textarea.__forkopAnnotatedTextareaController.analyzer = analyzer;
|
||||
textarea.__forkopAnnotatedTextareaController.update();
|
||||
if (textarea.__tachyonAnnotatedTextareaController) {
|
||||
textarea.__tachyonAnnotatedTextareaController.analyzer = analyzer;
|
||||
textarea.__tachyonAnnotatedTextareaController.update();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4474,7 +4474,7 @@ function attachAnnotatedTextarea(textarea, analyzer) {
|
||||
},
|
||||
};
|
||||
|
||||
textarea.__forkopAnnotatedTextareaController = controller;
|
||||
textarea.__tachyonAnnotatedTextareaController = controller;
|
||||
|
||||
const updateAnnotatedTextarea = () => controller.update();
|
||||
textarea.addEventListener("input", updateAnnotatedTextarea);
|
||||
@@ -4500,21 +4500,21 @@ function refreshAnnotatedTextareaValidation(option, section_id, textarea) {
|
||||
|
||||
if (
|
||||
textarea &&
|
||||
textarea.__forkopAnnotatedTextareaController &&
|
||||
typeof textarea.__forkopAnnotatedTextareaController.update === "function"
|
||||
textarea.__tachyonAnnotatedTextareaController &&
|
||||
typeof textarea.__tachyonAnnotatedTextareaController.update === "function"
|
||||
) {
|
||||
textarea.__forkopAnnotatedTextareaController.update();
|
||||
textarea.__tachyonAnnotatedTextareaController.update();
|
||||
}
|
||||
}
|
||||
|
||||
function attachNfqwsRemoteValidation(option, section_id, textarea) {
|
||||
if (!textarea || textarea.__forkopNfqwsRemoteValidationAttached) {
|
||||
if (!textarea || textarea.__tachyonNfqwsRemoteValidationAttached) {
|
||||
return;
|
||||
}
|
||||
|
||||
textarea.__forkopNfqwsRemoteValidationAttached = true;
|
||||
textarea.__forkopNfqwsRemoteValidationRequestId = 0;
|
||||
textarea.__forkopNfqwsRemoteValidationTimer = null;
|
||||
textarea.__tachyonNfqwsRemoteValidationAttached = true;
|
||||
textarea.__tachyonNfqwsRemoteValidationRequestId = 0;
|
||||
textarea.__tachyonNfqwsRemoteValidationTimer = null;
|
||||
|
||||
const runValidation = () => {
|
||||
const value = textarea.value;
|
||||
@@ -4525,11 +4525,11 @@ function attachNfqwsRemoteValidation(option, section_id, textarea) {
|
||||
}
|
||||
|
||||
const requestId =
|
||||
(textarea.__forkopNfqwsRemoteValidationRequestId || 0) + 1;
|
||||
textarea.__forkopNfqwsRemoteValidationRequestId = requestId;
|
||||
(textarea.__tachyonNfqwsRemoteValidationRequestId || 0) + 1;
|
||||
textarea.__tachyonNfqwsRemoteValidationRequestId = requestId;
|
||||
|
||||
validateNfqwsStrategyRemotely(value).then(() => {
|
||||
if (textarea.__forkopNfqwsRemoteValidationRequestId !== requestId) {
|
||||
if (textarea.__tachyonNfqwsRemoteValidationRequestId !== requestId) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4538,12 +4538,12 @@ function attachNfqwsRemoteValidation(option, section_id, textarea) {
|
||||
};
|
||||
|
||||
const scheduleValidation = (delay = NFQWS_REMOTE_VALIDATION_DEBOUNCE_MS) => {
|
||||
if (textarea.__forkopNfqwsRemoteValidationTimer) {
|
||||
window.clearTimeout(textarea.__forkopNfqwsRemoteValidationTimer);
|
||||
if (textarea.__tachyonNfqwsRemoteValidationTimer) {
|
||||
window.clearTimeout(textarea.__tachyonNfqwsRemoteValidationTimer);
|
||||
}
|
||||
|
||||
textarea.__forkopNfqwsRemoteValidationTimer = window.setTimeout(() => {
|
||||
textarea.__forkopNfqwsRemoteValidationTimer = null;
|
||||
textarea.__tachyonNfqwsRemoteValidationTimer = window.setTimeout(() => {
|
||||
textarea.__tachyonNfqwsRemoteValidationTimer = null;
|
||||
runValidation();
|
||||
}, delay);
|
||||
};
|
||||
@@ -4556,13 +4556,13 @@ function attachNfqwsRemoteValidation(option, section_id, textarea) {
|
||||
}
|
||||
|
||||
function attachNfqws2RemoteValidation(option, section_id, textarea) {
|
||||
if (!textarea || textarea.__forkopNfqws2RemoteValidationAttached) {
|
||||
if (!textarea || textarea.__tachyonNfqws2RemoteValidationAttached) {
|
||||
return;
|
||||
}
|
||||
|
||||
textarea.__forkopNfqws2RemoteValidationAttached = true;
|
||||
textarea.__forkopNfqws2RemoteValidationRequestId = 0;
|
||||
textarea.__forkopNfqws2RemoteValidationTimer = null;
|
||||
textarea.__tachyonNfqws2RemoteValidationAttached = true;
|
||||
textarea.__tachyonNfqws2RemoteValidationRequestId = 0;
|
||||
textarea.__tachyonNfqws2RemoteValidationTimer = null;
|
||||
|
||||
const runValidation = () => {
|
||||
const value = textarea.value;
|
||||
@@ -4573,11 +4573,11 @@ function attachNfqws2RemoteValidation(option, section_id, textarea) {
|
||||
}
|
||||
|
||||
const requestId =
|
||||
(textarea.__forkopNfqws2RemoteValidationRequestId || 0) + 1;
|
||||
textarea.__forkopNfqws2RemoteValidationRequestId = requestId;
|
||||
(textarea.__tachyonNfqws2RemoteValidationRequestId || 0) + 1;
|
||||
textarea.__tachyonNfqws2RemoteValidationRequestId = requestId;
|
||||
|
||||
validateNfqws2StrategyRemotely(value).then(() => {
|
||||
if (textarea.__forkopNfqws2RemoteValidationRequestId !== requestId) {
|
||||
if (textarea.__tachyonNfqws2RemoteValidationRequestId !== requestId) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4586,12 +4586,12 @@ function attachNfqws2RemoteValidation(option, section_id, textarea) {
|
||||
};
|
||||
|
||||
const scheduleValidation = (delay = NFQWS_REMOTE_VALIDATION_DEBOUNCE_MS) => {
|
||||
if (textarea.__forkopNfqws2RemoteValidationTimer) {
|
||||
window.clearTimeout(textarea.__forkopNfqws2RemoteValidationTimer);
|
||||
if (textarea.__tachyonNfqws2RemoteValidationTimer) {
|
||||
window.clearTimeout(textarea.__tachyonNfqws2RemoteValidationTimer);
|
||||
}
|
||||
|
||||
textarea.__forkopNfqws2RemoteValidationTimer = window.setTimeout(() => {
|
||||
textarea.__forkopNfqws2RemoteValidationTimer = null;
|
||||
textarea.__tachyonNfqws2RemoteValidationTimer = window.setTimeout(() => {
|
||||
textarea.__tachyonNfqws2RemoteValidationTimer = null;
|
||||
runValidation();
|
||||
}, delay);
|
||||
};
|
||||
@@ -5026,7 +5026,7 @@ function validateNfqwsStrategyRemotely(value) {
|
||||
|
||||
function getNfqwsForbiddenTokenInfo(token, index) {
|
||||
const configFileMessage = _(
|
||||
"External nfqws config files bypass Forkop queue management and explicit validation.",
|
||||
"External nfqws config files bypass Tachyon queue management and explicit validation.",
|
||||
);
|
||||
const hostSelectionMessage = _(
|
||||
"Resource selection by hostname inside nfqws is not supported here; sing-box selects resources before NFQUEUE.",
|
||||
@@ -5035,16 +5035,16 @@ function getNfqwsForbiddenTokenInfo(token, index) {
|
||||
"Resource selection by IP or CIDR inside nfqws is not supported here; sing-box selects resources before NFQUEUE.",
|
||||
);
|
||||
const placeholderMessage = _(
|
||||
"Zapret hostlist templates are not supported here because Forkop does not expand them for per-rule NFQWS strategies.",
|
||||
"Zapret hostlist templates are not supported here because Tachyon does not expand them for per-rule NFQWS strategies.",
|
||||
);
|
||||
const queueMessage = _(
|
||||
"The NFQUEUE number is assigned by Forkop for each rule and must not be overridden here.",
|
||||
"The NFQUEUE number is assigned by Tachyon for each rule and must not be overridden here.",
|
||||
);
|
||||
const fwmarkMessage = _(
|
||||
"The desync fwmark is managed by Forkop for loop prevention and must not be overridden here.",
|
||||
"The desync fwmark is managed by Tachyon for loop prevention and must not be overridden here.",
|
||||
);
|
||||
const daemonMessage = _(
|
||||
"Forkop manages the nfqws process lifecycle itself, so daemon mode is not allowed here.",
|
||||
"Tachyon manages the nfqws process lifecycle itself, so daemon mode is not allowed here.",
|
||||
);
|
||||
const dryRunMessage = _(
|
||||
"This field must start a working nfqws strategy; --dry-run exits immediately and is not allowed here.",
|
||||
@@ -5471,7 +5471,7 @@ function validateNfqws2StrategyRemotely(value) {
|
||||
|
||||
function getNfqws2ForbiddenTokenInfo(token, index, nextToken) {
|
||||
const configFileMessage = _(
|
||||
"External nfqws2 config files bypass Forkop queue management and explicit validation.",
|
||||
"External nfqws2 config files bypass Tachyon queue management and explicit validation.",
|
||||
);
|
||||
const hostSelectionMessage = _(
|
||||
"Resource selection by hostname inside nfqws2 is not supported here; sing-box selects resources before NFQUEUE.",
|
||||
@@ -5480,22 +5480,22 @@ function getNfqws2ForbiddenTokenInfo(token, index, nextToken) {
|
||||
"Resource selection by IP or CIDR inside nfqws2 is not supported here; sing-box selects resources before NFQUEUE.",
|
||||
);
|
||||
const placeholderMessage = _(
|
||||
"Zapret2 hostlist templates are not supported here because Forkop does not expand them for per-rule NFQWS2 strategies.",
|
||||
"Zapret2 hostlist templates are not supported here because Tachyon does not expand them for per-rule NFQWS2 strategies.",
|
||||
);
|
||||
const queueMessage = _(
|
||||
"The NFQUEUE number is assigned by Forkop for each rule and must not be overridden here.",
|
||||
"The NFQUEUE number is assigned by Tachyon for each rule and must not be overridden here.",
|
||||
);
|
||||
const fwmarkMessage = _(
|
||||
"The desync fwmark is managed by Forkop for loop prevention and must not be overridden here.",
|
||||
"The desync fwmark is managed by Tachyon for loop prevention and must not be overridden here.",
|
||||
);
|
||||
const fuzzMessage = _(
|
||||
"Fuzzing is not supported here because Forkop needs deterministic runtime validation.",
|
||||
"Fuzzing is not supported here because Tachyon needs deterministic runtime validation.",
|
||||
);
|
||||
const interceptMessage = _(
|
||||
"Disabling interception is incompatible with action=zapret2 because Forkop sends matched traffic through NFQUEUE.",
|
||||
"Disabling interception is incompatible with action=zapret2 because Tachyon sends matched traffic through NFQUEUE.",
|
||||
);
|
||||
const daemonMessage = _(
|
||||
"Forkop manages the nfqws2 process lifecycle itself, so daemon mode is not allowed here.",
|
||||
"Tachyon manages the nfqws2 process lifecycle itself, so daemon mode is not allowed here.",
|
||||
);
|
||||
const dryRunMessage = _(
|
||||
"This field must start a working nfqws2 strategy; --dry-run exits immediately and is not allowed here.",
|
||||
@@ -5891,16 +5891,16 @@ function byedpiTokenLooksLikeOption(token) {
|
||||
|
||||
function getByedpiControlledTokenInfo(token) {
|
||||
const listenMessage = _(
|
||||
"ByeDPI listen address and port are assigned by Forkop and must not be set in the strategy.",
|
||||
"ByeDPI listen address and port are assigned by Tachyon and must not be set in the strategy.",
|
||||
);
|
||||
const transparentMessage = _(
|
||||
"Transparent proxy mode is incompatible with action=byedpi because Forkop connects to ciadpi through SOCKS.",
|
||||
"Transparent proxy mode is incompatible with action=byedpi because Tachyon connects to ciadpi through SOCKS.",
|
||||
);
|
||||
const daemonMessage = _(
|
||||
"Forkop manages the ciadpi process lifecycle itself, so daemon mode is not allowed here.",
|
||||
"Tachyon manages the ciadpi process lifecycle itself, so daemon mode is not allowed here.",
|
||||
);
|
||||
const pidfileMessage = _(
|
||||
"Forkop manages ciadpi pid files itself, so pidfile options are not allowed here.",
|
||||
"Tachyon manages ciadpi pid files itself, so pidfile options are not allowed here.",
|
||||
);
|
||||
const exitMessage = _(
|
||||
"This field must start a working ciadpi strategy; help/version options exit immediately and are not allowed here.",
|
||||
@@ -6630,7 +6630,7 @@ function createSectionContent(section) {
|
||||
form.ListValue,
|
||||
"action",
|
||||
_("Action"),
|
||||
_("What Forkop should do when this section matches"),
|
||||
_("What Tachyon should do when this section matches"),
|
||||
);
|
||||
populateActionOptionValues(o);
|
||||
o.default = "connection";
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
"require rpc";
|
||||
"require uci";
|
||||
"require ui";
|
||||
"require view.forkop.main as main";
|
||||
"require view.tachyon.main as main";
|
||||
|
||||
const UCI_PACKAGE = main.FORKOP_UCI_PACKAGE;
|
||||
const UCI_PACKAGE = main.TACHYON_UCI_PACKAGE;
|
||||
const ROUTING_SECTION_ACTIONS = [
|
||||
"connection",
|
||||
"proxy",
|
||||
@@ -385,7 +385,7 @@ function qrSvgDataUri(text) {
|
||||
return `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
||||
}
|
||||
|
||||
const SERVER_STYLE_ID = "forkop-server-styles";
|
||||
const SERVER_STYLE_ID = "tachyon-server-styles";
|
||||
const DEFAULT_SERVER_PROTOCOL = "tailscale";
|
||||
const FALLBACK_SERVER_PROTOCOL = "vless";
|
||||
const STREAM_PROTOCOLS = ["vless", "vmess", "trojan"];
|
||||
@@ -938,15 +938,15 @@ function serverSafeName(sectionId) {
|
||||
}
|
||||
|
||||
function defaultTlsCertificatePath(sectionId) {
|
||||
return `/etc/forkop/server-certs/${serverSafeName(sectionId)}.crt`;
|
||||
return `/etc/tachyon/server-certs/${serverSafeName(sectionId)}.crt`;
|
||||
}
|
||||
|
||||
function defaultTlsKeyPath(sectionId) {
|
||||
return `/etc/forkop/server-certs/${serverSafeName(sectionId)}.key`;
|
||||
return `/etc/tachyon/server-certs/${serverSafeName(sectionId)}.key`;
|
||||
}
|
||||
|
||||
function defaultTailscaleHostname(sectionId) {
|
||||
return `forkop-${serverSafeName(sectionId)}`;
|
||||
return `tachyon-${serverSafeName(sectionId)}`;
|
||||
}
|
||||
|
||||
function setDefault(sectionId, key, value) {
|
||||
@@ -1356,7 +1356,7 @@ function loadGeneratedTlsCertificatePin(sectionId) {
|
||||
}
|
||||
|
||||
return fs
|
||||
.exec("/usr/bin/forkop", ["get_tls_certificate_sha256", sectionId])
|
||||
.exec("/usr/bin/tachyon", ["get_tls_certificate_sha256", sectionId])
|
||||
.then((response) => {
|
||||
if ((response.code ?? 0) !== 0 || !response.stdout) {
|
||||
throw new Error(response.stderr || response.stdout || "");
|
||||
@@ -2262,7 +2262,7 @@ function hasRealityKeypair(sectionId) {
|
||||
|
||||
function generateRealityKeypair(sectionId) {
|
||||
return fs
|
||||
.exec("/usr/bin/forkop", ["generate_reality_keypair"])
|
||||
.exec("/usr/bin/tachyon", ["generate_reality_keypair"])
|
||||
.then((response) => {
|
||||
if ((response.code ?? 0) !== 0 || !response.stdout) {
|
||||
throw new Error(response.stderr || response.stdout || "");
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
"require uci";
|
||||
"require baseclass";
|
||||
"require tools.widgets as widgets";
|
||||
"require view.forkop.main as main";
|
||||
"require view.tachyon.main as main";
|
||||
|
||||
const UCI_PACKAGE = main.FORKOP_UCI_PACKAGE;
|
||||
const UCI_PACKAGE = main.TACHYON_UCI_PACKAGE;
|
||||
|
||||
function isSingBoxDuration(value) {
|
||||
return /^([0-9]+(?:\.[0-9]+)?(?:ns|us|ms|s|m|h|d))+$/.test(value);
|
||||
@@ -124,8 +124,8 @@ function configureDnsList(option, choices, defaultValue) {
|
||||
}
|
||||
|
||||
function configureDnsFailoverVisibility(option, dnsOption, bootstrapOption) {
|
||||
option.depends("dns_server", "__forkop_multiple_dns__");
|
||||
option.depends("bootstrap_dns_server", "__forkop_multiple_dns__");
|
||||
option.depends("dns_server", "__tachyon_multiple_dns__");
|
||||
option.depends("bootstrap_dns_server", "__tachyon_multiple_dns__");
|
||||
option.retain = true;
|
||||
option.checkDepends = function (section_id) {
|
||||
return (
|
||||
@@ -395,7 +395,7 @@ function createSettingsContent(section, capabilities) {
|
||||
form.Value,
|
||||
"badwan_reload_delay",
|
||||
_("Interface Monitoring Delay"),
|
||||
_("Delay in milliseconds before reloading Forkop after interface UP"),
|
||||
_("Delay in milliseconds before reloading Tachyon after interface UP"),
|
||||
);
|
||||
o.depends("enable_badwan_interface_monitoring", "1");
|
||||
o.default = "2000";
|
||||
@@ -599,7 +599,7 @@ function createSettingsContent(section, capabilities) {
|
||||
form.Flag,
|
||||
"dont_touch_dhcp",
|
||||
_("Dont Touch My DHCP!"),
|
||||
_("Forkop will not modify your DHCP configuration"),
|
||||
_("Tachyon will not modify your DHCP configuration"),
|
||||
);
|
||||
o.default = "0";
|
||||
o.rmempty = false;
|
||||
|
||||
@@ -4,30 +4,30 @@
|
||||
"require baseclass";
|
||||
"require uci";
|
||||
"require ui";
|
||||
"require view.forkop.main as main";
|
||||
"require view.tachyon.main as main";
|
||||
|
||||
// Global settings
|
||||
"require view.forkop.settings as settings";
|
||||
"require view.tachyon.settings as settings";
|
||||
|
||||
// Sections
|
||||
"require view.forkop.section as section";
|
||||
"require view.tachyon.section as section";
|
||||
|
||||
// Server
|
||||
"require view.forkop.server as server";
|
||||
"require view.tachyon.server as server";
|
||||
|
||||
// Dashboard
|
||||
"require view.forkop.dashboard as dashboard";
|
||||
"require view.tachyon.dashboard as dashboard";
|
||||
|
||||
// Monitoring
|
||||
"require view.forkop.monitoring as monitoring";
|
||||
"require view.tachyon.monitoring as monitoring";
|
||||
|
||||
// Diagnostic
|
||||
"require view.forkop.diagnostic as diagnostic";
|
||||
"require view.tachyon.diagnostic as diagnostic";
|
||||
|
||||
// Updates
|
||||
"require view.forkop.updates as updates";
|
||||
"require view.tachyon.updates as updates";
|
||||
|
||||
const UCI_PACKAGE = main.FORKOP_UCI_PACKAGE;
|
||||
const UCI_PACKAGE = main.TACHYON_UCI_PACKAGE;
|
||||
const CBI_PREFIX = UCI_PACKAGE;
|
||||
|
||||
function renderSectionAdd(sectionRef, extra_class) {
|
||||
@@ -121,7 +121,7 @@ const EntryPoint = {
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent(main.FORKOP_ACTION_PROVIDERS_AVAILABILITY_EVENT, {
|
||||
new CustomEvent(main.TACHYON_ACTION_PROVIDERS_AVAILABILITY_EVENT, {
|
||||
detail: {
|
||||
zapretInstalled: uiCapabilities.zapretInstalled,
|
||||
zapret2Installed: uiCapabilities.zapret2Installed,
|
||||
@@ -209,9 +209,9 @@ const EntryPoint = {
|
||||
failed: false,
|
||||
data: {
|
||||
singbox: Number(data.service.sing_box?.running) || 0,
|
||||
forkopRunning: Number(data.service.forkop?.running) || 0,
|
||||
forkopEnabled: Number(data.service.forkop?.enabled) || 0,
|
||||
forkopStatus: data.service.forkop?.status || "",
|
||||
tachyonRunning: Number(data.service.tachyon?.running) || 0,
|
||||
tachyonEnabled: Number(data.service.tachyon?.enabled) || 0,
|
||||
tachyonStatus: data.service.tachyon?.status || "",
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -222,11 +222,11 @@ const EntryPoint = {
|
||||
|
||||
const loadFallbackUiCapabilities = function () {
|
||||
return Promise.allSettled([
|
||||
main.ForkopShellMethods.getServerCapabilities(),
|
||||
main.ForkopShellMethods.checkZapretRuntime(),
|
||||
main.ForkopShellMethods.checkZapret2Runtime(),
|
||||
main.ForkopShellMethods.checkByedpiRuntime(),
|
||||
main.ForkopShellMethods.checkInboundsConfig(),
|
||||
main.TachyonShellMethods.getServerCapabilities(),
|
||||
main.TachyonShellMethods.checkZapretRuntime(),
|
||||
main.TachyonShellMethods.checkZapret2Runtime(),
|
||||
main.TachyonShellMethods.checkByedpiRuntime(),
|
||||
main.TachyonShellMethods.checkInboundsConfig(),
|
||||
]).then(
|
||||
([
|
||||
serverCapabilitiesResult,
|
||||
@@ -308,7 +308,7 @@ const EntryPoint = {
|
||||
return uiCapabilitiesPromise;
|
||||
}
|
||||
|
||||
uiCapabilitiesPromise = main.ForkopShellMethods.getUiCapabilities()
|
||||
uiCapabilitiesPromise = main.TachyonShellMethods.getUiCapabilities()
|
||||
.then((response) => {
|
||||
if (!response?.success) {
|
||||
throw new Error("UI capabilities request failed");
|
||||
@@ -317,8 +317,8 @@ const EntryPoint = {
|
||||
return updateUiCapabilities(response.data);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.warn("Failed to load Forkop UI capabilities", error);
|
||||
return main.ForkopShellMethods.getUiState()
|
||||
console.warn("Failed to load Tachyon UI capabilities", error);
|
||||
return main.TachyonShellMethods.getUiState()
|
||||
.then((response) => {
|
||||
if (!response?.success) {
|
||||
throw new Error("UI state request failed");
|
||||
@@ -327,7 +327,7 @@ const EntryPoint = {
|
||||
return applyUiState(response.data);
|
||||
})
|
||||
.catch((fallbackError) => {
|
||||
console.warn("Failed to load Forkop UI state", fallbackError);
|
||||
console.warn("Failed to load Tachyon UI state", fallbackError);
|
||||
return loadFallbackUiCapabilities();
|
||||
});
|
||||
})
|
||||
@@ -337,16 +337,16 @@ const EntryPoint = {
|
||||
|
||||
return uiCapabilitiesPromise;
|
||||
};
|
||||
const forkopMap = new form.Map(
|
||||
const tachyonMap = new form.Map(
|
||||
UCI_PACKAGE,
|
||||
_("Forkop Settings"),
|
||||
_("Configuration for Forkop service"),
|
||||
_("Tachyon Settings"),
|
||||
_("Configuration for Tachyon service"),
|
||||
);
|
||||
forkopMap.tabbed = true;
|
||||
const originalHandleSaveApply = forkopMap.handleSaveApply;
|
||||
forkopMap.handleSaveApply = function (ev, mode) {
|
||||
tachyonMap.tabbed = true;
|
||||
const originalHandleSaveApply = tachyonMap.handleSaveApply;
|
||||
tachyonMap.handleSaveApply = function (ev, mode) {
|
||||
const refreshUiState = function () {
|
||||
main.ForkopShellMethods.getUiState()
|
||||
main.TachyonShellMethods.getUiState()
|
||||
.then((response) => {
|
||||
if (
|
||||
response?.success &&
|
||||
@@ -365,7 +365,7 @@ const EntryPoint = {
|
||||
...servicesInfoWidget,
|
||||
data: {
|
||||
...servicesInfoWidget.data,
|
||||
forkopStatus: "reloading",
|
||||
tachyonStatus: "reloading",
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -384,7 +384,7 @@ const EntryPoint = {
|
||||
});
|
||||
};
|
||||
|
||||
const rulesSection = forkopMap.section(
|
||||
const rulesSection = tachyonMap.section(
|
||||
form.GridSection,
|
||||
"section",
|
||||
_("Sections"),
|
||||
@@ -401,7 +401,7 @@ const EntryPoint = {
|
||||
});
|
||||
section.createSectionContent(rulesSection);
|
||||
|
||||
const serverSection = forkopMap.section(
|
||||
const serverSection = tachyonMap.section(
|
||||
form.GridSection,
|
||||
"server",
|
||||
_("Servers"),
|
||||
@@ -419,7 +419,7 @@ const EntryPoint = {
|
||||
});
|
||||
server.createServerContent(serverSection, uiCapabilities);
|
||||
|
||||
const settingsSection = forkopMap.section(
|
||||
const settingsSection = tachyonMap.section(
|
||||
form.TypedSection,
|
||||
"settings",
|
||||
_("Settings"),
|
||||
@@ -431,7 +431,7 @@ const EntryPoint = {
|
||||
};
|
||||
settings.createSettingsContent(settingsSection, uiCapabilities);
|
||||
|
||||
const diagnosticSection = forkopMap.section(
|
||||
const diagnosticSection = tachyonMap.section(
|
||||
form.TypedSection,
|
||||
"diagnostic",
|
||||
_("Diagnostics"),
|
||||
@@ -443,7 +443,7 @@ const EntryPoint = {
|
||||
};
|
||||
diagnostic.createDiagnosticContent(diagnosticSection);
|
||||
|
||||
const dashboardSection = forkopMap.section(
|
||||
const dashboardSection = tachyonMap.section(
|
||||
form.TypedSection,
|
||||
"dashboard",
|
||||
_("Dashboard"),
|
||||
@@ -455,7 +455,7 @@ const EntryPoint = {
|
||||
};
|
||||
dashboard.createDashboardContent(dashboardSection);
|
||||
|
||||
const monitoringSection = forkopMap.section(
|
||||
const monitoringSection = tachyonMap.section(
|
||||
form.TypedSection,
|
||||
"monitoring",
|
||||
_("Monitoring"),
|
||||
@@ -467,7 +467,7 @@ const EntryPoint = {
|
||||
};
|
||||
monitoring.createMonitoringContent(monitoringSection);
|
||||
|
||||
const updatesSection = forkopMap.section(
|
||||
const updatesSection = tachyonMap.section(
|
||||
form.TypedSection,
|
||||
"updates",
|
||||
_("Components"),
|
||||
@@ -481,7 +481,7 @@ const EntryPoint = {
|
||||
|
||||
await loadUiCapabilities().catch(() => null);
|
||||
|
||||
const rendered = await forkopMap.render();
|
||||
const rendered = await tachyonMap.render();
|
||||
main.coreService({
|
||||
waitForLogWatcherStart: loadUiCapabilities,
|
||||
logWatcherStartDelayMs: 5000,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"require ui";
|
||||
"require uci";
|
||||
"require fs";
|
||||
"require view.forkop.main as main";
|
||||
"require view.tachyon.main as main";
|
||||
|
||||
function createUpdatesContent(section) {
|
||||
const o = section.option(form.DummyValue, "_mount_node");
|
||||
|
||||
+112
-112
@@ -1,15 +1,15 @@
|
||||
# RU translations for FORKOP package.
|
||||
# Copyright (C) 2026 THE FORKOP COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the FORKOP package.
|
||||
# ushan0v, 2026.
|
||||
# RU translations for TACHYON package.
|
||||
# Copyright (C) 2026 THE TACHYON COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the TACHYON package.
|
||||
# Dushnilin, 2026.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: FORKOP\n"
|
||||
"Project-Id-Version: TACHYON\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-07-13 03:22+0300\n"
|
||||
"PO-Revision-Date: 2026-07-13 03:22+0300\n"
|
||||
"Last-Translator: ushan0v\n"
|
||||
"POT-Creation-Date: 2026-07-13 13:18+0300\n"
|
||||
"PO-Revision-Date: 2026-07-13 13:18+0300\n"
|
||||
"Last-Translator: Dushnilin\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -191,8 +191,8 @@ msgstr "Встроенные наборы правил"
|
||||
msgid "By flag emoji from name"
|
||||
msgstr "По эмодзи флага из названия"
|
||||
|
||||
msgid "ByeDPI listen address and port are assigned by Forkop and must not be set in the strategy."
|
||||
msgstr "Адрес и порт прослушивания ByeDPI назначаются Forkop и не должны задаваться в стратегии."
|
||||
msgid "ByeDPI listen address and port are assigned by Tachyon and must not be set in the strategy."
|
||||
msgstr "Адрес и порт прослушивания ByeDPI назначаются Tachyon и не должны задаваться в стратегии."
|
||||
|
||||
msgid "ByeDPI option does not accept a compact value: %s"
|
||||
msgstr "Опция ByeDPI не принимает компактное значение: %s"
|
||||
@@ -323,8 +323,8 @@ msgstr "Условия"
|
||||
msgid "Config File Path"
|
||||
msgstr "Путь к файлу конфигурации"
|
||||
|
||||
msgid "Configuration for Forkop service"
|
||||
msgstr "Настройки сервиса Forkop"
|
||||
msgid "Configuration for Tachyon service"
|
||||
msgstr "Настройки сервиса Tachyon"
|
||||
|
||||
msgid "Configure User-Agent in the item settings"
|
||||
msgstr "Настройте User-Agent в настройках элемента"
|
||||
@@ -374,8 +374,8 @@ msgstr "Дашборд сейчас недоступен"
|
||||
msgid "Default address for checking server availability and latency. URLTest uses its own address."
|
||||
msgstr "Адрес по умолчанию для проверки доступности и задержки серверов. Для URLTest используется собственный адрес."
|
||||
|
||||
msgid "Delay in milliseconds before reloading Forkop after interface UP"
|
||||
msgstr "Задержка в миллисекундах перед перезапуском Forkop после поднятия интерфейса"
|
||||
msgid "Delay in milliseconds before reloading Tachyon after interface UP"
|
||||
msgstr "Задержка в миллисекундах перед перезапуском Tachyon после поднятия интерфейса"
|
||||
|
||||
msgid "Delay value cannot be empty"
|
||||
msgstr "Значение задержки не может быть пустым"
|
||||
@@ -419,8 +419,8 @@ msgstr "Отключить QUIC"
|
||||
msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming"
|
||||
msgstr "Отключить QUIC протокол для улучшения совместимости или исправления видео стриминга"
|
||||
|
||||
msgid "Disabling interception is incompatible with action=zapret2 because Forkop sends matched traffic through NFQUEUE."
|
||||
msgstr "Отключение перехвата несовместимо с action=zapret2, потому что Forkop отправляет совпавший трафик через NFQUEUE."
|
||||
msgid "Disabling interception is incompatible with action=zapret2 because Tachyon sends matched traffic through NFQUEUE."
|
||||
msgstr "Отключение перехвата несовместимо с action=zapret2, потому что Tachyon отправляет совпавший трафик через NFQUEUE."
|
||||
|
||||
msgid "Display name"
|
||||
msgstr "Отображаемое имя"
|
||||
@@ -656,11 +656,11 @@ msgstr "Истекает"
|
||||
msgid "Expose this section as a local HTTP+SOCKS proxy"
|
||||
msgstr "Открыть эту секцию как локальный HTTP+SOCKS прокси"
|
||||
|
||||
msgid "External nfqws config files bypass Forkop queue management and explicit validation."
|
||||
msgstr "Внешние конфиги nfqws обходят управление очередями и явную валидацию Forkop."
|
||||
msgid "External nfqws config files bypass Tachyon queue management and explicit validation."
|
||||
msgstr "Внешние конфиги nfqws обходят управление очередями и явную валидацию Tachyon."
|
||||
|
||||
msgid "External nfqws2 config files bypass Forkop queue management and explicit validation."
|
||||
msgstr "Внешние конфиги nfqws2 обходят управление очередями и явную валидацию Forkop."
|
||||
msgid "External nfqws2 config files bypass Tachyon queue management and explicit validation."
|
||||
msgstr "Внешние конфиги nfqws2 обходят управление очередями и явную валидацию Tachyon."
|
||||
|
||||
msgid "Failed to close connection"
|
||||
msgstr "Не удалось закрыть подключение"
|
||||
@@ -707,63 +707,6 @@ msgstr "Исправьте подсвеченные поля и сохранит
|
||||
msgid "Forced device routing"
|
||||
msgstr "Принудительная маршрутизация устройств"
|
||||
|
||||
msgid "Forkop Error"
|
||||
msgstr "Ошибка Forkop"
|
||||
|
||||
msgid "Forkop manages ciadpi pid files itself, so pidfile options are not allowed here."
|
||||
msgstr "Forkop сам управляет pid-файлами ciadpi, поэтому параметры pidfile здесь запрещены."
|
||||
|
||||
msgid "Forkop manages the ciadpi process lifecycle itself, so daemon mode is not allowed here."
|
||||
msgstr "Forkop сам управляет жизненным циклом ciadpi, поэтому режим daemon здесь запрещён."
|
||||
|
||||
msgid "Forkop manages the nfqws process lifecycle itself, so daemon mode is not allowed here."
|
||||
msgstr "Forkop сам управляет жизненным циклом nfqws, поэтому режим daemon здесь запрещён."
|
||||
|
||||
msgid "Forkop manages the nfqws2 process lifecycle itself, so daemon mode is not allowed here."
|
||||
msgstr "Forkop сам управляет жизненным циклом nfqws2, поэтому режим daemon здесь запрещён."
|
||||
|
||||
msgid "Forkop service is stopped. Start the service to display connections."
|
||||
msgstr "Служба Forkop остановлена. Запустите сервис для отображения подключений."
|
||||
|
||||
msgid "Forkop service is stopped. Start the service to display the dashboard."
|
||||
msgstr "Служба Forkop остановлена. Запустите сервис для отображения дашборда."
|
||||
|
||||
msgid "Forkop Settings"
|
||||
msgstr "Настройки Forkop"
|
||||
|
||||
msgid "Forkop will not modify your DHCP configuration"
|
||||
msgstr "Forkop не будет изменять вашу конфигурацию DHCP"
|
||||
|
||||
msgid "Forkop-managed ciadpi runtime has restarted"
|
||||
msgstr "ciadpi Forkop перезапускался"
|
||||
|
||||
msgid "Forkop-managed ciadpi runtime is not ready"
|
||||
msgstr "ciadpi Forkop не готов"
|
||||
|
||||
msgid "Forkop-managed ciadpi runtime is not running"
|
||||
msgstr "ciadpi Forkop не запущен"
|
||||
|
||||
msgid "Forkop-managed ciadpi runtime is ready"
|
||||
msgstr "ciadpi Forkop готов"
|
||||
|
||||
msgid "Forkop-managed nfqws runtime is not ready"
|
||||
msgstr "NFQWS Forkop не готов"
|
||||
|
||||
msgid "Forkop-managed nfqws runtime is not running"
|
||||
msgstr "NFQWS Forkop не запущен"
|
||||
|
||||
msgid "Forkop-managed nfqws runtime is ready"
|
||||
msgstr "NFQWS Forkop готов"
|
||||
|
||||
msgid "Forkop-managed nfqws2 runtime is not ready"
|
||||
msgstr "NFQWS2 Forkop не готов"
|
||||
|
||||
msgid "Forkop-managed nfqws2 runtime is not running"
|
||||
msgstr "NFQWS2 Forkop не запущен"
|
||||
|
||||
msgid "Forkop-managed nfqws2 runtime is ready"
|
||||
msgstr "NFQWS2 Forkop готов"
|
||||
|
||||
msgid "Fronting IP"
|
||||
msgstr "IP фронтинга"
|
||||
|
||||
@@ -773,8 +716,8 @@ msgstr "Порт фронтинга"
|
||||
msgid "Fronting proxy protocol"
|
||||
msgstr "Proxy protocol для фронтинга"
|
||||
|
||||
msgid "Fuzzing is not supported here because Forkop needs deterministic runtime validation."
|
||||
msgstr "Fuzzing здесь не поддерживается, потому что Forkop нужна предсказуемая runtime-валидация."
|
||||
msgid "Fuzzing is not supported here because Tachyon needs deterministic runtime validation."
|
||||
msgstr "Fuzzing здесь не поддерживается, потому что Tachyon нужна предсказуемая runtime-валидация."
|
||||
|
||||
msgid "Generate HWID from router hardware information for this subscription"
|
||||
msgstr "Генерировать HWID из аппаратной информации роутера для этой подписки"
|
||||
@@ -1541,8 +1484,8 @@ msgstr "Выбор ресурсов по IP или CIDR внутри nfqws зд
|
||||
msgid "Resource selection by IP or CIDR inside nfqws2 is not supported here; sing-box selects resources before NFQUEUE."
|
||||
msgstr "Выбор ресурсов по IP или CIDR внутри nfqws2 здесь не поддерживается; sing-box выбирает ресурсы до NFQUEUE."
|
||||
|
||||
msgid "Restart Forkop"
|
||||
msgstr "Перезапустить Forkop"
|
||||
msgid "Restart Tachyon"
|
||||
msgstr "Перезапустить Tachyon"
|
||||
|
||||
msgid "Resume updates"
|
||||
msgstr "Продолжить обновление"
|
||||
@@ -1787,8 +1730,8 @@ msgstr "Укажите разные файлы"
|
||||
msgid "Standalone ByeDPI autostart is enabled"
|
||||
msgstr "Автозапуск отдельной службы ByeDPI включен"
|
||||
|
||||
msgid "Standalone ByeDPI is active together with Forkop ByeDPI rules"
|
||||
msgstr "Отдельная служба ByeDPI активна вместе с правилами ByeDPI в Forkop"
|
||||
msgid "Standalone ByeDPI is active together with Tachyon ByeDPI rules"
|
||||
msgstr "Отдельная служба ByeDPI активна вместе с правилами ByeDPI в Tachyon"
|
||||
|
||||
msgid "Standalone ByeDPI service is active"
|
||||
msgstr "Отдельная служба ByeDPI активна"
|
||||
@@ -1796,8 +1739,8 @@ msgstr "Отдельная служба ByeDPI активна"
|
||||
msgid "Standalone ByeDPI service is inactive"
|
||||
msgstr "Отдельная служба ByeDPI неактивна"
|
||||
|
||||
msgid "Standalone Zapret is active together with Forkop Zapret rules"
|
||||
msgstr "Отдельная служба Zapret активна вместе с правилами Zapret в Forkop"
|
||||
msgid "Standalone Zapret is active together with Tachyon Zapret rules"
|
||||
msgstr "Отдельная служба Zapret активна вместе с правилами Zapret в Tachyon"
|
||||
|
||||
msgid "Standalone Zapret service is active"
|
||||
msgstr "Отдельная служба Zapret активна"
|
||||
@@ -1808,8 +1751,8 @@ msgstr "Отдельная служба Zapret неактивна"
|
||||
msgid "Standalone Zapret2 autostart is enabled"
|
||||
msgstr "Автозапуск отдельной службы Zapret2 включён"
|
||||
|
||||
msgid "Standalone Zapret2 is active together with Forkop Zapret2 rules"
|
||||
msgstr "Отдельная служба Zapret2 активна вместе с правилами Zapret2 в Forkop"
|
||||
msgid "Standalone Zapret2 is active together with Tachyon Zapret2 rules"
|
||||
msgstr "Отдельная служба Zapret2 активна вместе с правилами Zapret2 в Tachyon"
|
||||
|
||||
msgid "Standalone Zapret2 service is active"
|
||||
msgstr "Отдельная служба Zapret2 активна"
|
||||
@@ -1817,14 +1760,14 @@ msgstr "Отдельная служба Zapret2 активна"
|
||||
msgid "Standalone Zapret2 service is inactive"
|
||||
msgstr "Отдельная служба Zapret2 неактивна"
|
||||
|
||||
msgid "Start Forkop"
|
||||
msgstr "Запустить Forkop"
|
||||
msgid "Start Tachyon"
|
||||
msgstr "Запустить Tachyon"
|
||||
|
||||
msgid "Stop checking when URLTest group is not used. Use sing-box duration format like 1d, 12h or 30m."
|
||||
msgstr "Останавливать проверку если URLTest группа не используется. Используйте формат длительности sing-box, например 1d, 12h или 30m."
|
||||
|
||||
msgid "Stop Forkop"
|
||||
msgstr "Остановить Forkop"
|
||||
msgid "Stop Tachyon"
|
||||
msgstr "Остановить Tachyon"
|
||||
|
||||
msgid "Subnets from the list will be extracted and added to nftables"
|
||||
msgstr "IP-адреса и подсети из списка будут извлечены и добавлены в nftables"
|
||||
@@ -1862,6 +1805,63 @@ msgstr "Системная информация"
|
||||
msgid "Table exist"
|
||||
msgstr "Таблица существует"
|
||||
|
||||
msgid "Tachyon Error"
|
||||
msgstr "Ошибка Tachyon"
|
||||
|
||||
msgid "Tachyon manages ciadpi pid files itself, so pidfile options are not allowed here."
|
||||
msgstr "Tachyon сам управляет pid-файлами ciadpi, поэтому параметры pidfile здесь запрещены."
|
||||
|
||||
msgid "Tachyon manages the ciadpi process lifecycle itself, so daemon mode is not allowed here."
|
||||
msgstr "Tachyon сам управляет жизненным циклом ciadpi, поэтому режим daemon здесь запрещён."
|
||||
|
||||
msgid "Tachyon manages the nfqws process lifecycle itself, so daemon mode is not allowed here."
|
||||
msgstr "Tachyon сам управляет жизненным циклом nfqws, поэтому режим daemon здесь запрещён."
|
||||
|
||||
msgid "Tachyon manages the nfqws2 process lifecycle itself, so daemon mode is not allowed here."
|
||||
msgstr "Tachyon сам управляет жизненным циклом nfqws2, поэтому режим daemon здесь запрещён."
|
||||
|
||||
msgid "Tachyon service is stopped. Start the service to display connections."
|
||||
msgstr "Служба Tachyon остановлена. Запустите сервис для отображения подключений."
|
||||
|
||||
msgid "Tachyon service is stopped. Start the service to display the dashboard."
|
||||
msgstr "Служба Tachyon остановлена. Запустите сервис для отображения дашборда."
|
||||
|
||||
msgid "Tachyon Settings"
|
||||
msgstr "Настройки Tachyon"
|
||||
|
||||
msgid "Tachyon will not modify your DHCP configuration"
|
||||
msgstr "Tachyon не будет изменять вашу конфигурацию DHCP"
|
||||
|
||||
msgid "Tachyon-managed ciadpi runtime has restarted"
|
||||
msgstr "ciadpi Tachyon перезапускался"
|
||||
|
||||
msgid "Tachyon-managed ciadpi runtime is not ready"
|
||||
msgstr "ciadpi Tachyon не готов"
|
||||
|
||||
msgid "Tachyon-managed ciadpi runtime is not running"
|
||||
msgstr "ciadpi Tachyon не запущен"
|
||||
|
||||
msgid "Tachyon-managed ciadpi runtime is ready"
|
||||
msgstr "ciadpi Tachyon готов"
|
||||
|
||||
msgid "Tachyon-managed nfqws runtime is not ready"
|
||||
msgstr "NFQWS Tachyon не готов"
|
||||
|
||||
msgid "Tachyon-managed nfqws runtime is not running"
|
||||
msgstr "NFQWS Tachyon не запущен"
|
||||
|
||||
msgid "Tachyon-managed nfqws runtime is ready"
|
||||
msgstr "NFQWS Tachyon готов"
|
||||
|
||||
msgid "Tachyon-managed nfqws2 runtime is not ready"
|
||||
msgstr "NFQWS2 Tachyon не готов"
|
||||
|
||||
msgid "Tachyon-managed nfqws2 runtime is not running"
|
||||
msgstr "NFQWS2 Tachyon не запущен"
|
||||
|
||||
msgid "Tachyon-managed nfqws2 runtime is ready"
|
||||
msgstr "NFQWS2 Tachyon готов"
|
||||
|
||||
msgid "Tailscale auth key"
|
||||
msgstr "Ключ авторизации Tailscale"
|
||||
|
||||
@@ -1898,11 +1898,11 @@ msgstr "Тестировать серверы, имена которых сов
|
||||
msgid "Testing URL"
|
||||
msgstr "URL проверки"
|
||||
|
||||
msgid "The desync fwmark is managed by Forkop for loop prevention and must not be overridden here."
|
||||
msgstr "Desync fwmark управляется Forkop для защиты от циклов и не должен переопределяться здесь."
|
||||
msgid "The desync fwmark is managed by Tachyon for loop prevention and must not be overridden here."
|
||||
msgstr "Desync fwmark управляется Tachyon для защиты от циклов и не должен переопределяться здесь."
|
||||
|
||||
msgid "The NFQUEUE number is assigned by Forkop for each rule and must not be overridden here."
|
||||
msgstr "Номер NFQUEUE назначается Forkop для каждого правила и не должен переопределяться здесь."
|
||||
msgid "The NFQUEUE number is assigned by Tachyon for each rule and must not be overridden here."
|
||||
msgstr "Номер NFQUEUE назначается Tachyon для каждого правила и не должен переопределяться здесь."
|
||||
|
||||
msgid "The rule applies to the domain and all its subdomains. Use full:, keyword:, or regex: prefixes for exact match, keyword match, or regular expression."
|
||||
msgstr "Правило применяется к домену и всем его поддоменам. Для полного совпадения, совпадению по слову или регулярному выражению используйте префиксы full:, keyword: или regex:."
|
||||
@@ -1967,8 +1967,8 @@ msgstr "Трафик этого уровня пойдёт напрямую."
|
||||
msgid "Traffic Total"
|
||||
msgstr "Всего трафика"
|
||||
|
||||
msgid "Transparent proxy mode is incompatible with action=byedpi because Forkop connects to ciadpi through SOCKS."
|
||||
msgstr "Режим прозрачного прокси несовместим с action=byedpi, потому что Forkop подключается к ciadpi через SOCKS."
|
||||
msgid "Transparent proxy mode is incompatible with action=byedpi because Tachyon connects to ciadpi through SOCKS."
|
||||
msgstr "Режим прозрачного прокси несовместим с action=byedpi, потому что Tachyon подключается к ciadpi через SOCKS."
|
||||
|
||||
msgid "Transport"
|
||||
msgstr "Транспорт"
|
||||
@@ -2015,18 +2015,18 @@ msgstr "Таймаут недоступности"
|
||||
msgid "Unexpected ByeDPI strategy argument: %s"
|
||||
msgstr "Неожиданный аргумент стратегии ByeDPI: %s"
|
||||
|
||||
msgid "Unexpected Forkop-managed ciadpi runtime is running"
|
||||
msgstr "Обнаружен лишний ciadpi Forkop"
|
||||
|
||||
msgid "Unexpected Forkop-managed nfqws runtime is running"
|
||||
msgstr "Обнаружен лишний NFQWS Forkop"
|
||||
|
||||
msgid "Unexpected Forkop-managed nfqws2 runtime is running"
|
||||
msgstr "Обнаружен лишний NFQWS2 Forkop"
|
||||
|
||||
msgid "Unexpected standalone token. Use explicit flags such as --name or --name=value."
|
||||
msgstr "Неожиданный отдельный токен. Используйте явные флаги вида --имя или --имя=значение."
|
||||
|
||||
msgid "Unexpected Tachyon-managed ciadpi runtime is running"
|
||||
msgstr "Обнаружен лишний ciadpi Tachyon"
|
||||
|
||||
msgid "Unexpected Tachyon-managed nfqws runtime is running"
|
||||
msgstr "Обнаружен лишний NFQWS Tachyon"
|
||||
|
||||
msgid "Unexpected Tachyon-managed nfqws2 runtime is running"
|
||||
msgstr "Обнаружен лишний NFQWS2 Tachyon"
|
||||
|
||||
msgid "unique UCI identifier"
|
||||
msgstr "уникальный идентификатор UCI"
|
||||
|
||||
@@ -2192,8 +2192,8 @@ msgstr "Предупреждение: %s нельзя использовать
|
||||
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
|
||||
msgstr "Предупреждение: Russia inside может быть использован только с %s. %s уже есть в Russia inside и будет удален из выбранных."
|
||||
|
||||
msgid "What Forkop should do when this section matches"
|
||||
msgstr "Что Forkop должен делать при совпадении этой секции"
|
||||
msgid "What Tachyon should do when this section matches"
|
||||
msgstr "Что Tachyon должен делать при совпадении этой секции"
|
||||
|
||||
msgid "When switching to another level, test every server and select the fastest instead of the first working one."
|
||||
msgstr "При переходе на другой уровень тестировать все сервера и выбирать самый быстрый, а не первый работающий."
|
||||
@@ -2210,8 +2210,8 @@ msgstr "Да"
|
||||
msgid "You can select Output Network Interface, by default autodetect"
|
||||
msgstr "Вы можете выбрать выходной сетевой интерфейс, по умолчанию он определяется автоматически."
|
||||
|
||||
msgid "Zapret hostlist templates are not supported here because Forkop does not expand them for per-rule NFQWS strategies."
|
||||
msgstr "Шаблоны hostlist zapret здесь не поддерживаются, потому что Forkop не разворачивает их для per-rule стратегий NFQWS."
|
||||
msgid "Zapret hostlist templates are not supported here because Tachyon does not expand them for per-rule NFQWS strategies."
|
||||
msgstr "Шаблоны hostlist zapret здесь не поддерживаются, потому что Tachyon не разворачивает их для per-rule стратегий NFQWS."
|
||||
|
||||
msgid "Zapret package is installed"
|
||||
msgstr "Пакет Zapret установлен"
|
||||
@@ -2231,8 +2231,8 @@ msgstr "sing-box outbound для Zapret настроен"
|
||||
msgid "Zapret sing-box outbound is not configured"
|
||||
msgstr "sing-box outbound для Zapret не настроен"
|
||||
|
||||
msgid "Zapret2 hostlist templates are not supported here because Forkop does not expand them for per-rule NFQWS2 strategies."
|
||||
msgstr "Шаблоны hostlist Zapret2 здесь не поддерживаются, потому что Forkop не разворачивает их для per-rule стратегий NFQWS2."
|
||||
msgid "Zapret2 hostlist templates are not supported here because Tachyon does not expand them for per-rule NFQWS2 strategies."
|
||||
msgstr "Шаблоны hostlist Zapret2 здесь не поддерживаются, потому что Tachyon не разворачивает их для per-rule стратегий NFQWS2."
|
||||
|
||||
msgid "Zapret2 package is installed"
|
||||
msgstr "Пакет Zapret2 установлен"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
/usr/bin/forkop luci_postinst >/dev/null 2>&1 || true
|
||||
/usr/bin/tachyon luci_postinst >/dev/null 2>&1 || true
|
||||
exit 0
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user