Rebrand project as Forkop
This commit is contained in:
@@ -11,8 +11,8 @@ body:
|
||||
Спасибо за создание отчета об ошибке!
|
||||
|
||||
Перед отправкой, пожалуйста:
|
||||
- Проверьте [существующие issues](https://github.com/ushan0v/podkop-plus/issues)
|
||||
- Просмотрите [README проекта](https://github.com/ushan0v/podkop-plus#readme)
|
||||
- Проверьте [существующие issues](https://github.com/ushan0v/forkop/issues)
|
||||
- Просмотрите [README проекта](https://github.com/ushan0v/forkop#readme)
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
@@ -53,7 +53,7 @@ body:
|
||||
Информация о вашей системе (заполните всё применимое)
|
||||
value: |
|
||||
- **OpenWrt версия**:
|
||||
- **Podkop Plus версия**:
|
||||
- **Forkop версия**:
|
||||
- **Роутер модель**:
|
||||
- **Sing-box версия**:
|
||||
render: markdown
|
||||
@@ -68,7 +68,7 @@ body:
|
||||
Релевантные части конфигурации (удалите чувствительную информацию!)
|
||||
placeholder: |
|
||||
Например:
|
||||
- Содержимое /etc/config/podkop-plus
|
||||
- Содержимое /etc/config/forkop
|
||||
- Конфигурация sing-box (если релевантно)
|
||||
- Дополнительные конфиги, которые потребуются wireless/network/dhcp и т.д.
|
||||
render: shell
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 💬 Если у вас что-то не работает, прежде всего прочитайте README проекта
|
||||
url: https://github.com/ushan0v/podkop-plus
|
||||
url: https://github.com/ushan0v/forkop
|
||||
about: README проекта
|
||||
- name: 📚 Если вы не нашли в README документацию, то вот ссылка на неё
|
||||
url: https://github.com/ushan0v/podkop-plus#readme
|
||||
about: README Podkop Plus
|
||||
url: https://github.com/ushan0v/forkop#readme
|
||||
about: README Forkop
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: ✨ Запрос новой функции
|
||||
description: Предложите новую функцию или улучшение для Podkop Plus
|
||||
description: Предложите новую функцию или улучшение для Forkop
|
||||
title: "[FEATURE] "
|
||||
labels: ["enhancement", "needs-discussion"]
|
||||
assignees: []
|
||||
@@ -11,14 +11,14 @@ body:
|
||||
Спасибо за предложение новой функции!
|
||||
|
||||
Перед отправкой, пожалуйста:
|
||||
- Проверьте [существующие запросы](https://github.com/ushan0v/podkop-plus/issues?q=is%3Aissue+label%3Aenhancement)
|
||||
- Убедитесь, что функции не существует в [README проекта](https://github.com/ushan0v/podkop-plus#readme)
|
||||
- Проверьте [существующие запросы](https://github.com/ushan0v/forkop/issues?q=is%3Aissue+label%3Aenhancement)
|
||||
- Убедитесь, что функции не существует в [README проекта](https://github.com/ushan0v/forkop#readme)
|
||||
|
||||
- type: textarea
|
||||
id: summary
|
||||
attributes:
|
||||
label: Краткое описание
|
||||
description: Краткое описание предлагаемой функции для Podkop Plus
|
||||
description: Краткое описание предлагаемой функции для Forkop
|
||||
placeholder: В одном предложении опишите, что вы хотите добавить...
|
||||
validations:
|
||||
required: true
|
||||
@@ -40,7 +40,7 @@ body:
|
||||
label: 💡 Предлагаемое решение
|
||||
description: Четкое и краткое описание того, что вы хотите реализовать
|
||||
placeholder: |
|
||||
Я хочу, чтобы Podkop мог [...]
|
||||
Я хочу, чтобы Forkop мог [...]
|
||||
Предлагаю добавить функцию, которая [...]
|
||||
Можно было бы улучшить [...] путем [...]
|
||||
validations:
|
||||
|
||||
@@ -3,8 +3,8 @@ name: Backend CI
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'podkop/files/**'
|
||||
- 'podkop/Makefile'
|
||||
- 'forkop/files/**'
|
||||
- 'forkop/Makefile'
|
||||
- 'build.sh'
|
||||
- 'tests/**'
|
||||
- '.github/workflows/backend-ci.yml'
|
||||
@@ -12,8 +12,8 @@ on:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'podkop/files/**'
|
||||
- 'podkop/Makefile'
|
||||
- 'forkop/files/**'
|
||||
- 'forkop/Makefile'
|
||||
- 'build.sh'
|
||||
- 'tests/**'
|
||||
- '.github/workflows/backend-ci.yml'
|
||||
@@ -48,8 +48,8 @@ jobs:
|
||||
- name: Check ucode syntax
|
||||
shell: bash
|
||||
run: |
|
||||
find podkop/files/usr/lib -name '*.uc' -print0 | xargs -0 -n1 ucode -c -o /dev/null
|
||||
find podkop/files/usr/lib -name '*.uc' -print0 | xargs -0 -n1 ucode -S -c -o /dev/null
|
||||
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
|
||||
|
||||
- name: Run backend tests
|
||||
shell: bash
|
||||
|
||||
@@ -37,15 +37,15 @@ jobs:
|
||||
else
|
||||
VERSION=$(git describe --tags --exact-match 2>/dev/null || true)
|
||||
fi
|
||||
if [[ ! "$VERSION" =~ ^([0-9]+(\.[0-9]+)*-[0-9]+|[0-9]+(\.[0-9]+){3})$ ]]; then
|
||||
echo "Release version must use x.y.z.n format; legacy x.y.z-n is also accepted, got: ${VERSION:-<empty>}" >&2
|
||||
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "Release version must use x.y.z format, got: ${VERSION:-<empty>}" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "commitish=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
build:
|
||||
name: Build Podkop Plus release packages
|
||||
name: Build Forkop release packages
|
||||
runs-on: ubuntu-latest
|
||||
needs: preparation
|
||||
steps:
|
||||
|
||||
@@ -3,7 +3,7 @@ name: Frontend CI
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'fe-app-podkop/**'
|
||||
- 'fe-app-forkop/**'
|
||||
- '.github/workflows/frontend-ci.yml'
|
||||
|
||||
jobs:
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
defaults:
|
||||
run:
|
||||
working-directory: fe-app-podkop
|
||||
working-directory: fe-app-forkop
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
@@ -28,14 +28,14 @@ jobs:
|
||||
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
working-directory: fe-app-podkop
|
||||
working-directory: fe-app-forkop
|
||||
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-podkop/yarn.lock') }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('fe-app-forkop/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ on:
|
||||
- 'rc/**'
|
||||
paths:
|
||||
- 'install.sh'
|
||||
- 'podkop/files/usr/bin/**'
|
||||
- 'podkop/files/usr/lib/**'
|
||||
- 'forkop/files/usr/bin/**'
|
||||
- 'forkop/files/usr/lib/**'
|
||||
- '.github/workflows/shellcheck.yml'
|
||||
pull_request:
|
||||
branches:
|
||||
@@ -24,8 +24,8 @@ on:
|
||||
- 'rc/**'
|
||||
paths:
|
||||
- 'install.sh'
|
||||
- 'podkop/files/usr/bin/**'
|
||||
- 'podkop/files/usr/lib/**'
|
||||
- 'forkop/files/usr/bin/**'
|
||||
- 'forkop/files/usr/lib/**'
|
||||
- '.github/workflows/shellcheck.yml'
|
||||
|
||||
permissions:
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
head: ${{ github.event.inputs.head }}
|
||||
severity: error
|
||||
include-path: |
|
||||
podkop/files/usr/bin/podkop
|
||||
podkop/files/usr/lib/**.sh
|
||||
forkop/files/usr/bin/forkop
|
||||
forkop/files/usr/lib/**.sh
|
||||
install.sh
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
.idea
|
||||
fe-app-podkop/node_modules
|
||||
fe-app-podkop/.yarn/
|
||||
fe-app-podkop/.env
|
||||
fe-app-forkop/node_modules
|
||||
fe-app-forkop/.yarn/
|
||||
fe-app-forkop/.env
|
||||
.DS_Store
|
||||
|
||||
sandbox/
|
||||
|
||||
@@ -16,35 +16,28 @@ if [[ "$DEFAULT_BUILD_HOME" == "/root" ]]; then
|
||||
DEFAULT_BUILD_HOME="${DEFAULT_BUILD_HOME:-/root}"
|
||||
fi
|
||||
|
||||
if [[ "$RELEASE_VERSION" =~ ^[0-9]+(\.[0-9]+)*-[0-9]+$ ]]; then
|
||||
BASE_VERSION="${RELEASE_VERSION%-*}"
|
||||
FORK_RELEASE="${RELEASE_VERSION##*-}"
|
||||
APK_INTERNAL_VERSION="${APK_INTERNAL_VERSION:-${BASE_VERSION}-r${FORK_RELEASE}}"
|
||||
elif [[ "$RELEASE_VERSION" =~ ^[0-9]+(\.[0-9]+){3}$ ]]; then
|
||||
BASE_VERSION="${RELEASE_VERSION%.*}"
|
||||
FORK_RELEASE="${RELEASE_VERSION##*.}"
|
||||
APK_INTERNAL_VERSION="${APK_INTERNAL_VERSION:-${RELEASE_VERSION}}"
|
||||
else
|
||||
echo "Expected release version in the form x.y.z.n; legacy x.y.z-n is also accepted" >&2
|
||||
if [[ ! "$RELEASE_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "Expected release version in the form x.y.z" >&2
|
||||
exit 1
|
||||
fi
|
||||
APK_INTERNAL_VERSION="$RELEASE_VERSION"
|
||||
|
||||
WSL_NATIVE_ROOT="${WSL_NATIVE_ROOT:-$DEFAULT_BUILD_HOME/build/podkop-plus}"
|
||||
WSL_NATIVE_ROOT="${WSL_NATIVE_ROOT:-$DEFAULT_BUILD_HOME/build/forkop}"
|
||||
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/podkop-plus/openwrt-sdk}"
|
||||
SDK_CACHE_DIR="${SDK_CACHE_DIR:-$DEFAULT_BUILD_HOME/.cache/forkop/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 Podkop Plus backend with hybrid sing-box + zapret orchestration"
|
||||
APP_DESCRIPTION="Rule-based Podkop Plus LuCI app with hybrid sing-box + zapret orchestration"
|
||||
I18N_DESCRIPTION="Translation for luci-app-podkop-plus - Русский (Russian)"
|
||||
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)"
|
||||
MAINTAINER="ushan0v <ushan0v@users.noreply.github.com>"
|
||||
PROJECT_URL="https://github.com/ushan0v/podkop-plus"
|
||||
PROJECT_URL="https://github.com/ushan0v/forkop"
|
||||
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, podkop-plus"
|
||||
APP_DEPENDS_APK="libc luci-base podkop-plus"
|
||||
APP_DEPENDS_IPK="libc, luci-base, forkop"
|
||||
APP_DEPENDS_APK="libc luci-base forkop"
|
||||
|
||||
APT_PACKAGES=(
|
||||
build-essential
|
||||
@@ -77,14 +70,14 @@ copy_to_native_root() {
|
||||
--exclude "dist" \
|
||||
--exclude ".idea" \
|
||||
--exclude "sandbox" \
|
||||
--exclude "fe-app-podkop/node_modules" \
|
||||
--exclude "fe-app-podkop/tests" \
|
||||
--exclude "fe-app-forkop/node_modules" \
|
||||
--exclude "fe-app-forkop/tests" \
|
||||
"$ROOT_DIR/" "$target_root/"
|
||||
rm -rf \
|
||||
"$target_root/.idea" \
|
||||
"$target_root/sandbox" \
|
||||
"$target_root/fe-app-podkop/node_modules" \
|
||||
"$target_root/fe-app-podkop/tests"
|
||||
"$target_root/fe-app-forkop/node_modules" \
|
||||
"$target_root/fe-app-forkop/tests"
|
||||
|
||||
if [[ -n "$OUTPUT_DIR_INPUT" ]]; then
|
||||
target_output="$OUTPUT_DIR_INPUT"
|
||||
@@ -179,7 +172,7 @@ extract_sdk() {
|
||||
local archive_path="$2"
|
||||
local sdk_url="$3"
|
||||
local destination="$SDK_WORK_DIR/$kind"
|
||||
local marker_file="$destination/.podkop-sdk-url"
|
||||
local marker_file="$destination/.forkop-sdk-url"
|
||||
local temp_dir
|
||||
local extracted_root
|
||||
|
||||
@@ -242,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/podkop-plus"
|
||||
make_dir "$output_root/usr/lib/forkop"
|
||||
|
||||
install -m 0755 "$ROOT_DIR/podkop/files/etc/init.d/podkop" "$output_root/etc/init.d/podkop-plus"
|
||||
install -m 0644 "$ROOT_DIR/podkop/files/etc/config/podkop" "$output_root/etc/config/podkop-plus"
|
||||
install -m 0755 "$ROOT_DIR/podkop/files/usr/bin/podkop" "$output_root/usr/bin/podkop-plus"
|
||||
cp -a "$ROOT_DIR/podkop/files/usr/lib/." "$output_root/usr/lib/podkop-plus/"
|
||||
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/"
|
||||
|
||||
sed -i -e "s/__COMPILED_VERSION_VARIABLE__/${RELEASE_VERSION}/g" \
|
||||
"$output_root/usr/lib/podkop-plus/core/constants.uc"
|
||||
"$output_root/usr/lib/forkop/core/constants.uc"
|
||||
|
||||
normalize_package_root_modes "$output_root"
|
||||
chmod 0755 "$output_root/etc/init.d/podkop-plus" "$output_root/usr/bin/podkop-plus"
|
||||
chmod 0755 "$output_root/etc/init.d/forkop" "$output_root/usr/bin/forkop"
|
||||
}
|
||||
|
||||
build_app_root() {
|
||||
@@ -262,23 +255,17 @@ build_app_root() {
|
||||
rm -rf "$output_root"
|
||||
make_dir "$output_root/www"
|
||||
|
||||
if [[ -d "$ROOT_DIR/luci-app-podkop-plus/htdocs" ]]; then
|
||||
cp -a "$ROOT_DIR/luci-app-podkop-plus/htdocs/." "$output_root/www/"
|
||||
if [[ -d "$ROOT_DIR/luci-app-forkop/htdocs" ]]; then
|
||||
cp -a "$ROOT_DIR/luci-app-forkop/htdocs/." "$output_root/www/"
|
||||
fi
|
||||
|
||||
if [[ -d "$output_root/www/luci-static/resources/view/podkop" ]]; then
|
||||
rm -rf "$output_root/www/luci-static/resources/view/podkop_plus"
|
||||
mv "$output_root/www/luci-static/resources/view/podkop" \
|
||||
"$output_root/www/luci-static/resources/view/podkop_plus"
|
||||
if [[ -d "$ROOT_DIR/luci-app-forkop/root" ]]; then
|
||||
cp -a "$ROOT_DIR/luci-app-forkop/root/." "$output_root/"
|
||||
fi
|
||||
|
||||
if [[ -d "$ROOT_DIR/luci-app-podkop-plus/root" ]]; then
|
||||
cp -a "$ROOT_DIR/luci-app-podkop-plus/root/." "$output_root/"
|
||||
fi
|
||||
|
||||
if [[ -f "$output_root/www/luci-static/resources/view/podkop_plus/main.js" ]]; then
|
||||
if [[ -f "$output_root/www/luci-static/resources/view/forkop/main.js" ]]; then
|
||||
sed -i -e "s/__COMPILED_VERSION_VARIABLE__/${RELEASE_VERSION}/g" \
|
||||
"$output_root/www/luci-static/resources/view/podkop_plus/main.js"
|
||||
"$output_root/www/luci-static/resources/view/forkop/main.js"
|
||||
fi
|
||||
|
||||
normalize_package_root_modes "$output_root"
|
||||
@@ -288,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/podkop_plus.ru.lmo"
|
||||
local lmo_path="$output_root/usr/lib/lua/luci/i18n/forkop.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-podkop-plus-ru" <<'EOF'
|
||||
cat > "$output_root/etc/uci-defaults/luci-i18n-forkop-ru" <<'EOF'
|
||||
uci set luci.languages.ru='Русский (Russian)'; uci commit luci
|
||||
EOF
|
||||
|
||||
"$po2lmo_bin" "$ROOT_DIR/luci-app-podkop-plus/po/ru/podkop_plus.po" "$lmo_path"
|
||||
"$po2lmo_bin" "$ROOT_DIR/luci-app-forkop/po/ru/forkop.po" "$lmo_path"
|
||||
|
||||
normalize_package_root_modes "$output_root"
|
||||
find "$output_root/etc/uci-defaults" -type f -exec chmod 0755 {} + 2>/dev/null || true
|
||||
@@ -339,7 +326,7 @@ write_backend_ipk_control() {
|
||||
make_dir "$control_dir"
|
||||
|
||||
cat > "$control_dir/control" <<EOF
|
||||
Package: podkop-plus
|
||||
Package: forkop
|
||||
Version: ${RELEASE_VERSION}
|
||||
Depends: ${BACKEND_DEPENDS_IPK}
|
||||
License: GPL-2.0-or-later
|
||||
@@ -352,37 +339,19 @@ Description: ${BACKEND_DESCRIPTION}
|
||||
EOF
|
||||
|
||||
cat > "$control_dir/conffiles" <<'EOF'
|
||||
/etc/config/podkop-plus
|
||||
EOF
|
||||
|
||||
cat > "$control_dir/preinst" <<'EOF'
|
||||
#!/usr/bin/ucode
|
||||
|
||||
let fs = require("fs");
|
||||
|
||||
if (getenv("IPKG_INSTROOT") != null && getenv("IPKG_INSTROOT") != "")
|
||||
exit(0);
|
||||
|
||||
if (fs.stat("/etc/config/podkop-plus") == null && fs.stat("/etc/config/podkop_plus") != null) {
|
||||
let data = fs.readfile("/etc/config/podkop_plus");
|
||||
if (data == null || fs.writefile("/etc/config/podkop-plus", data) == null)
|
||||
exit(1);
|
||||
system("chmod 0644 /etc/config/podkop-plus >/dev/null 2>&1");
|
||||
}
|
||||
|
||||
exit(0);
|
||||
/etc/config/forkop
|
||||
EOF
|
||||
|
||||
cat > "$control_dir/prerm" <<'EOF'
|
||||
#!/usr/bin/ucode
|
||||
|
||||
if (getenv("IPKG_INSTROOT") == null || getenv("IPKG_INSTROOT") == "")
|
||||
system("/usr/bin/podkop-plus package_prerm >/dev/null 2>&1");
|
||||
system("/usr/bin/forkop package_prerm >/dev/null 2>&1");
|
||||
|
||||
exit(0);
|
||||
EOF
|
||||
|
||||
chmod 0755 "$control_dir/preinst" "$control_dir/prerm"
|
||||
chmod 0755 "$control_dir/prerm"
|
||||
}
|
||||
|
||||
write_app_ipk_control() {
|
||||
@@ -393,7 +362,7 @@ write_app_ipk_control() {
|
||||
make_dir "$control_dir"
|
||||
|
||||
cat > "$control_dir/control" <<EOF
|
||||
Package: luci-app-podkop-plus
|
||||
Package: luci-app-forkop
|
||||
Version: ${RELEASE_VERSION}
|
||||
Depends: ${APP_DEPENDS_IPK}
|
||||
License: GPL-2.0-or-later
|
||||
@@ -414,7 +383,7 @@ default_postinst $0 $@
|
||||
EOF
|
||||
|
||||
cat > "$control_dir/postinst-pkg" <<'EOF'
|
||||
[ -n "${IPKG_INSTROOT}" ] || /usr/bin/podkop-plus luci_postinst >/dev/null 2>&1 || true
|
||||
[ -n "${IPKG_INSTROOT}" ] || /usr/bin/forkop luci_postinst >/dev/null 2>&1 || true
|
||||
EOF
|
||||
|
||||
cat > "$control_dir/prerm" <<'EOF'
|
||||
@@ -435,9 +404,9 @@ write_i18n_ipk_control() {
|
||||
make_dir "$control_dir"
|
||||
|
||||
cat > "$control_dir/control" <<EOF
|
||||
Package: luci-i18n-podkop-plus-ru
|
||||
Package: luci-i18n-forkop-ru
|
||||
Version: ${RELEASE_VERSION}
|
||||
Depends: libc, luci-app-podkop-plus
|
||||
Depends: libc, luci-app-forkop
|
||||
License: GPL-2.0-or-later
|
||||
Section: luci
|
||||
URL: ${PROJECT_URL}
|
||||
@@ -513,19 +482,6 @@ write_backend_apk_scripts() {
|
||||
|
||||
cat > "$scripts_dir/backend-pre-install.sh" <<'EOF'
|
||||
#!/usr/bin/ucode
|
||||
|
||||
let fs = require("fs");
|
||||
|
||||
if (getenv("IPKG_INSTROOT") != null && getenv("IPKG_INSTROOT") != "")
|
||||
exit(0);
|
||||
|
||||
if (fs.stat("/etc/config/podkop-plus") == null && fs.stat("/etc/config/podkop_plus") != null) {
|
||||
let data = fs.readfile("/etc/config/podkop_plus");
|
||||
if (data == null || fs.writefile("/etc/config/podkop-plus", data) == null)
|
||||
exit(1);
|
||||
system("chmod 0644 /etc/config/podkop-plus >/dev/null 2>&1");
|
||||
}
|
||||
|
||||
exit(0);
|
||||
EOF
|
||||
|
||||
@@ -538,26 +494,13 @@ EOF
|
||||
#!/usr/bin/ucode
|
||||
|
||||
if (getenv("IPKG_INSTROOT") == null || getenv("IPKG_INSTROOT") == "")
|
||||
system("/usr/bin/podkop-plus package_prerm >/dev/null 2>&1");
|
||||
system("/usr/bin/forkop package_prerm >/dev/null 2>&1");
|
||||
|
||||
exit(0);
|
||||
EOF
|
||||
|
||||
cat > "$scripts_dir/backend-pre-upgrade.sh" <<'EOF'
|
||||
#!/usr/bin/ucode
|
||||
|
||||
let fs = require("fs");
|
||||
|
||||
if (getenv("IPKG_INSTROOT") != null && getenv("IPKG_INSTROOT") != "")
|
||||
exit(0);
|
||||
|
||||
if (fs.stat("/etc/config/podkop-plus") == null && fs.stat("/etc/config/podkop_plus") != null) {
|
||||
let data = fs.readfile("/etc/config/podkop_plus");
|
||||
if (data == null || fs.writefile("/etc/config/podkop-plus", data) == null)
|
||||
exit(1);
|
||||
system("chmod 0644 /etc/config/podkop-plus >/dev/null 2>&1");
|
||||
}
|
||||
|
||||
exit(0);
|
||||
EOF
|
||||
|
||||
@@ -585,10 +528,10 @@ EOF
|
||||
[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0
|
||||
. ${IPKG_INSTROOT}/lib/functions.sh
|
||||
export root="${IPKG_INSTROOT}"
|
||||
export pkgname="luci-app-podkop-plus"
|
||||
export pkgname="luci-app-forkop"
|
||||
add_group_and_user
|
||||
default_postinst
|
||||
[ -n "${IPKG_INSTROOT}" ] || /usr/bin/podkop-plus luci_postinst >/dev/null 2>&1 || true
|
||||
[ -n "${IPKG_INSTROOT}" ] || /usr/bin/forkop luci_postinst >/dev/null 2>&1 || true
|
||||
EOF
|
||||
|
||||
cat > "$scripts_dir/app-pre-deinstall.sh" <<'EOF'
|
||||
@@ -596,7 +539,7 @@ EOF
|
||||
[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0
|
||||
. ${IPKG_INSTROOT}/lib/functions.sh
|
||||
export root="${IPKG_INSTROOT}"
|
||||
export pkgname="luci-app-podkop-plus"
|
||||
export pkgname="luci-app-forkop"
|
||||
default_prerm
|
||||
exit 0
|
||||
EOF
|
||||
@@ -613,10 +556,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-podkop-plus"
|
||||
export pkgname="luci-app-forkop"
|
||||
add_group_and_user
|
||||
default_postinst
|
||||
[ -n "${IPKG_INSTROOT}" ] || /usr/bin/podkop-plus luci_postinst >/dev/null 2>&1 || true
|
||||
[ -n "${IPKG_INSTROOT}" ] || /usr/bin/forkop luci_postinst >/dev/null 2>&1 || true
|
||||
EOF
|
||||
|
||||
chmod 0755 "$scripts_dir"/app-*.sh
|
||||
@@ -638,7 +581,7 @@ EOF
|
||||
[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0
|
||||
. ${IPKG_INSTROOT}/lib/functions.sh
|
||||
export root="${IPKG_INSTROOT}"
|
||||
export pkgname="luci-i18n-podkop-plus-ru"
|
||||
export pkgname="luci-i18n-forkop-ru"
|
||||
add_group_and_user
|
||||
default_postinst
|
||||
EOF
|
||||
@@ -648,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-podkop-plus-ru"
|
||||
export pkgname="luci-i18n-forkop-ru"
|
||||
default_prerm
|
||||
EOF
|
||||
|
||||
@@ -664,7 +607,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-podkop-plus-ru"
|
||||
export pkgname="luci-i18n-forkop-ru"
|
||||
add_group_and_user
|
||||
default_postinst
|
||||
EOF
|
||||
@@ -701,7 +644,7 @@ build_apk_package() {
|
||||
-I "description:${description}" \
|
||||
-I "arch:noarch" \
|
||||
-I "license:GPL-2.0-or-later" \
|
||||
-I "origin:podkop-plus" \
|
||||
-I "origin:forkop" \
|
||||
-I "maintainer:${maintainer}" \
|
||||
-I "url:${PROJECT_URL}" \
|
||||
-I "depends:${depends}" \
|
||||
@@ -720,7 +663,7 @@ build_apk_package() {
|
||||
-I "description:${description}" \
|
||||
-I "arch:noarch" \
|
||||
-I "license:GPL-2.0-or-later" \
|
||||
-I "origin:podkop-plus" \
|
||||
-I "origin:forkop" \
|
||||
-I "maintainer:${maintainer}" \
|
||||
-I "url:${PROJECT_URL}" \
|
||||
-I "depends:${depends}" \
|
||||
@@ -742,7 +685,7 @@ build_apk_package() {
|
||||
-I 'description:${description}' \
|
||||
-I 'arch:noarch' \
|
||||
-I 'license:GPL-2.0-or-later' \
|
||||
-I 'origin:podkop-plus' \
|
||||
-I 'origin:forkop' \
|
||||
-I 'maintainer:${maintainer}' \
|
||||
-I 'url:${PROJECT_URL}' \
|
||||
-I 'depends:${depends}' \
|
||||
@@ -764,7 +707,7 @@ build_apk_package() {
|
||||
-I 'description:${description}' \
|
||||
-I 'arch:noarch' \
|
||||
-I 'license:GPL-2.0-or-later' \
|
||||
-I 'origin:podkop-plus' \
|
||||
-I 'origin:forkop' \
|
||||
-I 'maintainer:${maintainer}' \
|
||||
-I 'url:${PROJECT_URL}' \
|
||||
-I 'depends:${depends}' \
|
||||
@@ -845,17 +788,17 @@ sync_artifacts_to_windows() {
|
||||
fi
|
||||
|
||||
rm -f \
|
||||
"$WINDOWS_ARTIFACTS_DIR"/podkop-plus_* \
|
||||
"$WINDOWS_ARTIFACTS_DIR"/luci-app-podkop-plus_* \
|
||||
"$WINDOWS_ARTIFACTS_DIR"/luci-i18n-podkop-plus-ru_*
|
||||
"$WINDOWS_ARTIFACTS_DIR"/forkop_* \
|
||||
"$WINDOWS_ARTIFACTS_DIR"/luci-app-forkop_* \
|
||||
"$WINDOWS_ARTIFACTS_DIR"/luci-i18n-forkop-ru_*
|
||||
|
||||
cp -f \
|
||||
"$output_dir"/podkop-plus_"${RELEASE_VERSION}"_all.ipk \
|
||||
"$output_dir"/luci-app-podkop-plus_"${RELEASE_VERSION}"_all.ipk \
|
||||
"$output_dir"/luci-i18n-podkop-plus-ru_"${RELEASE_VERSION}"_all.ipk \
|
||||
"$output_dir"/podkop-plus_"${RELEASE_VERSION}".apk \
|
||||
"$output_dir"/luci-app-podkop-plus_"${RELEASE_VERSION}".apk \
|
||||
"$output_dir"/luci-i18n-podkop-plus-ru_"${RELEASE_VERSION}".apk \
|
||||
"$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 \
|
||||
"$WINDOWS_ARTIFACTS_DIR"/
|
||||
|
||||
echo "Synced artifacts to Windows path: $WINDOWS_ARTIFACTS_DIR" >&2
|
||||
@@ -900,7 +843,7 @@ main() {
|
||||
mkdir -p "$WORK_DIR"
|
||||
output_dir="${OUTPUT_DIR_INPUT:-$ROOT_DIR/dist/release-final}"
|
||||
mkdir -p "$output_dir"
|
||||
rm -f "$output_dir"/podkop-plus_* "$output_dir"/luci-app-podkop-plus_* "$output_dir"/luci-i18n-podkop-plus-ru_*
|
||||
rm -f "$output_dir"/forkop_* "$output_dir"/luci-app-forkop_* "$output_dir"/luci-i18n-forkop-ru_*
|
||||
|
||||
ipk_archive="$(download_sdk_archive "$IPK_SDK_URL")"
|
||||
apk_archive="$(download_sdk_archive "$APK_SDK_URL")"
|
||||
@@ -927,74 +870,74 @@ main() {
|
||||
|
||||
build_ipk_package \
|
||||
"$ipkg_build_bin" \
|
||||
"podkop-plus" \
|
||||
"forkop" \
|
||||
"$backend_root" \
|
||||
"$backend_control" \
|
||||
"$output_dir/podkop-plus_${RELEASE_VERSION}_all.ipk"
|
||||
"$output_dir/forkop_${RELEASE_VERSION}.ipk"
|
||||
|
||||
build_ipk_package \
|
||||
"$ipkg_build_bin" \
|
||||
"luci-app-podkop-plus" \
|
||||
"luci-app-forkop" \
|
||||
"$app_root" \
|
||||
"$app_control" \
|
||||
"$output_dir/luci-app-podkop-plus_${RELEASE_VERSION}_all.ipk"
|
||||
"$output_dir/luci-app-forkop_${RELEASE_VERSION}.ipk"
|
||||
|
||||
build_ipk_package \
|
||||
"$ipkg_build_bin" \
|
||||
"luci-i18n-podkop-plus-ru" \
|
||||
"luci-i18n-forkop-ru" \
|
||||
"$i18n_root" \
|
||||
"$i18n_control" \
|
||||
"$output_dir/luci-i18n-podkop-plus-ru_${RELEASE_VERSION}_all.ipk"
|
||||
"$output_dir/luci-i18n-forkop-ru_${RELEASE_VERSION}.ipk"
|
||||
|
||||
generate_apk_metadata_files "podkop-plus" "$backend_root" "/etc/config/podkop-plus"
|
||||
generate_apk_metadata_files "luci-app-podkop-plus" "$app_root"
|
||||
generate_apk_metadata_files "luci-i18n-podkop-plus-ru" "$i18n_root"
|
||||
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"
|
||||
write_backend_apk_scripts "$apk_scripts"
|
||||
write_app_apk_scripts "$apk_scripts"
|
||||
write_i18n_apk_scripts "$apk_scripts"
|
||||
|
||||
build_apk_package \
|
||||
"$apk_bin" \
|
||||
"podkop-plus" \
|
||||
"forkop" \
|
||||
"$APK_INTERNAL_VERSION" \
|
||||
"$BACKEND_DESCRIPTION" \
|
||||
"$BACKEND_DEPENDS_APK" \
|
||||
"$backend_root" \
|
||||
"$apk_scripts" \
|
||||
"backend" \
|
||||
"$output_dir/podkop-plus_${RELEASE_VERSION}.apk" \
|
||||
"$output_dir/forkop_${RELEASE_VERSION}.apk" \
|
||||
"$MAINTAINER"
|
||||
|
||||
build_apk_package \
|
||||
"$apk_bin" \
|
||||
"luci-app-podkop-plus" \
|
||||
"luci-app-forkop" \
|
||||
"$APK_INTERNAL_VERSION" \
|
||||
"$APP_DESCRIPTION" \
|
||||
"$APP_DEPENDS_APK" \
|
||||
"$app_root" \
|
||||
"$apk_scripts" \
|
||||
"app" \
|
||||
"$output_dir/luci-app-podkop-plus_${RELEASE_VERSION}.apk" \
|
||||
"$output_dir/luci-app-forkop_${RELEASE_VERSION}.apk" \
|
||||
"$MAINTAINER"
|
||||
|
||||
build_apk_package \
|
||||
"$apk_bin" \
|
||||
"luci-i18n-podkop-plus-ru" \
|
||||
"luci-i18n-forkop-ru" \
|
||||
"$APK_INTERNAL_VERSION" \
|
||||
"$I18N_DESCRIPTION" \
|
||||
"libc luci-app-podkop-plus" \
|
||||
"libc luci-app-forkop" \
|
||||
"$i18n_root" \
|
||||
"$apk_scripts" \
|
||||
"i18n" \
|
||||
"$output_dir/luci-i18n-podkop-plus-ru_${RELEASE_VERSION}.apk" \
|
||||
"$output_dir/luci-i18n-forkop-ru_${RELEASE_VERSION}.apk" \
|
||||
"$MAINTAINER"
|
||||
|
||||
verify_ipk_metadata "$output_dir/podkop-plus_${RELEASE_VERSION}_all.ipk" "podkop-plus" "$RELEASE_VERSION"
|
||||
verify_ipk_metadata "$output_dir/luci-app-podkop-plus_${RELEASE_VERSION}_all.ipk" "luci-app-podkop-plus" "$RELEASE_VERSION"
|
||||
verify_ipk_metadata "$output_dir/luci-i18n-podkop-plus-ru_${RELEASE_VERSION}_all.ipk" "luci-i18n-podkop-plus-ru" "$RELEASE_VERSION"
|
||||
verify_apk_metadata "$apk_bin" "$output_dir/podkop-plus_${RELEASE_VERSION}.apk" "podkop-plus" "$APK_INTERNAL_VERSION"
|
||||
verify_apk_metadata "$apk_bin" "$output_dir/luci-app-podkop-plus_${RELEASE_VERSION}.apk" "luci-app-podkop-plus" "$APK_INTERNAL_VERSION"
|
||||
verify_apk_metadata "$apk_bin" "$output_dir/luci-i18n-podkop-plus-ru_${RELEASE_VERSION}.apk" "luci-i18n-podkop-plus-ru" "$APK_INTERNAL_VERSION"
|
||||
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"
|
||||
|
||||
cleanup_work_dir
|
||||
sync_artifacts_to_windows "$output_dir"
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
SFTP_HOST=192.168.160.129
|
||||
SFTP_PORT=22
|
||||
SFTP_USER=root
|
||||
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_BIN=../forkop/files/usr/bin/
|
||||
REMOTE_DIR_BIN=/usr/bin/
|
||||
|
||||
LOCAL_DIR_LIB=../forkop/files/usr/lib/
|
||||
REMOTE_DIR_LIB=/usr/lib/forkop/
|
||||
@@ -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-podkop-plus/po');
|
||||
const targetRoot = path.resolve(__dirname, '../luci-app-forkop/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 === 'podkop_plus.pot') {
|
||||
const potTarget = path.join(targetRoot, 'templates', 'podkop_plus.pot');
|
||||
if (file === 'forkop.pot') {
|
||||
const potTarget = path.join(targetRoot, 'templates', 'forkop.pot');
|
||||
await fs.mkdir(path.dirname(potTarget), { recursive: true });
|
||||
await fs.copyFile(filePath, potTarget);
|
||||
console.log(`✅ Copied POT: ${filePath} → ${potTarget}`);
|
||||
}
|
||||
|
||||
const match = file.match(/^podkop_plus\.([a-zA-Z_]+)\.po$/);
|
||||
const match = file.match(/^forkop\.([a-zA-Z_]+)\.po$/);
|
||||
if (match) {
|
||||
const lang = match[1];
|
||||
const poTarget = path.join(targetRoot, lang, 'podkop_plus.po');
|
||||
const poTarget = path.join(targetRoot, lang, 'forkop.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-podkop-plus/htdocs/luci-static/resources/view/podkop/**/*.js',
|
||||
'../luci-app-forkop/htdocs/luci-static/resources/view/forkop/**/*.js',
|
||||
], {
|
||||
ignore: [
|
||||
'**/*.test.ts',
|
||||
'**/main.js',
|
||||
'../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/main.js',
|
||||
'../luci-app-forkop/htdocs/luci-static/resources/view/forkop/main.js',
|
||||
],
|
||||
absolute: true,
|
||||
});
|
||||
@@ -8,7 +8,7 @@ if (!lang) {
|
||||
}
|
||||
|
||||
const callsPath = 'locales/calls.json';
|
||||
const poPath = `locales/podkop_plus.${lang}.po`;
|
||||
const poPath = `locales/forkop.${lang}.po`;
|
||||
|
||||
function getGitUser() {
|
||||
try {
|
||||
@@ -36,14 +36,14 @@ function getHeader(lang) {
|
||||
: 'nplurals=2; plural=(n != 1);';
|
||||
|
||||
return [
|
||||
`# ${lang.toUpperCase()} translations for PODKOP PLUS package.`,
|
||||
`# Copyright (C) ${now.getFullYear()} THE PODKOP PLUS COPYRIGHT HOLDER`,
|
||||
`# This file is distributed under the same license as the PODKOP PLUS package.`,
|
||||
`# ${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.`,
|
||||
`# ${translator}, ${now.getFullYear()}.`,
|
||||
'#',
|
||||
'msgid ""',
|
||||
'msgstr ""',
|
||||
`"Project-Id-Version: PODKOP PLUS\\n"`,
|
||||
`"Project-Id-Version: FORKOP\\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 { execSync } from 'child_process';
|
||||
|
||||
const inputFile = 'locales/calls.json';
|
||||
const outputFile = 'locales/podkop_plus.pot';
|
||||
const projectId = 'PODKOP PLUS';
|
||||
const outputFile = 'locales/forkop.pot';
|
||||
const projectId = 'FORKOP';
|
||||
|
||||
function getGitUser() {
|
||||
try {
|
||||
@@ -18,8 +18,8 @@ function getGitUser() {
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'Podkop Plus',
|
||||
email: 'noreply@podkop.plus',
|
||||
name: 'Forkop',
|
||||
email: 'ushan0v@users.noreply.github.com',
|
||||
};
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,14 @@
|
||||
# RU translations for PODKOP PLUS package.
|
||||
# Copyright (C) 2026 THE PODKOP PLUS COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PODKOP PLUS package.
|
||||
# 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.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PODKOP PLUS\n"
|
||||
"Project-Id-Version: FORKOP\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-07-10 02:05+0300\n"
|
||||
"PO-Revision-Date: 2026-07-10 02:05+0300\n"
|
||||
"POT-Creation-Date: 2026-07-11 06:01+0300\n"
|
||||
"PO-Revision-Date: 2026-07-11 06:01+0300\n"
|
||||
"Last-Translator: ushan0v\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: ru\n"
|
||||
@@ -185,8 +185,8 @@ msgstr "Встроенные наборы правил"
|
||||
msgid "By flag emoji from name"
|
||||
msgstr "По эмодзи флага из названия"
|
||||
|
||||
msgid "ByeDPI listen address and port are assigned by Podkop Plus and must not be set in the strategy."
|
||||
msgstr "Адрес и порт прослушивания ByeDPI назначаются Podkop Plus и не должны задаваться в стратегии."
|
||||
msgid "ByeDPI listen address and port are assigned by Forkop and must not be set in the strategy."
|
||||
msgstr "Адрес и порт прослушивания ByeDPI назначаются Forkop и не должны задаваться в стратегии."
|
||||
|
||||
msgid "ByeDPI option does not accept a compact value: %s"
|
||||
msgstr "Опция ByeDPI не принимает компактное значение: %s"
|
||||
@@ -317,8 +317,8 @@ msgstr "Условия"
|
||||
msgid "Config File Path"
|
||||
msgstr "Путь к файлу конфигурации"
|
||||
|
||||
msgid "Configuration for Podkop Plus service"
|
||||
msgstr "Настройки сервиса Podkop Plus"
|
||||
msgid "Configuration for Forkop service"
|
||||
msgstr "Настройки сервиса Forkop"
|
||||
|
||||
msgid "Configure User-Agent in the item settings"
|
||||
msgstr "Настройте User-Agent в настройках элемента"
|
||||
@@ -368,8 +368,8 @@ msgstr "Дашборд сейчас недоступен"
|
||||
msgid "Default address for checking server availability and latency. URLTest uses its own address."
|
||||
msgstr "Адрес по умолчанию для проверки доступности и задержки серверов. Для URLTest используется собственный адрес."
|
||||
|
||||
msgid "Delay in milliseconds before reloading Podkop Plus after interface UP"
|
||||
msgstr "Задержка в миллисекундах перед перезапуском Podkop Plus после поднятия интерфейса"
|
||||
msgid "Delay in milliseconds before reloading Forkop after interface UP"
|
||||
msgstr "Задержка в миллисекундах перед перезапуском Forkop после поднятия интерфейса"
|
||||
|
||||
msgid "Delay value cannot be empty"
|
||||
msgstr "Значение задержки не может быть пустым"
|
||||
@@ -416,8 +416,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 Podkop Plus sends matched traffic through NFQUEUE."
|
||||
msgstr "Отключение перехвата несовместимо с action=zapret2, потому что Podkop Plus отправляет совпавший трафик через NFQUEUE."
|
||||
msgid "Disabling interception is incompatible with action=zapret2 because Forkop sends matched traffic through NFQUEUE."
|
||||
msgstr "Отключение перехвата несовместимо с action=zapret2, потому что Forkop отправляет совпавший трафик через NFQUEUE."
|
||||
|
||||
msgid "Dismiss"
|
||||
msgstr "Отмена"
|
||||
@@ -602,11 +602,11 @@ msgstr "Истекает"
|
||||
msgid "Expose this section as a local HTTP+SOCKS proxy"
|
||||
msgstr "Открыть эту секцию как локальный HTTP+SOCKS прокси"
|
||||
|
||||
msgid "External nfqws config files bypass Podkop Plus queue management and explicit validation."
|
||||
msgstr "Внешние конфиги nfqws обходят управление очередями и явную валидацию Podkop Plus."
|
||||
msgid "External nfqws config files bypass Forkop queue management and explicit validation."
|
||||
msgstr "Внешние конфиги nfqws обходят управление очередями и явную валидацию Forkop."
|
||||
|
||||
msgid "External nfqws2 config files bypass Podkop Plus queue management and explicit validation."
|
||||
msgstr "Внешние конфиги nfqws2 обходят управление очередями и явную валидацию Podkop Plus."
|
||||
msgid "External nfqws2 config files bypass Forkop queue management and explicit validation."
|
||||
msgstr "Внешние конфиги nfqws2 обходят управление очередями и явную валидацию Forkop."
|
||||
|
||||
msgid "Failed to close connection"
|
||||
msgstr "Не удалось закрыть подключение"
|
||||
@@ -653,6 +653,63 @@ 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 фронтинга"
|
||||
|
||||
@@ -662,8 +719,8 @@ msgstr "Порт фронтинга"
|
||||
msgid "Fronting proxy protocol"
|
||||
msgstr "Proxy protocol для фронтинга"
|
||||
|
||||
msgid "Fuzzing is not supported here because Podkop Plus needs deterministic runtime validation."
|
||||
msgstr "Fuzzing здесь не поддерживается, потому что Podkop Plus нужна предсказуемая runtime-валидация."
|
||||
msgid "Fuzzing is not supported here because Forkop needs deterministic runtime validation."
|
||||
msgstr "Fuzzing здесь не поддерживается, потому что Forkop нужна предсказуемая runtime-валидация."
|
||||
|
||||
msgid "Generate HWID from router hardware information for this subscription"
|
||||
msgstr "Генерировать HWID из аппаратной информации роутера для этой подписки"
|
||||
@@ -1283,63 +1340,6 @@ msgstr "Периодически проверять текущий уровен
|
||||
msgid "Pin on dashboard"
|
||||
msgstr "Закрепить в дашборде"
|
||||
|
||||
msgid "Podkop Plus Error"
|
||||
msgstr "Ошибка Podkop Plus"
|
||||
|
||||
msgid "Podkop Plus manages ciadpi pid files itself, so pidfile options are not allowed here."
|
||||
msgstr "Podkop Plus сам управляет pid-файлами ciadpi, поэтому параметры pidfile здесь запрещены."
|
||||
|
||||
msgid "Podkop Plus manages the ciadpi process lifecycle itself, so daemon mode is not allowed here."
|
||||
msgstr "Podkop Plus сам управляет жизненным циклом ciadpi, поэтому режим daemon здесь запрещён."
|
||||
|
||||
msgid "Podkop Plus manages the nfqws process lifecycle itself, so daemon mode is not allowed here."
|
||||
msgstr "Podkop Plus сам управляет жизненным циклом nfqws, поэтому режим daemon здесь запрещён."
|
||||
|
||||
msgid "Podkop Plus manages the nfqws2 process lifecycle itself, so daemon mode is not allowed here."
|
||||
msgstr "Podkop Plus сам управляет жизненным циклом nfqws2, поэтому режим daemon здесь запрещён."
|
||||
|
||||
msgid "Podkop Plus service is stopped. Start the service to display connections."
|
||||
msgstr "Служба Podkop Plus остановлена. Запустите сервис для отображения подключений."
|
||||
|
||||
msgid "Podkop Plus service is stopped. Start the service to display the dashboard."
|
||||
msgstr "Служба Podkop Plus остановлена. Запустите сервис для отображения дашборда."
|
||||
|
||||
msgid "Podkop Plus Settings"
|
||||
msgstr "Настройки Podkop Plus"
|
||||
|
||||
msgid "Podkop Plus will not modify your DHCP configuration"
|
||||
msgstr "Podkop Plus не будет изменять вашу конфигурацию DHCP"
|
||||
|
||||
msgid "Podkop Plus-managed ciadpi runtime has restarted"
|
||||
msgstr "ciadpi Podkop Plus перезапускался"
|
||||
|
||||
msgid "Podkop Plus-managed ciadpi runtime is not ready"
|
||||
msgstr "ciadpi Podkop Plus не готов"
|
||||
|
||||
msgid "Podkop Plus-managed ciadpi runtime is not running"
|
||||
msgstr "ciadpi Podkop Plus не запущен"
|
||||
|
||||
msgid "Podkop Plus-managed ciadpi runtime is ready"
|
||||
msgstr "ciadpi Podkop Plus готов"
|
||||
|
||||
msgid "Podkop Plus-managed nfqws runtime is not ready"
|
||||
msgstr "NFQWS Podkop Plus не готов"
|
||||
|
||||
msgid "Podkop Plus-managed nfqws runtime is not running"
|
||||
msgstr "NFQWS Podkop Plus не запущен"
|
||||
|
||||
msgid "Podkop Plus-managed nfqws runtime is ready"
|
||||
msgstr "NFQWS Podkop Plus готов"
|
||||
|
||||
msgid "Podkop Plus-managed nfqws2 runtime is not ready"
|
||||
msgstr "NFQWS2 Podkop Plus не готов"
|
||||
|
||||
msgid "Podkop Plus-managed nfqws2 runtime is not running"
|
||||
msgstr "NFQWS2 Podkop Plus не запущен"
|
||||
|
||||
msgid "Podkop Plus-managed nfqws2 runtime is ready"
|
||||
msgstr "NFQWS2 Podkop Plus готов"
|
||||
|
||||
msgid "Port cannot be empty"
|
||||
msgstr "Порт не может быть пустым"
|
||||
|
||||
@@ -1457,8 +1457,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 Podkop Plus"
|
||||
msgstr "Перезапустить Podkop Plus"
|
||||
msgid "Restart Forkop"
|
||||
msgstr "Перезапустить Forkop"
|
||||
|
||||
msgid "Resume updates"
|
||||
msgstr "Продолжить обновление"
|
||||
@@ -1703,8 +1703,8 @@ msgstr "Укажите разные файлы"
|
||||
msgid "Standalone ByeDPI autostart is enabled"
|
||||
msgstr "Автозапуск отдельной службы ByeDPI включен"
|
||||
|
||||
msgid "Standalone ByeDPI is active together with Podkop Plus ByeDPI rules"
|
||||
msgstr "Отдельная служба ByeDPI активна вместе с правилами ByeDPI в Podkop Plus"
|
||||
msgid "Standalone ByeDPI is active together with Forkop ByeDPI rules"
|
||||
msgstr "Отдельная служба ByeDPI активна вместе с правилами ByeDPI в Forkop"
|
||||
|
||||
msgid "Standalone ByeDPI service is active"
|
||||
msgstr "Отдельная служба ByeDPI активна"
|
||||
@@ -1712,8 +1712,8 @@ msgstr "Отдельная служба ByeDPI активна"
|
||||
msgid "Standalone ByeDPI service is inactive"
|
||||
msgstr "Отдельная служба ByeDPI неактивна"
|
||||
|
||||
msgid "Standalone Zapret is active together with Podkop Plus Zapret rules"
|
||||
msgstr "Отдельная служба Zapret активна вместе с правилами Zapret в Podkop Plus"
|
||||
msgid "Standalone Zapret is active together with Forkop Zapret rules"
|
||||
msgstr "Отдельная служба Zapret активна вместе с правилами Zapret в Forkop"
|
||||
|
||||
msgid "Standalone Zapret service is active"
|
||||
msgstr "Отдельная служба Zapret активна"
|
||||
@@ -1724,8 +1724,8 @@ msgstr "Отдельная служба Zapret неактивна"
|
||||
msgid "Standalone Zapret2 autostart is enabled"
|
||||
msgstr "Автозапуск отдельной службы Zapret2 включён"
|
||||
|
||||
msgid "Standalone Zapret2 is active together with Podkop Plus Zapret2 rules"
|
||||
msgstr "Отдельная служба Zapret2 активна вместе с правилами Zapret2 в Podkop Plus"
|
||||
msgid "Standalone Zapret2 is active together with Forkop Zapret2 rules"
|
||||
msgstr "Отдельная служба Zapret2 активна вместе с правилами Zapret2 в Forkop"
|
||||
|
||||
msgid "Standalone Zapret2 service is active"
|
||||
msgstr "Отдельная служба Zapret2 активна"
|
||||
@@ -1733,14 +1733,14 @@ msgstr "Отдельная служба Zapret2 активна"
|
||||
msgid "Standalone Zapret2 service is inactive"
|
||||
msgstr "Отдельная служба Zapret2 неактивна"
|
||||
|
||||
msgid "Start Podkop Plus"
|
||||
msgstr "Запустить Podkop Plus"
|
||||
msgid "Start Forkop"
|
||||
msgstr "Запустить Forkop"
|
||||
|
||||
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 Podkop Plus"
|
||||
msgstr "Остановить Podkop Plus"
|
||||
msgid "Stop Forkop"
|
||||
msgstr "Остановить Forkop"
|
||||
|
||||
msgid "Subnets from the list will be extracted and added to nftables"
|
||||
msgstr "IP-адреса и подсети из списка будут извлечены и добавлены в nftables"
|
||||
@@ -1805,11 +1805,11 @@ msgstr "Тестировать серверы, имена которых сов
|
||||
msgid "Testing URL"
|
||||
msgstr "URL проверки"
|
||||
|
||||
msgid "The desync fwmark is managed by Podkop Plus for loop prevention and must not be overridden here."
|
||||
msgstr "Desync fwmark управляется Podkop Plus для защиты от циклов и не должен переопределяться здесь."
|
||||
msgid "The desync fwmark is managed by Forkop for loop prevention and must not be overridden here."
|
||||
msgstr "Desync fwmark управляется Forkop для защиты от циклов и не должен переопределяться здесь."
|
||||
|
||||
msgid "The NFQUEUE number is assigned by Podkop Plus for each rule and must not be overridden here."
|
||||
msgstr "Номер NFQUEUE назначается Podkop Plus для каждого правила и не должен переопределяться здесь."
|
||||
msgid "The NFQUEUE number is assigned by Forkop for each rule and must not be overridden here."
|
||||
msgstr "Номер NFQUEUE назначается Forkop для каждого правила и не должен переопределяться здесь."
|
||||
|
||||
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:."
|
||||
@@ -1874,8 +1874,8 @@ msgstr "Трафик этого уровня пойдёт напрямую."
|
||||
msgid "Traffic Total"
|
||||
msgstr "Всего трафика"
|
||||
|
||||
msgid "Transparent proxy mode is incompatible with action=byedpi because Podkop Plus connects to ciadpi through SOCKS."
|
||||
msgstr "Режим прозрачного прокси несовместим с action=byedpi, потому что Podkop Plus подключается к ciadpi через SOCKS."
|
||||
msgid "Transparent proxy mode is incompatible with action=byedpi because Forkop connects to ciadpi through SOCKS."
|
||||
msgstr "Режим прозрачного прокси несовместим с action=byedpi, потому что Forkop подключается к ciadpi через SOCKS."
|
||||
|
||||
msgid "Transport"
|
||||
msgstr "Транспорт"
|
||||
@@ -1922,14 +1922,14 @@ msgstr "Таймаут недоступности"
|
||||
msgid "Unexpected ByeDPI strategy argument: %s"
|
||||
msgstr "Неожиданный аргумент стратегии ByeDPI: %s"
|
||||
|
||||
msgid "Unexpected Podkop Plus-managed ciadpi runtime is running"
|
||||
msgstr "Обнаружен лишний ciadpi Podkop Plus"
|
||||
msgid "Unexpected Forkop-managed ciadpi runtime is running"
|
||||
msgstr "Обнаружен лишний ciadpi Forkop"
|
||||
|
||||
msgid "Unexpected Podkop Plus-managed nfqws runtime is running"
|
||||
msgstr "Обнаружен лишний NFQWS Podkop Plus"
|
||||
msgid "Unexpected Forkop-managed nfqws runtime is running"
|
||||
msgstr "Обнаружен лишний NFQWS Forkop"
|
||||
|
||||
msgid "Unexpected Podkop Plus-managed nfqws2 runtime is running"
|
||||
msgstr "Обнаружен лишний NFQWS2 Podkop Plus"
|
||||
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 "Неожиданный отдельный токен. Используйте явные флаги вида --имя или --имя=значение."
|
||||
@@ -2099,8 +2099,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 Podkop Plus should do when this section matches"
|
||||
msgstr "Что Podkop Plus должен делать при совпадении этой секции"
|
||||
msgid "What Forkop should do when this section matches"
|
||||
msgstr "Что Forkop должен делать при совпадении этой секции"
|
||||
|
||||
msgid "When switching to another level, test every server and select the fastest instead of the first working one."
|
||||
msgstr "При переходе на другой уровень тестировать все сервера и выбирать самый быстрый, а не первый работающий."
|
||||
@@ -2117,8 +2117,8 @@ msgstr "Да"
|
||||
msgid "You can select Output Network Interface, by default autodetect"
|
||||
msgstr "Вы можете выбрать выходной сетевой интерфейс, по умолчанию он определяется автоматически."
|
||||
|
||||
msgid "Zapret hostlist templates are not supported here because Podkop Plus does not expand them for per-rule NFQWS strategies."
|
||||
msgstr "Шаблоны hostlist zapret здесь не поддерживаются, потому что Podkop Plus не разворачивает их для per-rule стратегий NFQWS."
|
||||
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 package is installed"
|
||||
msgstr "Пакет Zapret установлен"
|
||||
@@ -2138,8 +2138,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 Podkop Plus does not expand them for per-rule NFQWS2 strategies."
|
||||
msgstr "Шаблоны hostlist Zapret2 здесь не поддерживаются, потому что Podkop Plus не разворачивает их для per-rule стратегий NFQWS2."
|
||||
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 package is installed"
|
||||
msgstr "Пакет Zapret2 установлен"
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "fe-app-podkop",
|
||||
"name": "fe-app-forkop",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"format": "prettier --write src",
|
||||
"format:js": "prettier --write ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop",
|
||||
"format:js": "prettier --write ../luci-app-forkop/htdocs/luci-static/resources/view/forkop",
|
||||
"lint": "eslint src --ext .ts,.tsx",
|
||||
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
||||
"build": "tsup src/main.ts",
|
||||
@@ -1,11 +1,10 @@
|
||||
export const PODKOP_UCI_PACKAGE = 'podkop-plus';
|
||||
export const PODKOP_LUCI_APP_VERSION = '__COMPILED_VERSION_VARIABLE__';
|
||||
export const PODKOP_ACTION_PROVIDERS_AVAILABILITY_EVENT =
|
||||
'podkop: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';
|
||||
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 FAKEIP_CHECK_DOMAIN = 'fakeip.forkop.fyi';
|
||||
export const IP_CHECK_DOMAIN = 'ip.forkop.fyi';
|
||||
export const DEFAULT_LATENCY_TEST_URL = 'https://www.gstatic.com/generate_204';
|
||||
export const LATENCY_TEST_URL_OPTIONS = [
|
||||
DEFAULT_LATENCY_TEST_URL,
|
||||
'https://cp.cloudflare.com/generate_204',
|
||||
+18
-18
@@ -1,15 +1,15 @@
|
||||
import { PodkopShellMethods } from '../methods';
|
||||
import { ForkopShellMethods } from '../methods';
|
||||
import { logger } from '../services/logger.service';
|
||||
import { store } from '../services/store.service';
|
||||
import { refreshRuntimeUiState } from '../services/runtimeUiState.service';
|
||||
import { Podkop } from '../types';
|
||||
import { Forkop } from '../types';
|
||||
|
||||
let latestServicesInfoRequestId = 0;
|
||||
|
||||
function getSettledMethodResponse<T>(
|
||||
scope: string,
|
||||
result: PromiseSettledResult<Podkop.MethodResponse<T>>,
|
||||
): Podkop.MethodResponse<T> {
|
||||
result: PromiseSettledResult<Forkop.MethodResponse<T>>,
|
||||
): Forkop.MethodResponse<T> {
|
||||
if (result.status === 'fulfilled') {
|
||||
return result.value;
|
||||
}
|
||||
@@ -34,34 +34,34 @@ export async function fetchServicesInfo() {
|
||||
return uiState;
|
||||
}
|
||||
|
||||
const [podkopResult, singboxResult] = await Promise.allSettled([
|
||||
PodkopShellMethods.getStatus(),
|
||||
PodkopShellMethods.getSingBoxStatus(),
|
||||
const [forkopResult, singboxResult] = await Promise.allSettled([
|
||||
ForkopShellMethods.getStatus(),
|
||||
ForkopShellMethods.getSingBoxStatus(),
|
||||
]);
|
||||
|
||||
if (requestId !== latestServicesInfoRequestId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const podkop = getSettledMethodResponse('getStatus', podkopResult);
|
||||
const forkop = getSettledMethodResponse('getStatus', forkopResult);
|
||||
const singbox = getSettledMethodResponse('getSingBoxStatus', singboxResult);
|
||||
const previousData = store.get().servicesInfoWidget.data;
|
||||
|
||||
store.set({
|
||||
servicesInfoWidget: {
|
||||
loading: false,
|
||||
failed: !podkop.success || !singbox.success,
|
||||
failed: !forkop.success || !singbox.success,
|
||||
data: {
|
||||
singbox: singbox.success ? singbox.data.running : previousData.singbox,
|
||||
podkopRunning: podkop.success
|
||||
? podkop.data.running
|
||||
: previousData.podkopRunning,
|
||||
podkopEnabled: podkop.success
|
||||
? podkop.data.enabled
|
||||
: previousData.podkopEnabled,
|
||||
podkopStatus: podkop.success
|
||||
? podkop.data.status
|
||||
: previousData.podkopStatus,
|
||||
forkopRunning: forkop.success
|
||||
? forkop.data.running
|
||||
: previousData.forkopRunning,
|
||||
forkopEnabled: forkop.success
|
||||
? forkop.data.enabled
|
||||
: previousData.forkopEnabled,
|
||||
forkopStatus: forkop.success
|
||||
? forkop.data.status
|
||||
: previousData.forkopStatus,
|
||||
},
|
||||
},
|
||||
});
|
||||
+8
-8
@@ -20,7 +20,7 @@ describe('fetchServicesInfo', () => {
|
||||
it('returns the fast UI state after applying it to the shared store', async () => {
|
||||
const uiState = {
|
||||
service: {
|
||||
podkop: {
|
||||
forkop: {
|
||||
running: 1,
|
||||
enabled: 1,
|
||||
status: 'restarting',
|
||||
@@ -67,7 +67,7 @@ describe('fetchServicesInfo', () => {
|
||||
|
||||
const state = store.get();
|
||||
|
||||
expect(state.servicesInfoWidget.data.podkopStatus).toBe('restarting');
|
||||
expect(state.servicesInfoWidget.data.forkopStatus).toBe('restarting');
|
||||
expect(state.diagnosticsActions.restart.loading).toBe(true);
|
||||
});
|
||||
|
||||
@@ -78,9 +78,9 @@ describe('fetchServicesInfo', () => {
|
||||
failed: false,
|
||||
data: {
|
||||
singbox: 1,
|
||||
podkopRunning: 1,
|
||||
podkopEnabled: 1,
|
||||
podkopStatus: 'running & enabled',
|
||||
forkopRunning: 1,
|
||||
forkopEnabled: 1,
|
||||
forkopStatus: 'running & enabled',
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -113,9 +113,9 @@ describe('fetchServicesInfo', () => {
|
||||
expect(state.servicesInfoWidget.failed).toBe(true);
|
||||
expect(state.servicesInfoWidget.data).toEqual({
|
||||
singbox: 0,
|
||||
podkopRunning: 1,
|
||||
podkopEnabled: 1,
|
||||
podkopStatus: 'running & enabled',
|
||||
forkopRunning: 1,
|
||||
forkopEnabled: 1,
|
||||
forkopStatus: 'running & enabled',
|
||||
});
|
||||
});
|
||||
});
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
import type { StoreType } from '../services/store.service';
|
||||
import type { Podkop } from '../types';
|
||||
import type { Forkop } from '../types';
|
||||
|
||||
export type UpdatesActionKey = keyof StoreType['updatesActions'];
|
||||
|
||||
const componentActionKeyMap: Record<string, UpdatesActionKey> = {
|
||||
'podkop:check_update': 'podkopCheck',
|
||||
'podkop:install': 'podkopInstall',
|
||||
'forkop:check_update': 'forkopCheck',
|
||||
'forkop:install': 'forkopInstall',
|
||||
'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: Podkop.ComponentName,
|
||||
action: Podkop.ComponentAction,
|
||||
component: Forkop.ComponentName,
|
||||
action: Forkop.ComponentAction,
|
||||
): UpdatesActionKey | undefined {
|
||||
return componentActionKeyMap[`${component}:${action}`];
|
||||
}
|
||||
+2
-4
@@ -26,8 +26,7 @@ function isVersionPlaceholder(version?: string) {
|
||||
|
||||
return (
|
||||
(typeof _ === 'function' && normalized === _('unknown').toLowerCase()) ||
|
||||
(typeof _ === 'function' &&
|
||||
normalized === _('Not installed').toLowerCase())
|
||||
(typeof _ === 'function' && normalized === _('Not installed').toLowerCase())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -68,7 +67,6 @@ export function normalizeSingBoxVariantFields<T extends SingBoxVariantFields>(
|
||||
sing_box_extended: singBoxExtended ? 1 : 0,
|
||||
sing_box_tiny: singBoxExtended ? 0 : value.sing_box_tiny ? 1 : 0,
|
||||
sing_box_compressed: singBoxExtended && value.sing_box_compressed ? 1 : 0,
|
||||
sing_box_tailscale:
|
||||
singBoxExtended || value.sing_box_tailscale ? 1 : 0,
|
||||
sing_box_tailscale: singBoxExtended || value.sing_box_tailscale ? 1 : 0,
|
||||
} as T;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { Forkop } from '../../types';
|
||||
import { FORKOP_UCI_PACKAGE } from '../../../constants';
|
||||
|
||||
export async function getConfigSections(): Promise<Forkop.ConfigSection[]> {
|
||||
return uci
|
||||
.load(FORKOP_UCI_PACKAGE)
|
||||
.then(() => uci.sections(FORKOP_UCI_PACKAGE));
|
||||
}
|
||||
+57
-57
@@ -1,5 +1,5 @@
|
||||
import { getConfigSections } from './getConfigSections';
|
||||
import { ClashAPI, Podkop } from '../../types';
|
||||
import { ClashAPI, Forkop } from '../../types';
|
||||
import {
|
||||
canUseDirectClashApi,
|
||||
getClashHttpUrl,
|
||||
@@ -7,11 +7,11 @@ import {
|
||||
isCopyableProxyLink,
|
||||
} from '../../../helpers';
|
||||
import { getOutboundTagBySection } from '../../runtimeTags';
|
||||
import { PodkopShellMethods } from '../shell';
|
||||
import { ForkopShellMethods } from '../shell';
|
||||
|
||||
interface IGetDashboardSectionsResponse {
|
||||
success: boolean;
|
||||
data: Podkop.OutboundGroup[];
|
||||
data: Forkop.OutboundGroup[];
|
||||
}
|
||||
|
||||
interface IGetDashboardSectionsOptions {
|
||||
@@ -28,12 +28,12 @@ type DashboardSectionCache = {
|
||||
section?: string;
|
||||
links?: Record<string, string>;
|
||||
linkRefs?: Record<string, unknown>;
|
||||
outboundMetadata?: Podkop.GetOutboundMetadata;
|
||||
outboundMetadata?: Forkop.GetOutboundMetadata;
|
||||
urltestGroups?: Record<string, UrlTestCacheGroup>;
|
||||
priorityGroups?: Record<string, PriorityCacheGroup>;
|
||||
subscriptionMetadata?:
|
||||
| Podkop.SubscriptionMetadata
|
||||
| Podkop.SubscriptionMetadata[];
|
||||
| Forkop.SubscriptionMetadata
|
||||
| Forkop.SubscriptionMetadata[];
|
||||
};
|
||||
|
||||
type UrlTestCacheGroup = {
|
||||
@@ -129,21 +129,21 @@ type ChildType =
|
||||
| 'priority_group'
|
||||
| 'priority_level';
|
||||
|
||||
const DASHBOARD_SECTION_CACHE_DIR = '/var/run/podkop-plus/section-cache';
|
||||
const DASHBOARD_SECTION_CACHE_DIR = '/var/run/forkop/section-cache';
|
||||
|
||||
function getDisplayName(section: Podkop.ConfigSection) {
|
||||
function getDisplayName(section: Forkop.ConfigSection) {
|
||||
return section.label || section['.name'];
|
||||
}
|
||||
|
||||
function getSectionAction(section: Podkop.ConfigSection) {
|
||||
function getSectionAction(section: Forkop.ConfigSection) {
|
||||
return section.action || '';
|
||||
}
|
||||
|
||||
function getSettingsSection(configSections: Podkop.ConfigSection[]) {
|
||||
function getSettingsSection(configSections: Forkop.ConfigSection[]) {
|
||||
return configSections.find((section) => section['.type'] === 'settings');
|
||||
}
|
||||
|
||||
function getClashApiSecret(configSections: Podkop.ConfigSection[]) {
|
||||
function getClashApiSecret(configSections: Forkop.ConfigSection[]) {
|
||||
return getSettingsSection(configSections)?.yacd_secret_key || '';
|
||||
}
|
||||
|
||||
@@ -152,8 +152,8 @@ function canFetchClashApiDirectly() {
|
||||
}
|
||||
|
||||
async function getClashApiProxies(
|
||||
configSections: Podkop.ConfigSection[],
|
||||
): Promise<Podkop.MethodResponse<ClashAPI.Proxies>> {
|
||||
configSections: Forkop.ConfigSection[],
|
||||
): Promise<Forkop.MethodResponse<ClashAPI.Proxies>> {
|
||||
if (canFetchClashApiDirectly()) {
|
||||
const secret = getClashApiSecret(configSections);
|
||||
|
||||
@@ -173,7 +173,7 @@ async function getClashApiProxies(
|
||||
}
|
||||
}
|
||||
|
||||
return PodkopShellMethods.getClashApiProxies();
|
||||
return ForkopShellMethods.getClashApiProxies();
|
||||
}
|
||||
|
||||
function getListValues(value?: string[] | string) {
|
||||
@@ -192,25 +192,25 @@ function getListValues(value?: string[] | string) {
|
||||
}
|
||||
|
||||
function childSections(
|
||||
configSections: Podkop.ConfigSection[],
|
||||
configSections: Forkop.ConfigSection[],
|
||||
type: ChildType,
|
||||
) {
|
||||
return configSections.filter((section) => section['.type'] === type);
|
||||
}
|
||||
|
||||
function ownedChildSections(
|
||||
parent: Podkop.ConfigSection,
|
||||
children: Podkop.ConfigSection[],
|
||||
parent: Forkop.ConfigSection,
|
||||
children: Forkop.ConfigSection[],
|
||||
) {
|
||||
return children.filter(
|
||||
(section): section is Podkop.ConfigSection =>
|
||||
(section): section is Forkop.ConfigSection =>
|
||||
section.section === parent['.name'],
|
||||
);
|
||||
}
|
||||
|
||||
function childSectionsByOwner(
|
||||
children: Podkop.ConfigSection[],
|
||||
ownerKey: keyof Podkop.ConfigSection,
|
||||
children: Forkop.ConfigSection[],
|
||||
ownerKey: keyof Forkop.ConfigSection,
|
||||
ownerValue: string,
|
||||
) {
|
||||
return children.filter((section) => section[ownerKey] === ownerValue);
|
||||
@@ -220,7 +220,7 @@ function compactSettingsMap(settings: Record<string, ItemSettings>) {
|
||||
return Object.keys(settings).length ? JSON.stringify(settings) : undefined;
|
||||
}
|
||||
|
||||
function hydrateConfigSections(configSections: Podkop.ConfigSection[]) {
|
||||
function hydrateConfigSections(configSections: Forkop.ConfigSection[]) {
|
||||
const subscriptionUrls = childSections(configSections, 'subscription_url');
|
||||
const urltests = childSections(configSections, 'urltest');
|
||||
const priorityGroups = childSections(configSections, 'priority_group');
|
||||
@@ -231,7 +231,7 @@ function hydrateConfigSections(configSections: Podkop.ConfigSection[]) {
|
||||
return section;
|
||||
}
|
||||
|
||||
const next: Podkop.ConfigSection = { ...section };
|
||||
const next: Forkop.ConfigSection = { ...section };
|
||||
const subscriptionUrlItems = ownedChildSections(next, subscriptionUrls);
|
||||
const urltestItems = ownedChildSections(next, urltests);
|
||||
const priorityGroupItems = ownedChildSections(next, priorityGroups);
|
||||
@@ -341,16 +341,16 @@ function hydrateConfigSections(configSections: Podkop.ConfigSection[]) {
|
||||
});
|
||||
}
|
||||
|
||||
function getManualProxyLinks(section: Podkop.ConfigSection) {
|
||||
function getManualProxyLinks(section: Forkop.ConfigSection) {
|
||||
return getListValues(section.selector_proxy_links);
|
||||
}
|
||||
|
||||
function getConnectionInterfaces(section: Podkop.ConfigSection) {
|
||||
function getConnectionInterfaces(section: Forkop.ConfigSection) {
|
||||
const values = getListValues(section.interfaces);
|
||||
return values.length ? values : getListValues(section.interface);
|
||||
}
|
||||
|
||||
function getJsonOutbounds(section: Podkop.ConfigSection) {
|
||||
function getJsonOutbounds(section: Forkop.ConfigSection) {
|
||||
const values = getListValues(section.outbound_jsons);
|
||||
return values.length ? values : getListValues(section.outbound_json);
|
||||
}
|
||||
@@ -359,27 +359,27 @@ function isConnectionAction(action: string) {
|
||||
return ['connection', 'proxy', 'outbound', 'vpn'].includes(action);
|
||||
}
|
||||
|
||||
function hasSubscriptionSources(section: Podkop.ConfigSection) {
|
||||
function hasSubscriptionSources(section: Forkop.ConfigSection) {
|
||||
return getSubscriptionSourceCount(section) > 0;
|
||||
}
|
||||
|
||||
function getSubscriptionSourceCount(section: Podkop.ConfigSection) {
|
||||
function getSubscriptionSourceCount(section: Forkop.ConfigSection) {
|
||||
return getListValues(section.subscription_urls).length;
|
||||
}
|
||||
|
||||
function shouldSortByLatency(section: Podkop.ConfigSection) {
|
||||
function shouldSortByLatency(section: Forkop.ConfigSection) {
|
||||
return section.sort_by_latency === '1';
|
||||
}
|
||||
|
||||
function hasConfiguredUrlTestList(section: Podkop.ConfigSection) {
|
||||
function hasConfiguredUrlTestList(section: Forkop.ConfigSection) {
|
||||
return getListValues(section.urltests).length > 0;
|
||||
}
|
||||
|
||||
function hasConfiguredPriorityList(section: Podkop.ConfigSection) {
|
||||
function hasConfiguredPriorityList(section: Forkop.ConfigSection) {
|
||||
return getListValues(section.priority_groups).length > 0;
|
||||
}
|
||||
|
||||
function getUrlTestIds(section: Podkop.ConfigSection) {
|
||||
function getUrlTestIds(section: Forkop.ConfigSection) {
|
||||
const values = getListValues(section.urltests);
|
||||
return values.length
|
||||
? values
|
||||
@@ -388,11 +388,11 @@ function getUrlTestIds(section: Podkop.ConfigSection) {
|
||||
: [];
|
||||
}
|
||||
|
||||
function isUrlTestEnabled(section: Podkop.ConfigSection) {
|
||||
function isUrlTestEnabled(section: Forkop.ConfigSection) {
|
||||
return getUrlTestIds(section).length > 0;
|
||||
}
|
||||
|
||||
function shouldUseProxyGroup(section: Podkop.ConfigSection) {
|
||||
function shouldUseProxyGroup(section: Forkop.ConfigSection) {
|
||||
return (
|
||||
getManualProxyLinks(section).length > 0 ||
|
||||
hasSubscriptionSources(section) ||
|
||||
@@ -403,7 +403,7 @@ function shouldUseProxyGroup(section: Podkop.ConfigSection) {
|
||||
);
|
||||
}
|
||||
|
||||
function getSectionProxyConfigType(section: Podkop.ConfigSection) {
|
||||
function getSectionProxyConfigType(section: Forkop.ConfigSection) {
|
||||
if (hasSubscriptionSources(section)) {
|
||||
return 'subscription' as const;
|
||||
}
|
||||
@@ -431,7 +431,7 @@ function getSectionProxyConfigType(section: Podkop.ConfigSection) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getJsonOutboundDisplayName(section: Podkop.ConfigSection) {
|
||||
function getJsonOutboundDisplayName(section: Forkop.ConfigSection) {
|
||||
try {
|
||||
const parsedOutbound = JSON.parse(section.outbound_json || '{}');
|
||||
return parsedOutbound?.tag ? decodeURIComponent(parsedOutbound.tag) : '';
|
||||
@@ -440,7 +440,7 @@ function getJsonOutboundDisplayName(section: Podkop.ConfigSection) {
|
||||
}
|
||||
}
|
||||
|
||||
function buildManualLinkByCode(section: Podkop.ConfigSection) {
|
||||
function buildManualLinkByCode(section: Forkop.ConfigSection) {
|
||||
const sectionName = section['.name'];
|
||||
|
||||
return new Map(
|
||||
@@ -459,7 +459,7 @@ function uniqueCodes(codes: string[]) {
|
||||
return Array.from(new Set(codes.filter(Boolean)));
|
||||
}
|
||||
|
||||
function isSelectorOutbound(outbound: Podkop.Outbound) {
|
||||
function isSelectorOutbound(outbound: Forkop.Outbound) {
|
||||
return outbound.type?.toLowerCase() === 'selector';
|
||||
}
|
||||
|
||||
@@ -476,7 +476,7 @@ function getLatencySortValue(outbound: { latency: number }) {
|
||||
}
|
||||
|
||||
function sortOutboundsForDashboard(
|
||||
outbounds: Podkop.Outbound[],
|
||||
outbounds: Forkop.Outbound[],
|
||||
options: {
|
||||
pinnedCode?: string;
|
||||
pinnedCodes?: string[];
|
||||
@@ -527,7 +527,7 @@ function sortOutboundsForDashboard(
|
||||
.map((item) => item.outbound);
|
||||
}
|
||||
|
||||
function sortUrlTestMembers(outbounds: Podkop.UrlTestMember[]) {
|
||||
function sortUrlTestMembers(outbounds: Forkop.UrlTestMember[]) {
|
||||
return outbounds
|
||||
.map((outbound, index) => ({ outbound, index }))
|
||||
.sort((left, right) => {
|
||||
@@ -627,7 +627,7 @@ function getPriorityTag(sectionName: string, id: string) {
|
||||
}
|
||||
|
||||
function getUrlTestDisplayName(
|
||||
section: Podkop.ConfigSection,
|
||||
section: Forkop.ConfigSection,
|
||||
id: string,
|
||||
settings: ItemSettings | undefined,
|
||||
) {
|
||||
@@ -638,7 +638,7 @@ function getUrlTestDisplayName(
|
||||
);
|
||||
}
|
||||
|
||||
function getUrlTestConfigs(section: Podkop.ConfigSection): UrlTestConfig[] {
|
||||
function getUrlTestConfigs(section: Forkop.ConfigSection): UrlTestConfig[] {
|
||||
const settingsMap = itemSettingsMap(section.urltest_settings);
|
||||
const sectionName = section['.name'];
|
||||
|
||||
@@ -721,11 +721,11 @@ function priorityLevelConfigsFromSettings(
|
||||
);
|
||||
}
|
||||
|
||||
function getPriorityGroupIds(section: Podkop.ConfigSection) {
|
||||
function getPriorityGroupIds(section: Forkop.ConfigSection) {
|
||||
return getListValues(section.priority_groups);
|
||||
}
|
||||
|
||||
function getPriorityConfigs(section: Podkop.ConfigSection): PriorityConfig[] {
|
||||
function getPriorityConfigs(section: Forkop.ConfigSection): PriorityConfig[] {
|
||||
const settingsMap = itemSettingsMap(section.priority_group_settings);
|
||||
const sectionName = section['.name'];
|
||||
|
||||
@@ -831,7 +831,7 @@ function getOutboundDisplayName(
|
||||
code: string,
|
||||
entry: ClashProxyEntry | undefined,
|
||||
link: string,
|
||||
outboundMetadata?: Podkop.GetOutboundMetadata,
|
||||
outboundMetadata?: Forkop.GetOutboundMetadata,
|
||||
preferMetadata = false,
|
||||
) {
|
||||
const metadataName = outboundMetadata?.names?.[code];
|
||||
@@ -863,10 +863,10 @@ function buildUrlTestInfo({
|
||||
proxyByCode: Map<string, ClashProxyEntry>;
|
||||
manualLinkByCode: Map<string, string>;
|
||||
cachedProxyLinks: Map<string, string>;
|
||||
outboundMetadata?: Podkop.GetOutboundMetadata;
|
||||
outboundMetadata?: Forkop.GetOutboundMetadata;
|
||||
subscriptionCopyableCodes: Set<string>;
|
||||
showDetectedCountries: boolean;
|
||||
}): Podkop.UrlTestInfo {
|
||||
}): Forkop.UrlTestInfo {
|
||||
const childCodes = uniqueCodes(
|
||||
groupCache?.outbounds?.length
|
||||
? groupCache.outbounds
|
||||
@@ -940,10 +940,10 @@ function buildPriorityInfo({
|
||||
proxyByCode: Map<string, ClashProxyEntry>;
|
||||
manualLinkByCode: Map<string, string>;
|
||||
cachedProxyLinks: Map<string, string>;
|
||||
outboundMetadata?: Podkop.GetOutboundMetadata;
|
||||
outboundMetadata?: Forkop.GetOutboundMetadata;
|
||||
subscriptionCopyableCodes: Set<string>;
|
||||
showDetectedCountries: boolean;
|
||||
}): Podkop.PriorityInfo {
|
||||
}): Forkop.PriorityInfo {
|
||||
const selectedCode = entry?.value.now || '';
|
||||
const cacheLevels = Array.isArray(groupCache?.levels)
|
||||
? groupCache.levels
|
||||
@@ -1067,9 +1067,9 @@ function buildPriorityInfo({
|
||||
}
|
||||
|
||||
function buildProxyGroupOutbounds(
|
||||
section: Podkop.ConfigSection,
|
||||
section: Forkop.ConfigSection,
|
||||
proxies: ClashProxyEntry[],
|
||||
outboundMetadata?: Podkop.GetOutboundMetadata,
|
||||
outboundMetadata?: Forkop.GetOutboundMetadata,
|
||||
urltestGroups: Record<string, UrlTestCacheGroup> = {},
|
||||
priorityGroups: Record<string, PriorityCacheGroup> = {},
|
||||
subscriptionCopyableCodes: Set<string> = new Set(),
|
||||
@@ -1252,9 +1252,9 @@ function buildProxyGroupOutbounds(
|
||||
function metadataMatchesCurrentSource(
|
||||
sectionName: string,
|
||||
sourceCount: number,
|
||||
metadata: Podkop.SubscriptionMetadata,
|
||||
metadata: Forkop.SubscriptionMetadata,
|
||||
) {
|
||||
const legacyMetadata = metadata as Podkop.SubscriptionMetadata & {
|
||||
const legacyMetadata = metadata as Forkop.SubscriptionMetadata & {
|
||||
source_index?: number;
|
||||
source_section?: string;
|
||||
};
|
||||
@@ -1306,9 +1306,9 @@ function metadataMatchesCurrentSource(
|
||||
function getSubscriptionMetadataSourceIndex(
|
||||
sectionName: string,
|
||||
sourceCount: number,
|
||||
metadata: Podkop.SubscriptionMetadata,
|
||||
metadata: Forkop.SubscriptionMetadata,
|
||||
) {
|
||||
const legacyMetadata = metadata as Podkop.SubscriptionMetadata & {
|
||||
const legacyMetadata = metadata as Forkop.SubscriptionMetadata & {
|
||||
source_index?: number;
|
||||
source_section?: string;
|
||||
};
|
||||
@@ -1331,9 +1331,9 @@ function getSubscriptionMetadataSourceIndex(
|
||||
}
|
||||
|
||||
function isSubscriptionMetadataVisible(
|
||||
section: Podkop.ConfigSection,
|
||||
section: Forkop.ConfigSection,
|
||||
sourceCount: number,
|
||||
metadata: Podkop.SubscriptionMetadata,
|
||||
metadata: Forkop.SubscriptionMetadata,
|
||||
) {
|
||||
const sourceIndex = getSubscriptionMetadataSourceIndex(
|
||||
section['.name'],
|
||||
@@ -1354,7 +1354,7 @@ function isSubscriptionMetadataVisible(
|
||||
}
|
||||
|
||||
function getSubscriptionMetadata(
|
||||
section: Podkop.ConfigSection,
|
||||
section: Forkop.ConfigSection,
|
||||
sourceCount: number,
|
||||
dashboardCache?: DashboardSectionCache,
|
||||
) {
|
||||
+1
-1
@@ -2,7 +2,7 @@ import { getConfigSections } from './getConfigSections';
|
||||
import { getDashboardSections } from './getDashboardSections';
|
||||
import { getClashApiSecret } from './getClashApiSecret';
|
||||
|
||||
export const CustomPodkopMethods = {
|
||||
export const CustomForkopMethods = {
|
||||
getConfigSections,
|
||||
getDashboardSections,
|
||||
getClashApiSecret,
|
||||
+8
-8
@@ -12,7 +12,7 @@ vi.mock('../getConfigSections', () => ({
|
||||
}));
|
||||
|
||||
vi.mock('../../shell', () => ({
|
||||
PodkopShellMethods: {
|
||||
ForkopShellMethods: {
|
||||
getClashApiProxies: mocks.getClashApiProxies,
|
||||
},
|
||||
}));
|
||||
@@ -26,7 +26,7 @@ vi.mock('../../../../helpers', () => ({
|
||||
}));
|
||||
|
||||
import { getDashboardSections } from '../getDashboardSections';
|
||||
import { ClashAPI, Podkop } from '../../../types';
|
||||
import { ClashAPI, Forkop } from '../../../types';
|
||||
|
||||
function proxy(
|
||||
type: string,
|
||||
@@ -43,8 +43,8 @@ function proxy(
|
||||
}
|
||||
|
||||
function proxySection(
|
||||
options: Partial<Podkop.ConfigSection> = {},
|
||||
): Podkop.ConfigSection {
|
||||
options: Partial<Forkop.ConfigSection> = {},
|
||||
): Forkop.ConfigSection {
|
||||
return {
|
||||
'.name': 'main',
|
||||
'.type': 'section',
|
||||
@@ -71,8 +71,8 @@ function urlTestSettings(
|
||||
|
||||
function priorityGroup(
|
||||
id: string,
|
||||
options: Partial<Podkop.ConfigSection> = {},
|
||||
): Podkop.ConfigSection {
|
||||
options: Partial<Forkop.ConfigSection> = {},
|
||||
): Forkop.ConfigSection {
|
||||
return {
|
||||
'.name': id,
|
||||
'.type': 'priority_group',
|
||||
@@ -94,8 +94,8 @@ function priorityGroup(
|
||||
|
||||
function priorityLevel(
|
||||
id: string,
|
||||
options: Partial<Podkop.ConfigSection> = {},
|
||||
): Podkop.ConfigSection {
|
||||
options: Partial<Forkop.ConfigSection> = {},
|
||||
): Forkop.ConfigSection {
|
||||
return {
|
||||
'.name': id,
|
||||
'.type': 'priority_level',
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
import { executeShellCommand } from '../../../helpers';
|
||||
import { Podkop } from '../../types';
|
||||
import { Forkop } from '../../types';
|
||||
|
||||
interface CallBaseMethodOptions {
|
||||
allowNonZeroWithStdout?: boolean;
|
||||
@@ -7,11 +7,11 @@ interface CallBaseMethodOptions {
|
||||
}
|
||||
|
||||
export async function callBaseMethod<T>(
|
||||
method: Podkop.AvailableMethods,
|
||||
method: Forkop.AvailableMethods,
|
||||
args: string[] = [],
|
||||
command: string = '/usr/bin/podkop-plus',
|
||||
command: string = '/usr/bin/forkop',
|
||||
options: CallBaseMethodOptions = {},
|
||||
): Promise<Podkop.MethodResponse<T>> {
|
||||
): Promise<Forkop.MethodResponse<T>> {
|
||||
try {
|
||||
const response = await executeShellCommand({
|
||||
command,
|
||||
+141
-141
@@ -1,5 +1,5 @@
|
||||
import { callBaseMethod } from './callBaseMethod';
|
||||
import { ClashAPI, Podkop } from '../../types';
|
||||
import { ClashAPI, Forkop } 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/podkop-plus/component-actions';
|
||||
const COMPONENT_ACTION_STATE_DIR = '/var/run/forkop/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<Podkop.ComponentActionResult>(output);
|
||||
return parseJsonObjectOutput<Forkop.ComponentActionResult>(output);
|
||||
}
|
||||
|
||||
function parseComponentActionResult(
|
||||
@@ -68,13 +68,13 @@ function parseComponentActionStartResult(
|
||||
return null;
|
||||
}
|
||||
|
||||
return parsedResponse as unknown as Podkop.ComponentActionStartResult;
|
||||
return parsedResponse as unknown as Forkop.ComponentActionStartResult;
|
||||
}
|
||||
|
||||
function parseSubscriptionUpdateStartResult(
|
||||
response: Awaited<ReturnType<typeof executeShellCommand>>,
|
||||
) {
|
||||
return parseJsonObjectOutput<Podkop.SubscriptionUpdateStartResult>(
|
||||
return parseJsonObjectOutput<Forkop.SubscriptionUpdateStartResult>(
|
||||
response.stdout,
|
||||
);
|
||||
}
|
||||
@@ -82,7 +82,7 @@ function parseSubscriptionUpdateStartResult(
|
||||
function parseSubscriptionUpdateJobState(
|
||||
response: Awaited<ReturnType<typeof executeShellCommand>>,
|
||||
) {
|
||||
return parseJsonObjectOutput<Podkop.SubscriptionUpdateJobState>(
|
||||
return parseJsonObjectOutput<Forkop.SubscriptionUpdateJobState>(
|
||||
response.stdout,
|
||||
);
|
||||
}
|
||||
@@ -90,19 +90,19 @@ function parseSubscriptionUpdateJobState(
|
||||
function parseUiActionStartResult(
|
||||
response: Awaited<ReturnType<typeof executeShellCommand>>,
|
||||
) {
|
||||
return parseJsonObjectOutput<Podkop.UiActionStartResult>(response.stdout);
|
||||
return parseJsonObjectOutput<Forkop.UiActionStartResult>(response.stdout);
|
||||
}
|
||||
|
||||
function parseServiceActionState(
|
||||
response: Awaited<ReturnType<typeof executeShellCommand>>,
|
||||
) {
|
||||
return parseJsonObjectOutput<Podkop.ServiceActionState>(response.stdout);
|
||||
return parseJsonObjectOutput<Forkop.ServiceActionState>(response.stdout);
|
||||
}
|
||||
|
||||
function parseLatencyActionState(
|
||||
response: Awaited<ReturnType<typeof executeShellCommand>>,
|
||||
) {
|
||||
return parseJsonObjectOutput<Podkop.LatencyActionState>(response.stdout);
|
||||
return parseJsonObjectOutput<Forkop.LatencyActionState>(response.stdout);
|
||||
}
|
||||
|
||||
function isComponentActionJobId(jobId: string) {
|
||||
@@ -123,9 +123,9 @@ async function readComponentActionState(jobId: string) {
|
||||
}
|
||||
}
|
||||
|
||||
async function readPodkopVersion() {
|
||||
async function readForkopVersion() {
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/podkop-plus',
|
||||
command: '/usr/bin/forkop',
|
||||
args: ['show_version'],
|
||||
timeout: COMPONENT_ACTION_RPC_TIMEOUT_MS,
|
||||
});
|
||||
@@ -139,13 +139,13 @@ async function readPodkopVersion() {
|
||||
|
||||
async function isComponentActionStillRunning(
|
||||
jobId: string,
|
||||
component: Podkop.ComponentName,
|
||||
action: Podkop.ComponentAction,
|
||||
component: Forkop.ComponentName,
|
||||
action: Forkop.ComponentAction,
|
||||
) {
|
||||
const response = await callBaseMethod<Podkop.UiState>(
|
||||
Podkop.AvailableMethods.GET_UI_STATE,
|
||||
const response = await callBaseMethod<Forkop.UiState>(
|
||||
Forkop.AvailableMethods.GET_UI_STATE,
|
||||
[],
|
||||
'/usr/bin/podkop-plus',
|
||||
'/usr/bin/forkop',
|
||||
{ timeout: GET_UI_STATE_RPC_TIMEOUT_MS },
|
||||
);
|
||||
|
||||
@@ -163,12 +163,12 @@ async function isComponentActionStillRunning(
|
||||
|
||||
function componentActionFailure(
|
||||
response: Awaited<ReturnType<typeof executeShellCommand>>,
|
||||
parsedResponse?: Pick<Podkop.ComponentActionResult, 'message'> | null,
|
||||
parsedResponse?: Pick<Forkop.ComponentActionResult, 'message'> | null,
|
||||
) {
|
||||
return {
|
||||
success: false,
|
||||
error: parsedResponse?.message || response.stderr || _('Failed to execute'),
|
||||
} as Podkop.MethodFailureResponse;
|
||||
} as Forkop.MethodFailureResponse;
|
||||
}
|
||||
|
||||
function uiActionFailure(
|
||||
@@ -179,7 +179,7 @@ function uiActionFailure(
|
||||
return {
|
||||
success: false,
|
||||
error: parsedResponse?.message || response.stderr || fallback,
|
||||
} as Podkop.MethodFailureResponse;
|
||||
} as Forkop.MethodFailureResponse;
|
||||
}
|
||||
|
||||
function createTransientRpcGraceTracker(graceMs: number) {
|
||||
@@ -204,170 +204,170 @@ function createTransientRpcGraceTracker(graceMs: number) {
|
||||
};
|
||||
}
|
||||
|
||||
export const PodkopShellMethods = {
|
||||
export const ForkopShellMethods = {
|
||||
checkDNSAvailable: async () =>
|
||||
callBaseMethod<Podkop.DnsCheckResult>(
|
||||
Podkop.AvailableMethods.CHECK_DNS_AVAILABLE,
|
||||
callBaseMethod<Forkop.DnsCheckResult>(
|
||||
Forkop.AvailableMethods.CHECK_DNS_AVAILABLE,
|
||||
),
|
||||
checkFakeIP: async () =>
|
||||
callBaseMethod<Podkop.FakeIPCheckResult>(
|
||||
Podkop.AvailableMethods.CHECK_FAKEIP,
|
||||
callBaseMethod<Forkop.FakeIPCheckResult>(
|
||||
Forkop.AvailableMethods.CHECK_FAKEIP,
|
||||
),
|
||||
checkNftRules: async () =>
|
||||
callBaseMethod<Podkop.NftRulesCheckResult>(
|
||||
Podkop.AvailableMethods.CHECK_NFT_RULES,
|
||||
callBaseMethod<Forkop.NftRulesCheckResult>(
|
||||
Forkop.AvailableMethods.CHECK_NFT_RULES,
|
||||
),
|
||||
checkZapretRuntime: async () =>
|
||||
callBaseMethod<Podkop.ZapretCheckResult>(
|
||||
Podkop.AvailableMethods.CHECK_ZAPRET_RUNTIME,
|
||||
callBaseMethod<Forkop.ZapretCheckResult>(
|
||||
Forkop.AvailableMethods.CHECK_ZAPRET_RUNTIME,
|
||||
),
|
||||
checkZapret2Runtime: async () =>
|
||||
callBaseMethod<Podkop.Zapret2CheckResult>(
|
||||
Podkop.AvailableMethods.CHECK_ZAPRET2_RUNTIME,
|
||||
callBaseMethod<Forkop.Zapret2CheckResult>(
|
||||
Forkop.AvailableMethods.CHECK_ZAPRET2_RUNTIME,
|
||||
),
|
||||
checkByedpiRuntime: async () =>
|
||||
callBaseMethod<Podkop.ByedpiCheckResult>(
|
||||
Podkop.AvailableMethods.CHECK_BYEDPI_RUNTIME,
|
||||
callBaseMethod<Forkop.ByedpiCheckResult>(
|
||||
Forkop.AvailableMethods.CHECK_BYEDPI_RUNTIME,
|
||||
),
|
||||
checkInboundsConfig: async () =>
|
||||
callBaseMethod<Podkop.InboundsConfigCheckResult>(
|
||||
Podkop.AvailableMethods.CHECK_INBOUNDS_CONFIG,
|
||||
callBaseMethod<Forkop.InboundsConfigCheckResult>(
|
||||
Forkop.AvailableMethods.CHECK_INBOUNDS_CONFIG,
|
||||
),
|
||||
getStatus: async () =>
|
||||
callBaseMethod<Podkop.GetStatus>(Podkop.AvailableMethods.GET_STATUS),
|
||||
callBaseMethod<Forkop.GetStatus>(Forkop.AvailableMethods.GET_STATUS),
|
||||
getOutboundLink: async (section: string, tag: string) =>
|
||||
callBaseMethod<Podkop.GetOutboundLink>(
|
||||
Podkop.AvailableMethods.GET_OUTBOUND_LINK,
|
||||
callBaseMethod<Forkop.GetOutboundLink>(
|
||||
Forkop.AvailableMethods.GET_OUTBOUND_LINK,
|
||||
[section, tag],
|
||||
),
|
||||
getOutboundLinkStates: async (section: string) =>
|
||||
callBaseMethod<Podkop.GetOutboundLinkStates>(
|
||||
Podkop.AvailableMethods.GET_OUTBOUND_LINK_STATES,
|
||||
callBaseMethod<Forkop.GetOutboundLinkStates>(
|
||||
Forkop.AvailableMethods.GET_OUTBOUND_LINK_STATES,
|
||||
[section],
|
||||
),
|
||||
getOutboundMetadata: async (section: string) =>
|
||||
callBaseMethod<Podkop.GetOutboundMetadata>(
|
||||
Podkop.AvailableMethods.GET_OUTBOUND_METADATA,
|
||||
callBaseMethod<Forkop.GetOutboundMetadata>(
|
||||
Forkop.AvailableMethods.GET_OUTBOUND_METADATA,
|
||||
[section],
|
||||
),
|
||||
getSubscriptionMetadata: async (section: string) =>
|
||||
callBaseMethod<Podkop.SubscriptionMetadata | Podkop.SubscriptionMetadata[]>(
|
||||
Podkop.AvailableMethods.GET_SUBSCRIPTION_METADATA,
|
||||
callBaseMethod<Forkop.SubscriptionMetadata | Forkop.SubscriptionMetadata[]>(
|
||||
Forkop.AvailableMethods.GET_SUBSCRIPTION_METADATA,
|
||||
[section],
|
||||
),
|
||||
checkSingBox: async () =>
|
||||
callBaseMethod<Podkop.SingBoxCheckResult>(
|
||||
Podkop.AvailableMethods.CHECK_SING_BOX,
|
||||
callBaseMethod<Forkop.SingBoxCheckResult>(
|
||||
Forkop.AvailableMethods.CHECK_SING_BOX,
|
||||
),
|
||||
checkInbounds: async () =>
|
||||
callBaseMethod<Podkop.InboundsCheckResult>(
|
||||
Podkop.AvailableMethods.CHECK_INBOUNDS,
|
||||
callBaseMethod<Forkop.InboundsCheckResult>(
|
||||
Forkop.AvailableMethods.CHECK_INBOUNDS,
|
||||
),
|
||||
getSingBoxStatus: async () =>
|
||||
callBaseMethod<Podkop.GetSingBoxStatus>(
|
||||
Podkop.AvailableMethods.GET_SING_BOX_STATUS,
|
||||
callBaseMethod<Forkop.GetSingBoxStatus>(
|
||||
Forkop.AvailableMethods.GET_SING_BOX_STATUS,
|
||||
),
|
||||
getZapretStatus: async () =>
|
||||
callBaseMethod<Podkop.GetZapretStatus>(
|
||||
Podkop.AvailableMethods.GET_ZAPRET_STATUS,
|
||||
callBaseMethod<Forkop.GetZapretStatus>(
|
||||
Forkop.AvailableMethods.GET_ZAPRET_STATUS,
|
||||
),
|
||||
getZapret2Status: async () =>
|
||||
callBaseMethod<Podkop.GetZapret2Status>(
|
||||
Podkop.AvailableMethods.GET_ZAPRET2_STATUS,
|
||||
callBaseMethod<Forkop.GetZapret2Status>(
|
||||
Forkop.AvailableMethods.GET_ZAPRET2_STATUS,
|
||||
),
|
||||
getByedpiStatus: async () =>
|
||||
callBaseMethod<Podkop.GetByedpiStatus>(
|
||||
Podkop.AvailableMethods.GET_BYEDPI_STATUS,
|
||||
callBaseMethod<Forkop.GetByedpiStatus>(
|
||||
Forkop.AvailableMethods.GET_BYEDPI_STATUS,
|
||||
),
|
||||
getClashApiProxies: async () =>
|
||||
callBaseMethod<ClashAPI.Proxies>(Podkop.AvailableMethods.CLASH_API, [
|
||||
Podkop.AvailableClashAPIMethods.GET_PROXIES,
|
||||
callBaseMethod<ClashAPI.Proxies>(Forkop.AvailableMethods.CLASH_API, [
|
||||
Forkop.AvailableClashAPIMethods.GET_PROXIES,
|
||||
]),
|
||||
getClashApiConnections: async () =>
|
||||
callBaseMethod<unknown>(Podkop.AvailableMethods.CLASH_API, [
|
||||
Podkop.AvailableClashAPIMethods.GET_CONNECTIONS,
|
||||
callBaseMethod<unknown>(Forkop.AvailableMethods.CLASH_API, [
|
||||
Forkop.AvailableClashAPIMethods.GET_CONNECTIONS,
|
||||
]),
|
||||
getClashApiProxyLatency: async (tag: string, timeout = '5000') =>
|
||||
callBaseMethod<Podkop.GetClashApiProxyLatency>(
|
||||
Podkop.AvailableMethods.CLASH_API,
|
||||
[Podkop.AvailableClashAPIMethods.GET_PROXY_LATENCY, tag, timeout],
|
||||
callBaseMethod<Forkop.GetClashApiProxyLatency>(
|
||||
Forkop.AvailableMethods.CLASH_API,
|
||||
[Forkop.AvailableClashAPIMethods.GET_PROXY_LATENCY, tag, timeout],
|
||||
),
|
||||
getClashApiProxyLatencies: async (tags: string[]) =>
|
||||
callBaseMethod<Podkop.GetClashApiProxyLatencies>(
|
||||
Podkop.AvailableMethods.CLASH_API,
|
||||
callBaseMethod<Forkop.GetClashApiProxyLatencies>(
|
||||
Forkop.AvailableMethods.CLASH_API,
|
||||
[
|
||||
Podkop.AvailableClashAPIMethods.GET_PROXY_LATENCIES,
|
||||
Forkop.AvailableClashAPIMethods.GET_PROXY_LATENCIES,
|
||||
JSON.stringify(tags),
|
||||
'5000',
|
||||
],
|
||||
),
|
||||
getClashApiGroupLatency: async (tag: string) =>
|
||||
callBaseMethod<Podkop.GetClashApiGroupLatency>(
|
||||
Podkop.AvailableMethods.CLASH_API,
|
||||
[Podkop.AvailableClashAPIMethods.GET_GROUP_LATENCY, tag, '10000'],
|
||||
callBaseMethod<Forkop.GetClashApiGroupLatency>(
|
||||
Forkop.AvailableMethods.CLASH_API,
|
||||
[Forkop.AvailableClashAPIMethods.GET_GROUP_LATENCY, tag, '10000'],
|
||||
),
|
||||
setClashApiGroupProxy: async (group: string, proxy: string) =>
|
||||
callBaseMethod<unknown>(Podkop.AvailableMethods.CLASH_API, [
|
||||
Podkop.AvailableClashAPIMethods.SET_GROUP_PROXY,
|
||||
callBaseMethod<unknown>(Forkop.AvailableMethods.CLASH_API, [
|
||||
Forkop.AvailableClashAPIMethods.SET_GROUP_PROXY,
|
||||
group,
|
||||
proxy,
|
||||
]),
|
||||
closeClashApiConnection: async (connectionId: string) =>
|
||||
callBaseMethod<unknown>(Podkop.AvailableMethods.CLASH_API, [
|
||||
Podkop.AvailableClashAPIMethods.CLOSE_CONNECTION,
|
||||
callBaseMethod<unknown>(Forkop.AvailableMethods.CLASH_API, [
|
||||
Forkop.AvailableClashAPIMethods.CLOSE_CONNECTION,
|
||||
connectionId,
|
||||
]),
|
||||
closeAllClashApiConnections: async () =>
|
||||
callBaseMethod<unknown>(Podkop.AvailableMethods.CLASH_API, [
|
||||
Podkop.AvailableClashAPIMethods.CLOSE_ALL_CONNECTIONS,
|
||||
callBaseMethod<unknown>(Forkop.AvailableMethods.CLASH_API, [
|
||||
Forkop.AvailableClashAPIMethods.CLOSE_ALL_CONNECTIONS,
|
||||
]),
|
||||
enable: async () =>
|
||||
callBaseMethod<unknown>(
|
||||
Podkop.AvailableMethods.ENABLE,
|
||||
Forkop.AvailableMethods.ENABLE,
|
||||
[],
|
||||
'/etc/init.d/podkop-plus',
|
||||
'/etc/init.d/forkop',
|
||||
),
|
||||
disable: async () =>
|
||||
callBaseMethod<unknown>(
|
||||
Podkop.AvailableMethods.DISABLE,
|
||||
Forkop.AvailableMethods.DISABLE,
|
||||
[],
|
||||
'/etc/init.d/podkop-plus',
|
||||
'/etc/init.d/forkop',
|
||||
),
|
||||
globalCheck: async (masked = true) =>
|
||||
callBaseMethod<unknown>(Podkop.AvailableMethods.GLOBAL_CHECK, [
|
||||
callBaseMethod<unknown>(Forkop.AvailableMethods.GLOBAL_CHECK, [
|
||||
masked ? 'masked' : 'raw',
|
||||
]),
|
||||
showSingBoxConfig: async (masked = true) =>
|
||||
callBaseMethod<unknown>(Podkop.AvailableMethods.SHOW_SING_BOX_CONFIG, [
|
||||
callBaseMethod<unknown>(Forkop.AvailableMethods.SHOW_SING_BOX_CONFIG, [
|
||||
masked ? 'masked' : 'raw',
|
||||
]),
|
||||
checkLogs: async () =>
|
||||
callBaseMethod<unknown>(Podkop.AvailableMethods.CHECK_LOGS),
|
||||
callBaseMethod<unknown>(Forkop.AvailableMethods.CHECK_LOGS),
|
||||
checkSingBoxLogs: async () =>
|
||||
callBaseMethod<unknown>(Podkop.AvailableMethods.CHECK_SING_BOX_LOGS),
|
||||
callBaseMethod<unknown>(Forkop.AvailableMethods.CHECK_SING_BOX_LOGS),
|
||||
getSystemInfo: async () =>
|
||||
callBaseMethod<Podkop.GetSystemInfo>(
|
||||
Podkop.AvailableMethods.GET_SYSTEM_INFO,
|
||||
callBaseMethod<Forkop.GetSystemInfo>(
|
||||
Forkop.AvailableMethods.GET_SYSTEM_INFO,
|
||||
),
|
||||
getServerCapabilities: async () =>
|
||||
callBaseMethod<Podkop.GetServerCapabilities>(
|
||||
Podkop.AvailableMethods.GET_SERVER_CAPABILITIES,
|
||||
callBaseMethod<Forkop.GetServerCapabilities>(
|
||||
Forkop.AvailableMethods.GET_SERVER_CAPABILITIES,
|
||||
),
|
||||
getUiCapabilities: async () =>
|
||||
callBaseMethod<Podkop.GetUiCapabilities>(
|
||||
Podkop.AvailableMethods.GET_UI_CAPABILITIES,
|
||||
callBaseMethod<Forkop.GetUiCapabilities>(
|
||||
Forkop.AvailableMethods.GET_UI_CAPABILITIES,
|
||||
),
|
||||
getUiState: async () =>
|
||||
callBaseMethod<Podkop.UiState>(
|
||||
Podkop.AvailableMethods.GET_UI_STATE,
|
||||
callBaseMethod<Forkop.UiState>(
|
||||
Forkop.AvailableMethods.GET_UI_STATE,
|
||||
[],
|
||||
'/usr/bin/podkop-plus',
|
||||
'/usr/bin/forkop',
|
||||
{ timeout: GET_UI_STATE_RPC_TIMEOUT_MS },
|
||||
),
|
||||
serviceActionStart: async (action: Podkop.ServiceAction) => {
|
||||
serviceActionStart: async (action: Forkop.ServiceAction) => {
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/podkop-plus',
|
||||
args: [Podkop.AvailableMethods.SERVICE_ACTION_ASYNC, action],
|
||||
command: '/usr/bin/forkop',
|
||||
args: [Forkop.AvailableMethods.SERVICE_ACTION_ASYNC, action],
|
||||
timeout: UI_ACTION_RPC_TIMEOUT_MS,
|
||||
});
|
||||
const parsedResponse = parseUiActionStartResult(response);
|
||||
@@ -387,12 +387,12 @@ export const PodkopShellMethods = {
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Podkop.MethodSuccessResponse<Podkop.UiActionStartResult>;
|
||||
} as Forkop.MethodSuccessResponse<Forkop.UiActionStartResult>;
|
||||
},
|
||||
serviceActionStatus: async (jobId: string) => {
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/podkop-plus',
|
||||
args: [Podkop.AvailableMethods.SERVICE_ACTION_STATUS, jobId],
|
||||
command: '/usr/bin/forkop',
|
||||
args: [Forkop.AvailableMethods.SERVICE_ACTION_STATUS, jobId],
|
||||
timeout: UI_ACTION_RPC_TIMEOUT_MS,
|
||||
});
|
||||
const parsedResponse = parseServiceActionState(response);
|
||||
@@ -408,13 +408,13 @@ export const PodkopShellMethods = {
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Podkop.MethodSuccessResponse<Podkop.ServiceActionState>;
|
||||
} as Forkop.MethodSuccessResponse<Forkop.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 PodkopShellMethods.serviceActionStatus(jobId);
|
||||
const response = await ForkopShellMethods.serviceActionStatus(jobId);
|
||||
|
||||
if (!response.success) {
|
||||
return response;
|
||||
@@ -430,18 +430,18 @@ export const PodkopShellMethods = {
|
||||
return {
|
||||
success: false,
|
||||
error: _('Operation timed out'),
|
||||
} as Podkop.MethodFailureResponse;
|
||||
} as Forkop.MethodFailureResponse;
|
||||
},
|
||||
latencyTestStart: async (
|
||||
latencyType: Podkop.LatencyActionState['latency_type'],
|
||||
latencyType: Forkop.LatencyActionState['latency_type'],
|
||||
section: string,
|
||||
tag: string,
|
||||
timeout?: string,
|
||||
) => {
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/podkop-plus',
|
||||
command: '/usr/bin/forkop',
|
||||
args: [
|
||||
Podkop.AvailableMethods.LATENCY_TEST_ASYNC,
|
||||
Forkop.AvailableMethods.LATENCY_TEST_ASYNC,
|
||||
latencyType,
|
||||
section,
|
||||
tag,
|
||||
@@ -466,12 +466,12 @@ export const PodkopShellMethods = {
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Podkop.MethodSuccessResponse<Podkop.UiActionStartResult>;
|
||||
} as Forkop.MethodSuccessResponse<Forkop.UiActionStartResult>;
|
||||
},
|
||||
latencyTestStatus: async (jobId: string) => {
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/podkop-plus',
|
||||
args: [Podkop.AvailableMethods.LATENCY_TEST_STATUS, jobId],
|
||||
command: '/usr/bin/forkop',
|
||||
args: [Forkop.AvailableMethods.LATENCY_TEST_STATUS, jobId],
|
||||
timeout: UI_ACTION_RPC_TIMEOUT_MS,
|
||||
});
|
||||
const parsedResponse = parseLatencyActionState(response);
|
||||
@@ -487,7 +487,7 @@ export const PodkopShellMethods = {
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Podkop.MethodSuccessResponse<Podkop.LatencyActionState>;
|
||||
} as Forkop.MethodSuccessResponse<Forkop.LatencyActionState>;
|
||||
},
|
||||
waitLatencyTestJob: async (jobId: string, startedAt = Date.now()) => {
|
||||
const transientRpc = createTransientRpcGraceTracker(
|
||||
@@ -497,7 +497,7 @@ export const PodkopShellMethods = {
|
||||
while (Date.now() - startedAt < LATENCY_TEST_TIMEOUT_MS) {
|
||||
await sleep(LATENCY_TEST_POLL_INTERVAL_MS);
|
||||
|
||||
const response = await PodkopShellMethods.latencyTestStatus(jobId);
|
||||
const response = await ForkopShellMethods.latencyTestStatus(jobId);
|
||||
|
||||
if (!response.success) {
|
||||
if (transientRpc.shouldContinue(response.error)) {
|
||||
@@ -518,15 +518,15 @@ export const PodkopShellMethods = {
|
||||
return {
|
||||
success: false,
|
||||
error: _('Operation timed out'),
|
||||
} as Podkop.MethodFailureResponse;
|
||||
} as Forkop.MethodFailureResponse;
|
||||
},
|
||||
uiActionAck: async (
|
||||
kind: 'service' | 'latency' | 'component' | 'subscription',
|
||||
jobId: string,
|
||||
) => {
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/podkop-plus',
|
||||
args: [Podkop.AvailableMethods.UI_ACTION_ACK, kind, jobId],
|
||||
command: '/usr/bin/forkop',
|
||||
args: [Forkop.AvailableMethods.UI_ACTION_ACK, kind, jobId],
|
||||
timeout: UI_ACTION_RPC_TIMEOUT_MS,
|
||||
});
|
||||
const parsedResponse = parseUiActionStartResult(response);
|
||||
@@ -538,15 +538,15 @@ export const PodkopShellMethods = {
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Podkop.MethodSuccessResponse<Podkop.UiActionStartResult>;
|
||||
} as Forkop.MethodSuccessResponse<Forkop.UiActionStartResult>;
|
||||
},
|
||||
componentActionStart: async (
|
||||
component: Podkop.ComponentName,
|
||||
action: Podkop.ComponentAction,
|
||||
component: Forkop.ComponentName,
|
||||
action: Forkop.ComponentAction,
|
||||
) => {
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/podkop-plus',
|
||||
args: [Podkop.AvailableMethods.COMPONENT_ACTION_ASYNC, component, action],
|
||||
command: '/usr/bin/forkop',
|
||||
args: [Forkop.AvailableMethods.COMPONENT_ACTION_ASYNC, component, action],
|
||||
timeout: COMPONENT_ACTION_RPC_TIMEOUT_MS,
|
||||
});
|
||||
const parsedResponse = parseComponentActionStartResult(response);
|
||||
@@ -562,12 +562,12 @@ export const PodkopShellMethods = {
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Podkop.MethodSuccessResponse<Podkop.ComponentActionStartResult>;
|
||||
} as Forkop.MethodSuccessResponse<Forkop.ComponentActionStartResult>;
|
||||
},
|
||||
componentActionStatus: async (jobId: string) => {
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/podkop-plus',
|
||||
args: [Podkop.AvailableMethods.COMPONENT_ACTION_STATUS, jobId],
|
||||
command: '/usr/bin/forkop',
|
||||
args: [Forkop.AvailableMethods.COMPONENT_ACTION_STATUS, jobId],
|
||||
timeout: COMPONENT_ACTION_RPC_TIMEOUT_MS,
|
||||
});
|
||||
const parsedResponse = parseComponentActionResult(response);
|
||||
@@ -579,16 +579,16 @@ export const PodkopShellMethods = {
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Podkop.MethodSuccessResponse<Podkop.ComponentActionResult>;
|
||||
} as Forkop.MethodSuccessResponse<Forkop.ComponentActionResult>;
|
||||
},
|
||||
componentUpdateCheckCache: async () =>
|
||||
callBaseMethod<Podkop.ComponentUpdateCheckCache>(
|
||||
Podkop.AvailableMethods.COMPONENT_UPDATE_CHECK_CACHE,
|
||||
callBaseMethod<Forkop.ComponentUpdateCheckCache>(
|
||||
Forkop.AvailableMethods.COMPONENT_UPDATE_CHECK_CACHE,
|
||||
),
|
||||
waitComponentActionJob: async (
|
||||
jobId: string,
|
||||
component: Podkop.ComponentName,
|
||||
action: Podkop.ComponentAction,
|
||||
component: Forkop.ComponentName,
|
||||
action: Forkop.ComponentAction,
|
||||
expectedLatestVersion?: string,
|
||||
) => {
|
||||
let selfUpdateVersionMatchedAt = 0;
|
||||
@@ -608,7 +608,7 @@ export const PodkopShellMethods = {
|
||||
return {
|
||||
success: true,
|
||||
data: stateResponse,
|
||||
} as Podkop.MethodSuccessResponse<Podkop.ComponentActionResult>;
|
||||
} as Forkop.MethodSuccessResponse<Forkop.ComponentActionResult>;
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -621,8 +621,8 @@ export const PodkopShellMethods = {
|
||||
|
||||
lastStatusRefreshAt = Date.now();
|
||||
const statusResponse = await executeShellCommand({
|
||||
command: '/usr/bin/podkop-plus',
|
||||
args: [Podkop.AvailableMethods.COMPONENT_ACTION_STATUS, jobId],
|
||||
command: '/usr/bin/forkop',
|
||||
args: [Forkop.AvailableMethods.COMPONENT_ACTION_STATUS, jobId],
|
||||
timeout: COMPONENT_ACTION_RPC_TIMEOUT_MS,
|
||||
});
|
||||
const parsedResponse = parseComponentActionResult(statusResponse);
|
||||
@@ -644,9 +644,9 @@ export const PodkopShellMethods = {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (component === 'podkop' && action === 'install') {
|
||||
if (component === 'forkop' && action === 'install') {
|
||||
const installedVersion = expectedLatestVersion
|
||||
? await readPodkopVersion()
|
||||
? await readForkopVersion()
|
||||
: '';
|
||||
|
||||
if (
|
||||
@@ -667,13 +667,13 @@ export const PodkopShellMethods = {
|
||||
success: true,
|
||||
component,
|
||||
action,
|
||||
message: translate('Podkop Plus has been installed'),
|
||||
message: translate('Forkop has been installed'),
|
||||
current_version: installedVersion,
|
||||
latest_version: expectedLatestVersion,
|
||||
changed: true,
|
||||
status: 'latest',
|
||||
},
|
||||
} as Podkop.MethodSuccessResponse<Podkop.ComponentActionResult>;
|
||||
} as Forkop.MethodSuccessResponse<Forkop.ComponentActionResult>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -691,17 +691,17 @@ export const PodkopShellMethods = {
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Podkop.MethodSuccessResponse<Podkop.ComponentActionResult>;
|
||||
} as Forkop.MethodSuccessResponse<Forkop.ComponentActionResult>;
|
||||
}
|
||||
},
|
||||
subscriptionUpdateStart: async (section?: string, sourceIndex?: number) => {
|
||||
const startArgs = [
|
||||
Podkop.AvailableMethods.SUBSCRIPTION_UPDATE_ASYNC,
|
||||
Forkop.AvailableMethods.SUBSCRIPTION_UPDATE_ASYNC,
|
||||
...(section ? [section] : []),
|
||||
...(section && sourceIndex !== undefined ? [String(sourceIndex)] : []),
|
||||
];
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/podkop-plus',
|
||||
command: '/usr/bin/forkop',
|
||||
args: startArgs,
|
||||
timeout: SUBSCRIPTION_UPDATE_RPC_TIMEOUT_MS,
|
||||
});
|
||||
@@ -718,18 +718,18 @@ export const PodkopShellMethods = {
|
||||
parsedResponse?.message ||
|
||||
response.stderr ||
|
||||
_('Subscription update failed'),
|
||||
} as Podkop.MethodFailureResponse;
|
||||
} as Forkop.MethodFailureResponse;
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Podkop.MethodSuccessResponse<Podkop.SubscriptionUpdateStartResult>;
|
||||
} as Forkop.MethodSuccessResponse<Forkop.SubscriptionUpdateStartResult>;
|
||||
},
|
||||
subscriptionUpdateStatus: async (jobId: string) => {
|
||||
const response = await executeShellCommand({
|
||||
command: '/usr/bin/podkop-plus',
|
||||
args: [Podkop.AvailableMethods.SUBSCRIPTION_UPDATE_STATUS, jobId],
|
||||
command: '/usr/bin/forkop',
|
||||
args: [Forkop.AvailableMethods.SUBSCRIPTION_UPDATE_STATUS, jobId],
|
||||
timeout: SUBSCRIPTION_UPDATE_RPC_TIMEOUT_MS,
|
||||
});
|
||||
const parsedResponse = parseSubscriptionUpdateJobState(response);
|
||||
@@ -738,13 +738,13 @@ export const PodkopShellMethods = {
|
||||
return {
|
||||
success: false,
|
||||
error: response.stderr || _('Subscription update failed'),
|
||||
} as Podkop.MethodFailureResponse;
|
||||
} as Forkop.MethodFailureResponse;
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: parsedResponse,
|
||||
} as Podkop.MethodSuccessResponse<Podkop.SubscriptionUpdateJobState>;
|
||||
} as Forkop.MethodSuccessResponse<Forkop.SubscriptionUpdateJobState>;
|
||||
},
|
||||
waitSubscriptionUpdateJob: async (jobId: string) => {
|
||||
const transientRpc = createTransientRpcGraceTracker(
|
||||
@@ -754,7 +754,7 @@ export const PodkopShellMethods = {
|
||||
while (true) {
|
||||
await sleep(SUBSCRIPTION_UPDATE_POLL_INTERVAL_MS);
|
||||
|
||||
const response = await PodkopShellMethods.subscriptionUpdateStatus(jobId);
|
||||
const response = await ForkopShellMethods.subscriptionUpdateStatus(jobId);
|
||||
|
||||
if (!response.success) {
|
||||
if (transientRpc.shouldContinue(response.error)) {
|
||||
+7
-7
@@ -8,7 +8,7 @@ vi.mock('../../../../helpers', () => ({
|
||||
executeShellCommand: mocks.executeShellCommand,
|
||||
}));
|
||||
|
||||
import { Podkop } from '../../../types';
|
||||
import { Forkop } from '../../../types';
|
||||
import { callBaseMethod } from '../callBaseMethod';
|
||||
|
||||
describe('callBaseMethod', () => {
|
||||
@@ -24,7 +24,7 @@ describe('callBaseMethod', () => {
|
||||
});
|
||||
|
||||
const response = await callBaseMethod(
|
||||
Podkop.AvailableMethods.CHECK_DNS_AVAILABLE,
|
||||
Forkop.AvailableMethods.CHECK_DNS_AVAILABLE,
|
||||
);
|
||||
|
||||
expect(response).toEqual({
|
||||
@@ -41,9 +41,9 @@ describe('callBaseMethod', () => {
|
||||
});
|
||||
|
||||
const response = await callBaseMethod(
|
||||
Podkop.AvailableMethods.GLOBAL_CHECK,
|
||||
Forkop.AvailableMethods.GLOBAL_CHECK,
|
||||
[],
|
||||
'/usr/bin/podkop-plus',
|
||||
'/usr/bin/forkop',
|
||||
{ allowNonZeroWithStdout: true },
|
||||
);
|
||||
|
||||
@@ -61,14 +61,14 @@ describe('callBaseMethod', () => {
|
||||
});
|
||||
|
||||
await callBaseMethod(
|
||||
Podkop.AvailableMethods.GLOBAL_CHECK,
|
||||
Forkop.AvailableMethods.GLOBAL_CHECK,
|
||||
[],
|
||||
'/usr/bin/podkop-plus',
|
||||
'/usr/bin/forkop',
|
||||
{ timeout: 60000 },
|
||||
);
|
||||
|
||||
expect(mocks.executeShellCommand).toHaveBeenCalledWith({
|
||||
command: '/usr/bin/podkop-plus',
|
||||
command: '/usr/bin/forkop',
|
||||
args: ['global_check'],
|
||||
timeout: 60000,
|
||||
});
|
||||
+13
-13
@@ -9,9 +9,9 @@ vi.mock('../../../../helpers', () => ({
|
||||
executeShellCommand: mocks.executeShellCommand,
|
||||
}));
|
||||
|
||||
import { PodkopShellMethods } from '../index';
|
||||
import { ForkopShellMethods } from '../index';
|
||||
|
||||
describe('PodkopShellMethods.componentAction', () => {
|
||||
describe('ForkopShellMethods.componentAction', () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
mocks.executeShellCommand.mockReset();
|
||||
@@ -26,7 +26,7 @@ describe('PodkopShellMethods.componentAction', () => {
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it('does not fail Podkop Plus self-update when status polling disappears after package replacement', async () => {
|
||||
it('does not fail Forkop 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('PodkopShellMethods.componentAction', () => {
|
||||
});
|
||||
});
|
||||
|
||||
const responsePromise = PodkopShellMethods.waitComponentActionJob(
|
||||
const responsePromise = ForkopShellMethods.waitComponentActionJob(
|
||||
'job-1',
|
||||
'podkop',
|
||||
'forkop',
|
||||
'install',
|
||||
'0.7.17.11',
|
||||
);
|
||||
@@ -65,9 +65,9 @@ describe('PodkopShellMethods.componentAction', () => {
|
||||
success: true,
|
||||
data: {
|
||||
success: true,
|
||||
component: 'podkop',
|
||||
component: 'forkop',
|
||||
action: 'install',
|
||||
message: 'Podkop Plus has been installed',
|
||||
message: 'Forkop has been installed',
|
||||
current_version: '0.7.17.11',
|
||||
latest_version: '0.7.17.11',
|
||||
changed: true,
|
||||
@@ -87,7 +87,7 @@ describe('PodkopShellMethods.componentAction', () => {
|
||||
});
|
||||
|
||||
await expect(
|
||||
PodkopShellMethods.componentActionStart('zapret', 'install'),
|
||||
ForkopShellMethods.componentActionStart('zapret', 'install'),
|
||||
).resolves.toEqual({
|
||||
success: false,
|
||||
error: 'Another component action is already running',
|
||||
@@ -147,7 +147,7 @@ describe('PodkopShellMethods.componentAction', () => {
|
||||
});
|
||||
});
|
||||
|
||||
const responsePromise = PodkopShellMethods.waitComponentActionJob(
|
||||
const responsePromise = ForkopShellMethods.waitComponentActionJob(
|
||||
'job-1',
|
||||
'sing_box',
|
||||
'check_update',
|
||||
@@ -201,7 +201,7 @@ describe('PodkopShellMethods.componentAction', () => {
|
||||
return Promise.resolve({
|
||||
stdout: JSON.stringify({
|
||||
service: {
|
||||
podkop: {
|
||||
forkop: {
|
||||
running: 0,
|
||||
enabled: 1,
|
||||
status: 'stopped but enabled',
|
||||
@@ -251,7 +251,7 @@ describe('PodkopShellMethods.componentAction', () => {
|
||||
});
|
||||
});
|
||||
|
||||
const responsePromise = PodkopShellMethods.waitComponentActionJob(
|
||||
const responsePromise = ForkopShellMethods.waitComponentActionJob(
|
||||
'job-1',
|
||||
'sing_box',
|
||||
'install_extended',
|
||||
@@ -274,7 +274,7 @@ describe('PodkopShellMethods.componentAction', () => {
|
||||
},
|
||||
});
|
||||
expect(mocks.executeShellCommand).toHaveBeenCalledWith({
|
||||
command: '/usr/bin/podkop-plus',
|
||||
command: '/usr/bin/forkop',
|
||||
args: ['get_ui_state'],
|
||||
timeout: 3000,
|
||||
});
|
||||
@@ -321,7 +321,7 @@ describe('PodkopShellMethods.componentAction', () => {
|
||||
});
|
||||
});
|
||||
|
||||
const responsePromise = PodkopShellMethods.waitComponentActionJob(
|
||||
const responsePromise = ForkopShellMethods.waitComponentActionJob(
|
||||
'job-1',
|
||||
'zapret',
|
||||
'check_update',
|
||||
+5
-5
@@ -8,9 +8,9 @@ vi.mock('../../../../helpers', () => ({
|
||||
executeShellCommand: mocks.executeShellCommand,
|
||||
}));
|
||||
|
||||
import { PodkopShellMethods } from '../index';
|
||||
import { ForkopShellMethods } from '../index';
|
||||
|
||||
describe('PodkopShellMethods.latencyAction', () => {
|
||||
describe('ForkopShellMethods.latencyAction', () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
mocks.executeShellCommand.mockReset();
|
||||
@@ -52,7 +52,7 @@ describe('PodkopShellMethods.latencyAction', () => {
|
||||
});
|
||||
});
|
||||
|
||||
const responsePromise = PodkopShellMethods.waitLatencyTestJob('job-1');
|
||||
const responsePromise = ForkopShellMethods.waitLatencyTestJob('job-1');
|
||||
|
||||
await vi.advanceTimersByTimeAsync(2000);
|
||||
|
||||
@@ -76,7 +76,7 @@ describe('PodkopShellMethods.latencyAction', () => {
|
||||
code: 0,
|
||||
});
|
||||
|
||||
await PodkopShellMethods.latencyTestStart(
|
||||
await ForkopShellMethods.latencyTestStart(
|
||||
'proxy',
|
||||
'AWG',
|
||||
'AWG-out',
|
||||
@@ -84,7 +84,7 @@ describe('PodkopShellMethods.latencyAction', () => {
|
||||
);
|
||||
|
||||
expect(mocks.executeShellCommand).toHaveBeenCalledWith({
|
||||
command: '/usr/bin/podkop-plus',
|
||||
command: '/usr/bin/forkop',
|
||||
args: ['latency_test_async', 'proxy', 'AWG', 'AWG-out', '10000'],
|
||||
timeout: 15000,
|
||||
});
|
||||
+4
-4
@@ -8,9 +8,9 @@ vi.mock('../../../../helpers', () => ({
|
||||
executeShellCommand: mocks.executeShellCommand,
|
||||
}));
|
||||
|
||||
import { PodkopShellMethods } from '../index';
|
||||
import { ForkopShellMethods } from '../index';
|
||||
|
||||
describe('PodkopShellMethods.serviceAction', () => {
|
||||
describe('ForkopShellMethods.serviceAction', () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
mocks.executeShellCommand.mockReset();
|
||||
@@ -44,7 +44,7 @@ describe('PodkopShellMethods.serviceAction', () => {
|
||||
});
|
||||
});
|
||||
|
||||
const responsePromise = PodkopShellMethods.waitServiceActionJob('job-1');
|
||||
const responsePromise = ForkopShellMethods.waitServiceActionJob('job-1');
|
||||
|
||||
await vi.advanceTimersByTimeAsync(1000);
|
||||
|
||||
@@ -72,7 +72,7 @@ describe('PodkopShellMethods.serviceAction', () => {
|
||||
});
|
||||
|
||||
await expect(
|
||||
PodkopShellMethods.serviceActionStart('restart'),
|
||||
ForkopShellMethods.serviceActionStart('restart'),
|
||||
).resolves.toEqual({
|
||||
success: false,
|
||||
error: 'Another service action is already running',
|
||||
+10
-10
@@ -8,9 +8,9 @@ vi.mock('../../../../helpers', () => ({
|
||||
executeShellCommand: mocks.executeShellCommand,
|
||||
}));
|
||||
|
||||
import { PodkopShellMethods } from '../index';
|
||||
import { ForkopShellMethods } from '../index';
|
||||
|
||||
describe('PodkopShellMethods.subscriptionUpdate', () => {
|
||||
describe('ForkopShellMethods.subscriptionUpdate', () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
mocks.executeShellCommand.mockReset();
|
||||
@@ -55,7 +55,7 @@ describe('PodkopShellMethods.subscriptionUpdate', () => {
|
||||
});
|
||||
|
||||
await expect(
|
||||
PodkopShellMethods.subscriptionUpdateStart('main'),
|
||||
ForkopShellMethods.subscriptionUpdateStart('main'),
|
||||
).resolves.toEqual({
|
||||
success: true,
|
||||
data: {
|
||||
@@ -66,7 +66,7 @@ describe('PodkopShellMethods.subscriptionUpdate', () => {
|
||||
});
|
||||
|
||||
const responsePromise =
|
||||
PodkopShellMethods.waitSubscriptionUpdateJob('job-1');
|
||||
ForkopShellMethods.waitSubscriptionUpdateJob('job-1');
|
||||
|
||||
await vi.advanceTimersByTimeAsync(1500);
|
||||
|
||||
@@ -80,12 +80,12 @@ describe('PodkopShellMethods.subscriptionUpdate', () => {
|
||||
},
|
||||
});
|
||||
expect(mocks.executeShellCommand).toHaveBeenNthCalledWith(1, {
|
||||
command: '/usr/bin/podkop-plus',
|
||||
command: '/usr/bin/forkop',
|
||||
args: ['subscription_update_async', 'main'],
|
||||
timeout: 15000,
|
||||
});
|
||||
expect(mocks.executeShellCommand).toHaveBeenNthCalledWith(2, {
|
||||
command: '/usr/bin/podkop-plus',
|
||||
command: '/usr/bin/forkop',
|
||||
args: ['subscription_update_status', 'job-1'],
|
||||
timeout: 15000,
|
||||
});
|
||||
@@ -102,7 +102,7 @@ describe('PodkopShellMethods.subscriptionUpdate', () => {
|
||||
});
|
||||
|
||||
await expect(
|
||||
PodkopShellMethods.subscriptionUpdateStart('main'),
|
||||
ForkopShellMethods.subscriptionUpdateStart('main'),
|
||||
).resolves.toEqual({
|
||||
success: false,
|
||||
error: 'Subscription update is already running',
|
||||
@@ -134,7 +134,7 @@ describe('PodkopShellMethods.subscriptionUpdate', () => {
|
||||
});
|
||||
|
||||
const responsePromise =
|
||||
PodkopShellMethods.waitSubscriptionUpdateJob('job-1');
|
||||
ForkopShellMethods.waitSubscriptionUpdateJob('job-1');
|
||||
|
||||
await vi.advanceTimersByTimeAsync(1500);
|
||||
|
||||
@@ -189,7 +189,7 @@ describe('PodkopShellMethods.subscriptionUpdate', () => {
|
||||
});
|
||||
|
||||
const responsePromise =
|
||||
PodkopShellMethods.waitSubscriptionUpdateJob('job-1');
|
||||
ForkopShellMethods.waitSubscriptionUpdateJob('job-1');
|
||||
|
||||
await vi.advanceTimersByTimeAsync(10 * 60 * 1000 + 3000);
|
||||
|
||||
@@ -239,7 +239,7 @@ describe('PodkopShellMethods.subscriptionUpdate', () => {
|
||||
});
|
||||
|
||||
const responsePromise =
|
||||
PodkopShellMethods.waitSubscriptionUpdateJob('job-1');
|
||||
ForkopShellMethods.waitSubscriptionUpdateJob('job-1');
|
||||
|
||||
await vi.advanceTimersByTimeAsync(3000);
|
||||
|
||||
+12
-12
@@ -1,13 +1,13 @@
|
||||
import { TabServiceInstance } from './tab.service';
|
||||
import { store } from './store.service';
|
||||
import { logger } from './logger.service';
|
||||
import { PodkopLogWatcher } from './podkopLogWatcher.service';
|
||||
import { ForkopLogWatcher } from './forkopLogWatcher.service';
|
||||
import {
|
||||
getPodkopLogNotification,
|
||||
getForkopLogNotification,
|
||||
LogNotificationDeduper,
|
||||
PodkopLogNotification,
|
||||
ForkopLogNotification,
|
||||
} from './logNotificationDeduper.service';
|
||||
import { PodkopShellMethods } from '../methods';
|
||||
import { ForkopShellMethods } 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> = {
|
||||
podkop: 'Podkop Plus',
|
||||
forkop: 'Forkop',
|
||||
sing_box: 'sing-box',
|
||||
zapret: 'Zapret',
|
||||
zapret2: 'Zapret2',
|
||||
@@ -33,7 +33,7 @@ function componentDisplayName(component: string) {
|
||||
return names[component] || component;
|
||||
}
|
||||
|
||||
function showLogNotification(notification: PodkopLogNotification) {
|
||||
function showLogNotification(notification: ForkopLogNotification) {
|
||||
if (notification.kind === 'component-update') {
|
||||
const message = _('New version %s is available for %s')
|
||||
.replace('%s', notification.version)
|
||||
@@ -43,16 +43,16 @@ function showLogNotification(notification: PodkopLogNotification) {
|
||||
_('Component update available'),
|
||||
E('div', {}, message),
|
||||
'warning',
|
||||
'pdk-component-update-notification',
|
||||
'fkp-component-update-notification',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
ui.addNotification(
|
||||
_('Podkop Plus Error'),
|
||||
_('Forkop Error'),
|
||||
E('div', {}, notification.line),
|
||||
'error',
|
||||
'pdk-log-error-notification',
|
||||
'fkp-log-error-notification',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -67,12 +67,12 @@ export function coreService(options: CoreServiceOptions = {}) {
|
||||
});
|
||||
});
|
||||
|
||||
const watcher = PodkopLogWatcher.getInstance();
|
||||
const watcher = ForkopLogWatcher.getInstance();
|
||||
const logNotificationDeduper = new LogNotificationDeduper();
|
||||
|
||||
watcher.init(
|
||||
async () => {
|
||||
const logs = await PodkopShellMethods.checkLogs();
|
||||
const logs = await ForkopShellMethods.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 = getPodkopLogNotification(line);
|
||||
const notification = getForkopLogNotification(line);
|
||||
if (notification) {
|
||||
showLogNotification(notification);
|
||||
}
|
||||
+19
-19
@@ -2,14 +2,14 @@ import { logger } from './logger.service';
|
||||
|
||||
type LogFetcher = () => Promise<string> | string;
|
||||
|
||||
interface PodkopLogWatcherOptions {
|
||||
interface ForkopLogWatcherOptions {
|
||||
intervalMs?: number;
|
||||
onNewLog?: (line: string) => void;
|
||||
maxTrackedLines?: number;
|
||||
}
|
||||
|
||||
export class PodkopLogWatcher {
|
||||
private static instance: PodkopLogWatcher;
|
||||
export class ForkopLogWatcher {
|
||||
private static instance: ForkopLogWatcher;
|
||||
private fetcher?: LogFetcher;
|
||||
private onNewLog?: (line: string) => void;
|
||||
private intervalMs = 5000;
|
||||
@@ -29,21 +29,21 @@ export class PodkopLogWatcher {
|
||||
}
|
||||
}
|
||||
|
||||
static getInstance(): PodkopLogWatcher {
|
||||
if (!PodkopLogWatcher.instance) {
|
||||
PodkopLogWatcher.instance = new PodkopLogWatcher();
|
||||
static getInstance(): ForkopLogWatcher {
|
||||
if (!ForkopLogWatcher.instance) {
|
||||
ForkopLogWatcher.instance = new ForkopLogWatcher();
|
||||
}
|
||||
return PodkopLogWatcher.instance;
|
||||
return ForkopLogWatcher.instance;
|
||||
}
|
||||
|
||||
init(fetcher: LogFetcher, options?: PodkopLogWatcherOptions): void {
|
||||
init(fetcher: LogFetcher, options?: ForkopLogWatcherOptions): void {
|
||||
this.fetcher = fetcher;
|
||||
this.onNewLog = options?.onNewLog;
|
||||
this.intervalMs = options?.intervalMs ?? 5000;
|
||||
this.maxTrackedLines = options?.maxTrackedLines ?? 500;
|
||||
this.lastLines = new Set();
|
||||
logger.info(
|
||||
'[PodkopLogWatcher]',
|
||||
'[ForkopLogWatcher]',
|
||||
`initialized (interval: ${this.intervalMs}ms)`,
|
||||
);
|
||||
}
|
||||
@@ -54,18 +54,18 @@ export class PodkopLogWatcher {
|
||||
|
||||
async checkOnce(): Promise<void> {
|
||||
if (!this.fetcher) {
|
||||
logger.warn('[PodkopLogWatcher]', 'fetcher not found');
|
||||
logger.warn('[ForkopLogWatcher]', 'fetcher not found');
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.paused) {
|
||||
logger.debug('[PodkopLogWatcher]', 'skipped check — tab not visible');
|
||||
logger.debug('[ForkopLogWatcher]', 'skipped check — tab not visible');
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.checking) {
|
||||
logger.debug(
|
||||
'[PodkopLogWatcher]',
|
||||
'[ForkopLogWatcher]',
|
||||
'skipped check — previous check is running',
|
||||
);
|
||||
return;
|
||||
@@ -92,7 +92,7 @@ export class PodkopLogWatcher {
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error('[PodkopLogWatcher]', 'failed to read logs:', err);
|
||||
logger.error('[ForkopLogWatcher]', 'failed to read logs:', err);
|
||||
} finally {
|
||||
this.checking = false;
|
||||
}
|
||||
@@ -101,7 +101,7 @@ export class PodkopLogWatcher {
|
||||
start(): void {
|
||||
if (this.running) return;
|
||||
if (!this.fetcher) {
|
||||
logger.warn('[PodkopLogWatcher]', 'attempted to start without fetcher');
|
||||
logger.warn('[ForkopLogWatcher]', 'attempted to start without fetcher');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ export class PodkopLogWatcher {
|
||||
void this.checkOnce();
|
||||
this.timer = setInterval(() => this.checkOnce(), this.intervalMs);
|
||||
logger.info(
|
||||
'[PodkopLogWatcher]',
|
||||
'[ForkopLogWatcher]',
|
||||
`started (interval: ${this.intervalMs}ms)`,
|
||||
);
|
||||
}
|
||||
@@ -118,25 +118,25 @@ export class PodkopLogWatcher {
|
||||
if (!this.running) return;
|
||||
this.running = false;
|
||||
if (this.timer) clearInterval(this.timer);
|
||||
logger.info('[PodkopLogWatcher]', 'stopped');
|
||||
logger.info('[ForkopLogWatcher]', 'stopped');
|
||||
}
|
||||
|
||||
pause(): void {
|
||||
if (!this.running || this.paused) return;
|
||||
this.paused = true;
|
||||
logger.info('[PodkopLogWatcher]', 'paused (tab not visible)');
|
||||
logger.info('[ForkopLogWatcher]', 'paused (tab not visible)');
|
||||
}
|
||||
|
||||
resume(): void {
|
||||
if (!this.running || !this.paused) return;
|
||||
this.paused = false;
|
||||
logger.info('[PodkopLogWatcher]', 'resumed (tab active)');
|
||||
logger.info('[ForkopLogWatcher]', 'resumed (tab active)');
|
||||
void this.checkOnce();
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
this.lastLines = new Set();
|
||||
this.checking = false;
|
||||
logger.info('[PodkopLogWatcher]', 'log history reset');
|
||||
logger.info('[ForkopLogWatcher]', 'log history reset');
|
||||
}
|
||||
}
|
||||
+6
-7
@@ -1,8 +1,7 @@
|
||||
const LOG_NOTIFICATION_STORAGE_KEY =
|
||||
'podkop-plus:shown-log-error-notifications:v1';
|
||||
const LOG_NOTIFICATION_STORAGE_KEY = 'forkop:shown-log-error-notifications:v1';
|
||||
const MAX_STORED_LOG_NOTIFICATIONS = 500;
|
||||
|
||||
export type PodkopLogNotification =
|
||||
export type ForkopLogNotification =
|
||||
| { kind: 'error'; line: string }
|
||||
| {
|
||||
kind: 'component-update';
|
||||
@@ -61,15 +60,15 @@ export function isErrorLogLine(line: string) {
|
||||
return lower.includes('[error]') || lower.includes('[fatal]');
|
||||
}
|
||||
|
||||
export function getPodkopLogNotification(
|
||||
export function getForkopLogNotification(
|
||||
line: string,
|
||||
): PodkopLogNotification | null {
|
||||
): ForkopLogNotification | null {
|
||||
if (isErrorLogLine(line)) {
|
||||
return { kind: 'error', line };
|
||||
}
|
||||
|
||||
const update = line.match(
|
||||
/\[component-update\]\s+(podkop|sing_box|zapret|zapret2|byedpi)\s+(\S+)/i,
|
||||
/\[component-update\]\s+(forkop|sing_box|zapret|zapret2|byedpi)\s+(\S+)/i,
|
||||
);
|
||||
|
||||
if (!update) {
|
||||
@@ -98,7 +97,7 @@ export class LogNotificationDeduper {
|
||||
}
|
||||
|
||||
shouldNotify(line: string) {
|
||||
if (!getPodkopLogNotification(line)) {
|
||||
if (!getForkopLogNotification(line)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+9
-9
@@ -1,17 +1,17 @@
|
||||
import { PodkopShellMethods } from '../methods';
|
||||
import { Podkop } from '../types';
|
||||
import { ForkopShellMethods } from '../methods';
|
||||
import { Forkop } 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: Podkop.UiState) => void;
|
||||
type RuntimeUiStateListener = (uiState: Forkop.UiState) => void;
|
||||
|
||||
let runtimeUiStateRefreshPromise: Promise<Podkop.UiState | undefined> | null =
|
||||
let runtimeUiStateRefreshPromise: Promise<Forkop.UiState | undefined> | null =
|
||||
null;
|
||||
let lastRuntimeUiStateRefreshAt = 0;
|
||||
let lastRuntimeUiState: Podkop.UiState | undefined;
|
||||
let lastRuntimeUiState: Forkop.UiState | undefined;
|
||||
let runtimeStateResumeRefreshRegistered = false;
|
||||
let runtimeStatePollTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
let runtimeStatePollingStarted = false;
|
||||
@@ -26,7 +26,7 @@ function isDocumentVisible() {
|
||||
);
|
||||
}
|
||||
|
||||
function hasRunningAction(uiState: Podkop.UiState) {
|
||||
function hasRunningAction(uiState: Forkop.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: Podkop.UiState) {
|
||||
function notifyRuntimeUiStateListeners(uiState: Forkop.UiState) {
|
||||
for (const listener of runtimeUiStateListeners) {
|
||||
try {
|
||||
listener(uiState);
|
||||
@@ -69,7 +69,7 @@ function notifyRuntimeUiStateListeners(uiState: Podkop.UiState) {
|
||||
|
||||
export async function refreshRuntimeUiState({
|
||||
force = false,
|
||||
}: { force?: boolean } = {}): Promise<Podkop.UiState | undefined> {
|
||||
}: { force?: boolean } = {}): Promise<Forkop.UiState | undefined> {
|
||||
if (!isDocumentVisible()) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -88,7 +88,7 @@ export async function refreshRuntimeUiState({
|
||||
|
||||
lastRuntimeUiStateRefreshAt = now;
|
||||
|
||||
const promise = PodkopShellMethods.getUiState()
|
||||
const promise = ForkopShellMethods.getUiState()
|
||||
.then((response) => {
|
||||
if (!response.success) {
|
||||
return undefined;
|
||||
+14
-14
@@ -1,4 +1,4 @@
|
||||
import { Podkop } from '../types';
|
||||
import { Forkop } 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;
|
||||
podkopRunning: number;
|
||||
podkopEnabled: number;
|
||||
podkopStatus: string;
|
||||
forkopRunning: number;
|
||||
forkopEnabled: number;
|
||||
forkopStatus: string;
|
||||
};
|
||||
};
|
||||
sectionsWidget: {
|
||||
loading: boolean;
|
||||
failed: boolean;
|
||||
data: Podkop.OutboundGroup[];
|
||||
data: Forkop.OutboundGroup[];
|
||||
latencyFetchingSections: Record<string, boolean>;
|
||||
latencyProgressSections: Record<string, Podkop.LatencyActionProgress>;
|
||||
latencyProgressSections: Record<string, Forkop.LatencyActionProgress>;
|
||||
selectorSwitchingSections: Record<string, string>;
|
||||
subscriptionUpdatingSections: Record<string, boolean>;
|
||||
};
|
||||
@@ -190,8 +190,8 @@ export interface StoreType {
|
||||
loading: boolean;
|
||||
loaded: boolean;
|
||||
providerInfoLoaded: boolean;
|
||||
podkop_version: string;
|
||||
podkop_latest_version: string;
|
||||
forkop_version: string;
|
||||
forkop_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: {
|
||||
podkopCheck: { loading: boolean };
|
||||
podkopInstall: { loading: boolean };
|
||||
forkopCheck: { loading: boolean };
|
||||
forkopInstall: { loading: boolean };
|
||||
singBoxCheck: { loading: boolean };
|
||||
singBoxInstall: { loading: boolean };
|
||||
singBoxInstallExtended: { loading: boolean };
|
||||
@@ -228,7 +228,7 @@ export interface StoreType {
|
||||
byedpiRemove: { loading: boolean };
|
||||
};
|
||||
updatesChecks: Record<
|
||||
Podkop.ComponentName,
|
||||
Forkop.ComponentName,
|
||||
{
|
||||
status: 'latest' | 'outdated' | 'dev' | null;
|
||||
latest_version: string;
|
||||
@@ -262,9 +262,9 @@ const initialStore: StoreType = {
|
||||
failed: false,
|
||||
data: {
|
||||
singbox: 0,
|
||||
podkopRunning: 0,
|
||||
podkopEnabled: 0,
|
||||
podkopStatus: '',
|
||||
forkopRunning: 0,
|
||||
forkopEnabled: 0,
|
||||
forkopStatus: '',
|
||||
},
|
||||
},
|
||||
sectionsWidget: {
|
||||
+6
-5
@@ -1,4 +1,4 @@
|
||||
import { PodkopShellMethods } from '../methods';
|
||||
import { ForkopShellMethods } 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,
|
||||
podkop_version: _('unknown'),
|
||||
podkop_latest_version: _('unknown'),
|
||||
forkop_version: _('unknown'),
|
||||
forkop_latest_version: _('unknown'),
|
||||
luci_app_version: _('unknown'),
|
||||
sing_box_version: _('unknown'),
|
||||
sing_box_extended: 0,
|
||||
@@ -65,14 +65,15 @@ export async function ensureSystemInfo({
|
||||
|
||||
const promise = (async () => {
|
||||
try {
|
||||
const systemInfo = await PodkopShellMethods.getSystemInfo();
|
||||
const systemInfo = await ForkopShellMethods.getSystemInfo();
|
||||
|
||||
if (requestId !== latestSystemInfoRequestId) {
|
||||
return store.get().diagnosticsSystemInfo;
|
||||
}
|
||||
|
||||
if (systemInfo.success) {
|
||||
const nextSystemInfo: StoreType['diagnosticsSystemInfo'] = normalizeSingBoxVariantFields({
|
||||
const nextSystemInfo: StoreType['diagnosticsSystemInfo'] =
|
||||
normalizeSingBoxVariantFields({
|
||||
...UNKNOWN_SYSTEM_INFO,
|
||||
loading: false,
|
||||
loaded: true,
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
import { beforeEach, describe, expect, it } from 'vitest';
|
||||
|
||||
import { PodkopLogWatcher } from '../podkopLogWatcher.service';
|
||||
import { ForkopLogWatcher } from '../forkopLogWatcher.service';
|
||||
|
||||
describe('PodkopLogWatcher', () => {
|
||||
const watcher = PodkopLogWatcher.getInstance();
|
||||
describe('ForkopLogWatcher', () => {
|
||||
const watcher = ForkopLogWatcher.getInstance();
|
||||
let rawLogs = '';
|
||||
let seenLines: string[] = [];
|
||||
|
||||
+17
-19
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest';
|
||||
|
||||
import {
|
||||
getLogNotificationKey,
|
||||
getPodkopLogNotification,
|
||||
getForkopLogNotification,
|
||||
isErrorLogLine,
|
||||
LogNotificationDeduper,
|
||||
} from '../logNotificationDeduper.service';
|
||||
@@ -37,46 +37,44 @@ class MemoryStorage implements Storage {
|
||||
|
||||
describe('LogNotificationDeduper', () => {
|
||||
it('accepts error, fatal, and component update log lines', () => {
|
||||
expect(isErrorLogLine('podkop-plus: [info] ok')).toBe(false);
|
||||
expect(isErrorLogLine('podkop-plus: [error] failed')).toBe(true);
|
||||
expect(isErrorLogLine('podkop-plus: [fatal] failed')).toBe(true);
|
||||
expect(isErrorLogLine('forkop: [info] ok')).toBe(false);
|
||||
expect(isErrorLogLine('forkop: [error] failed')).toBe(true);
|
||||
expect(isErrorLogLine('forkop: [fatal] failed')).toBe(true);
|
||||
expect(
|
||||
getPodkopLogNotification(
|
||||
'podkop-plus: [info] [component-update] zapret2 v1.2.3',
|
||||
getForkopLogNotification(
|
||||
'forkop: [info] [component-update] zapret2 v1.2.3',
|
||||
),
|
||||
).toEqual({
|
||||
kind: 'component-update',
|
||||
line: 'podkop-plus: [info] [component-update] zapret2 v1.2.3',
|
||||
line: 'forkop: [info] [component-update] zapret2 v1.2.3',
|
||||
component: 'zapret2',
|
||||
version: 'v1.2.3',
|
||||
});
|
||||
expect(getPodkopLogNotification('podkop-plus: [info] ok')).toBeNull();
|
||||
expect(getForkopLogNotification('forkop: [info] ok')).toBeNull();
|
||||
});
|
||||
|
||||
it('dedupes already shown log lines through session storage', () => {
|
||||
const storage = new MemoryStorage();
|
||||
const first = new LogNotificationDeduper(storage);
|
||||
|
||||
expect(first.shouldNotify('podkop-plus: [error] failed')).toBe(true);
|
||||
expect(first.shouldNotify('podkop-plus: [error] failed')).toBe(false);
|
||||
expect(first.shouldNotify('podkop-plus: [error] another failure')).toBe(
|
||||
true,
|
||||
);
|
||||
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('podkop-plus: [info] [component-update] podkop 1.2.3'),
|
||||
first.shouldNotify('forkop: [info] [component-update] forkop 1.2.3'),
|
||||
).toBe(true);
|
||||
|
||||
const afterReload = new LogNotificationDeduper(storage);
|
||||
|
||||
expect(afterReload.shouldNotify('podkop-plus: [error] failed')).toBe(false);
|
||||
expect(afterReload.shouldNotify('podkop-plus: [fatal] fatal failure')).toBe(
|
||||
expect(afterReload.shouldNotify('forkop: [error] failed')).toBe(false);
|
||||
expect(afterReload.shouldNotify('forkop: [fatal] fatal failure')).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
it('keeps the full log line as the replay key', () => {
|
||||
expect(
|
||||
getLogNotificationKey(' Jun 06 podkop-plus: [error] failed '),
|
||||
).toBe('Jun 06 podkop-plus: [error] failed');
|
||||
expect(getLogNotificationKey(' Jun 06 forkop: [error] failed ')).toBe(
|
||||
'Jun 06 forkop: [error] failed',
|
||||
);
|
||||
});
|
||||
});
|
||||
+7
-7
@@ -8,7 +8,7 @@ vi.mock('../../../helpers', () => ({
|
||||
executeShellCommand: mocks.executeShellCommand,
|
||||
}));
|
||||
|
||||
import { Podkop } from '../../types';
|
||||
import { Forkop } from '../../types';
|
||||
import { store } from '../store.service';
|
||||
import {
|
||||
getCachedRuntimeUiState,
|
||||
@@ -19,10 +19,10 @@ import {
|
||||
function createUiState(
|
||||
status = 'running & enabled',
|
||||
running = 1,
|
||||
): Podkop.UiState {
|
||||
): Forkop.UiState {
|
||||
return {
|
||||
service: {
|
||||
podkop: {
|
||||
forkop: {
|
||||
running,
|
||||
enabled: 1,
|
||||
status,
|
||||
@@ -73,14 +73,14 @@ describe('refreshRuntimeUiState', () => {
|
||||
);
|
||||
|
||||
expect(mocks.executeShellCommand).toHaveBeenCalledWith({
|
||||
command: '/usr/bin/podkop-plus',
|
||||
command: '/usr/bin/forkop',
|
||||
args: ['get_ui_state'],
|
||||
timeout: 3000,
|
||||
});
|
||||
expect(store.get().servicesInfoWidget.data).toMatchObject({
|
||||
podkopRunning: 0,
|
||||
podkopEnabled: 1,
|
||||
podkopStatus: 'stopped but enabled',
|
||||
forkopRunning: 0,
|
||||
forkopEnabled: 1,
|
||||
forkopStatus: 'stopped but enabled',
|
||||
});
|
||||
});
|
||||
|
||||
+8
-8
@@ -1,7 +1,7 @@
|
||||
import { beforeEach, describe, expect, it } from 'vitest';
|
||||
import { applyUiStateToStore } from '../uiState.service';
|
||||
import { store } from '../store.service';
|
||||
import { Podkop } from '../../types';
|
||||
import { Forkop } from '../../types';
|
||||
import {
|
||||
clearLocalActionOverlay,
|
||||
setLocalComponentAction,
|
||||
@@ -11,12 +11,12 @@ import {
|
||||
} from '../localActionOverlay.service';
|
||||
|
||||
function createUiState(
|
||||
actions: Partial<Podkop.UiState['actions']> = {},
|
||||
capabilities: Partial<Podkop.UiState['capabilities']> = {},
|
||||
): Podkop.UiState {
|
||||
actions: Partial<Forkop.UiState['actions']> = {},
|
||||
capabilities: Partial<Forkop.UiState['capabilities']> = {},
|
||||
): Forkop.UiState {
|
||||
return {
|
||||
service: {
|
||||
podkop: {
|
||||
forkop: {
|
||||
running: 0,
|
||||
enabled: 1,
|
||||
status: 'starting',
|
||||
@@ -114,9 +114,9 @@ describe('applyUiStateToStore', () => {
|
||||
loading: false,
|
||||
failed: false,
|
||||
data: {
|
||||
podkopEnabled: 1,
|
||||
podkopRunning: 0,
|
||||
podkopStatus: 'starting',
|
||||
forkopEnabled: 1,
|
||||
forkopRunning: 0,
|
||||
forkopStatus: 'starting',
|
||||
},
|
||||
});
|
||||
expect(state.diagnosticsSystemInfo).toMatchObject({
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
const UI_ACTION_NOTIFICATION_STORAGE_KEY =
|
||||
'podkop-plus:owned-ui-action-notifications:v1';
|
||||
'forkop:owned-ui-action-notifications:v1';
|
||||
const MAX_STORED_UI_ACTION_NOTIFICATIONS = 100;
|
||||
|
||||
export type UiActionNotificationKind = 'component' | 'subscription';
|
||||
+12
-12
@@ -1,11 +1,11 @@
|
||||
import { getComponentActionKey } from '../helpers/getComponentActionKey';
|
||||
import { normalizeSingBoxVariantFields } from '../helpers/singBoxVariant';
|
||||
import type { Podkop } from '../types';
|
||||
import type { Forkop } from '../types';
|
||||
import { getLocalActionOverlay } from './localActionOverlay.service';
|
||||
import { store } from './store.service';
|
||||
import type { StoreType } from './store.service';
|
||||
|
||||
type UiActionMap = Partial<Podkop.UiState['actions']>;
|
||||
type UiActionMap = Partial<Forkop.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 {
|
||||
podkopCheck: { loading: false },
|
||||
podkopInstall: { loading: false },
|
||||
forkopCheck: { loading: false },
|
||||
forkopInstall: { loading: false },
|
||||
singBoxCheck: { loading: false },
|
||||
singBoxInstall: { loading: false },
|
||||
singBoxInstallExtended: { loading: false },
|
||||
@@ -43,8 +43,8 @@ function getEmptyDiagnosticsActions(): StoreType['diagnosticsActions'] {
|
||||
}
|
||||
|
||||
function normalizeLatencyProgress(
|
||||
progress?: Podkop.LatencyActionProgress,
|
||||
): Podkop.LatencyActionProgress | undefined {
|
||||
progress?: Forkop.LatencyActionProgress,
|
||||
): Forkop.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: Podkop.UiState) {
|
||||
function applyServiceState(uiState: Forkop.UiState) {
|
||||
const currentSystemInfo = store.get().diagnosticsSystemInfo;
|
||||
const nextSystemInfo = {
|
||||
...currentSystemInfo,
|
||||
@@ -88,9 +88,9 @@ function applyServiceState(uiState: Podkop.UiState) {
|
||||
failed: false,
|
||||
data: {
|
||||
singbox: uiState.service.sing_box.running,
|
||||
podkopRunning: uiState.service.podkop.running,
|
||||
podkopEnabled: uiState.service.podkop.enabled,
|
||||
podkopStatus: uiState.service.podkop.status,
|
||||
forkopRunning: uiState.service.forkop.running,
|
||||
forkopEnabled: uiState.service.forkop.enabled,
|
||||
forkopStatus: uiState.service.forkop.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, Podkop.LatencyActionProgress> =
|
||||
const latencyProgressSections: Record<string, Forkop.LatencyActionProgress> =
|
||||
{};
|
||||
const updatesActions = getEmptyUpdatesActions();
|
||||
const diagnosticsActions = getEmptyDiagnosticsActions();
|
||||
@@ -188,7 +188,7 @@ function applyActionState(actions: UiActionMap = {}) {
|
||||
});
|
||||
}
|
||||
|
||||
export function applyUiStateToStore(uiState: Podkop.UiState) {
|
||||
export function applyUiStateToStore(uiState: Forkop.UiState) {
|
||||
applyServiceState(uiState);
|
||||
applyActionState(uiState.actions);
|
||||
}
|
||||
+94
-94
@@ -8,7 +8,7 @@ import { copyToClipboard } from '../../../helpers/copyToClipboard';
|
||||
import { showToast } from '../../../helpers/showToast';
|
||||
import { prettyBytes } from '../../../helpers/prettyBytes';
|
||||
import { renderCopyIcon24 } from '../../../icons';
|
||||
import { CustomPodkopMethods, PodkopShellMethods } from '../../methods';
|
||||
import { CustomForkopMethods, ForkopShellMethods } 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 { Podkop } from '../../types';
|
||||
import { Forkop } from '../../types';
|
||||
import {
|
||||
getCachedRuntimeUiState,
|
||||
refreshRuntimeUiState,
|
||||
@@ -79,7 +79,7 @@ async function fetchDashboardSectionsOnce(mountId: number) {
|
||||
});
|
||||
|
||||
try {
|
||||
const { data, success } = await CustomPodkopMethods.getDashboardSections();
|
||||
const { data, success } = await CustomForkopMethods.getDashboardSections();
|
||||
|
||||
if (
|
||||
!dashboardMounted ||
|
||||
@@ -219,7 +219,7 @@ function setLatencyFetching(
|
||||
sectionName: string,
|
||||
fetching: boolean,
|
||||
local = false,
|
||||
progress?: Podkop.LatencyActionProgress,
|
||||
progress?: Forkop.LatencyActionProgress,
|
||||
) {
|
||||
if (local || !fetching) {
|
||||
setLocalLatencyAction(sectionName, fetching && local);
|
||||
@@ -255,7 +255,7 @@ function setLatencyFetching(
|
||||
async function completeSubscriptionUpdateJob(
|
||||
jobId: string,
|
||||
sectionName: string,
|
||||
response: Podkop.MethodResponse<Podkop.SubscriptionUpdateJobState>,
|
||||
response: Forkop.MethodResponse<Forkop.SubscriptionUpdateJobState>,
|
||||
) {
|
||||
if (pageUnloading) {
|
||||
setSubscriptionUpdating(sectionName, false);
|
||||
@@ -287,7 +287,7 @@ async function completeSubscriptionUpdateJob(
|
||||
setSubscriptionUpdating(sectionName, false);
|
||||
|
||||
if (jobId && response.success) {
|
||||
void PodkopShellMethods.uiActionAck('subscription', jobId);
|
||||
void ForkopShellMethods.uiActionAck('subscription', jobId);
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
@@ -305,7 +305,7 @@ async function completeSubscriptionUpdateJob(
|
||||
}
|
||||
|
||||
async function followSubscriptionUpdateState(
|
||||
state: Podkop.SubscriptionUpdateJobState,
|
||||
state: Forkop.SubscriptionUpdateJobState,
|
||||
) {
|
||||
const jobId = state.job_id;
|
||||
const sectionName = state.section || '';
|
||||
@@ -325,11 +325,11 @@ async function followSubscriptionUpdateState(
|
||||
|
||||
try {
|
||||
const response = state.running
|
||||
? await PodkopShellMethods.waitSubscriptionUpdateJob(jobId)
|
||||
? await ForkopShellMethods.waitSubscriptionUpdateJob(jobId)
|
||||
: ({
|
||||
success: true,
|
||||
data: state,
|
||||
} as Podkop.MethodSuccessResponse<Podkop.SubscriptionUpdateJobState>);
|
||||
} as Forkop.MethodSuccessResponse<Forkop.SubscriptionUpdateJobState>);
|
||||
|
||||
await completeSubscriptionUpdateJob(jobId, sectionName, response);
|
||||
} catch (error) {
|
||||
@@ -366,13 +366,13 @@ async function completeLatencyTestJob(jobId: string, sectionName: string) {
|
||||
}
|
||||
|
||||
if (jobId) {
|
||||
void PodkopShellMethods.uiActionAck('latency', jobId);
|
||||
void ForkopShellMethods.uiActionAck('latency', jobId);
|
||||
}
|
||||
|
||||
void fetchDashboardSections({ force: true });
|
||||
}
|
||||
|
||||
async function followLatencyTestState(state: Podkop.LatencyActionState) {
|
||||
async function followLatencyTestState(state: Forkop.LatencyActionState) {
|
||||
const jobId = state.job_id;
|
||||
const sectionName = state.section || '';
|
||||
|
||||
@@ -391,7 +391,7 @@ async function followLatencyTestState(state: Podkop.LatencyActionState) {
|
||||
|
||||
try {
|
||||
if (state.running) {
|
||||
await PodkopShellMethods.waitLatencyTestJob(jobId);
|
||||
await ForkopShellMethods.waitLatencyTestJob(jobId);
|
||||
}
|
||||
|
||||
await completeLatencyTestJob(jobId, sectionName);
|
||||
@@ -405,13 +405,13 @@ async function followLatencyTestState(state: Podkop.LatencyActionState) {
|
||||
}
|
||||
}
|
||||
|
||||
function followDashboardActionsFromUiState(uiState: Podkop.UiState) {
|
||||
function followDashboardActionsFromUiState(uiState: Forkop.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 PodkopShellMethods.uiActionAck('subscription', state.job_id);
|
||||
void ForkopShellMethods.uiActionAck('subscription', state.job_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,7 +420,7 @@ function followDashboardActionsFromUiState(uiState: Podkop.UiState) {
|
||||
void followLatencyTestState(state);
|
||||
} else if (state.job_id && !handledLatencyJobs.has(state.job_id)) {
|
||||
handledLatencyJobs.add(state.job_id);
|
||||
void PodkopShellMethods.uiActionAck('latency', state.job_id);
|
||||
void ForkopShellMethods.uiActionAck('latency', state.job_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -571,7 +571,7 @@ function getDashboardServiceAvailability() {
|
||||
return getServiceAvailability({
|
||||
loading: service.loading,
|
||||
failed: service.failed,
|
||||
running: service.data.podkopRunning,
|
||||
running: service.data.forkopRunning,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -611,7 +611,7 @@ function syncDashboardServiceAvailability() {
|
||||
const stopped = availability === 'stopped';
|
||||
const container = document.getElementById('dashboard-status');
|
||||
|
||||
container?.classList.toggle('pdk_dashboard-page--service-stopped', stopped);
|
||||
container?.classList.toggle('fkp_dashboard-page--service-stopped', stopped);
|
||||
|
||||
if (stopped || availability === 'loading') {
|
||||
stopDashboardDataUpdates();
|
||||
@@ -646,7 +646,7 @@ async function handleChooseOutbound(
|
||||
setSelectorSwitching(sectionName, tag);
|
||||
|
||||
try {
|
||||
await PodkopShellMethods.setClashApiGroupProxy(selector, tag);
|
||||
await ForkopShellMethods.setClashApiGroupProxy(selector, tag);
|
||||
await fetchDashboardSections({ force: true });
|
||||
} finally {
|
||||
setSelectorSwitching(sectionName);
|
||||
@@ -654,9 +654,9 @@ async function handleChooseOutbound(
|
||||
}
|
||||
|
||||
function getInitialLatencyProgress(
|
||||
latencyType: Podkop.LatencyActionState['latency_type'],
|
||||
latencyType: Forkop.LatencyActionState['latency_type'],
|
||||
tag: string,
|
||||
): Podkop.LatencyActionProgress | undefined {
|
||||
): Forkop.LatencyActionProgress | undefined {
|
||||
if (latencyType !== 'proxy_list') {
|
||||
return undefined;
|
||||
}
|
||||
@@ -678,7 +678,7 @@ function getInitialLatencyProgress(
|
||||
}
|
||||
|
||||
async function handleTestLatency(
|
||||
latencyType: Podkop.LatencyActionState['latency_type'],
|
||||
latencyType: Forkop.LatencyActionState['latency_type'],
|
||||
sectionName: string,
|
||||
tag: string,
|
||||
timeout?: string,
|
||||
@@ -698,7 +698,7 @@ async function handleTestLatency(
|
||||
let completed = false;
|
||||
|
||||
try {
|
||||
const startResponse = await PodkopShellMethods.latencyTestStart(
|
||||
const startResponse = await ForkopShellMethods.latencyTestStart(
|
||||
latencyType,
|
||||
sectionName,
|
||||
tag,
|
||||
@@ -717,7 +717,7 @@ async function handleTestLatency(
|
||||
|
||||
followedLatencyJobs.add(jobId);
|
||||
ownsJobFollow = true;
|
||||
await PodkopShellMethods.waitLatencyTestJob(jobId);
|
||||
await ForkopShellMethods.waitLatencyTestJob(jobId);
|
||||
await completeLatencyTestJob(jobId, sectionName);
|
||||
completed = true;
|
||||
} catch (error) {
|
||||
@@ -734,8 +734,8 @@ async function handleTestLatency(
|
||||
}
|
||||
|
||||
async function handleCopyOutbound(
|
||||
section: Podkop.OutboundGroup,
|
||||
outbound: Podkop.Outbound,
|
||||
section: Forkop.OutboundGroup,
|
||||
outbound: Forkop.Outbound,
|
||||
) {
|
||||
const link = outbound.link;
|
||||
|
||||
@@ -744,7 +744,7 @@ async function handleCopyOutbound(
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await PodkopShellMethods.getOutboundLink(
|
||||
const response = await ForkopShellMethods.getOutboundLink(
|
||||
section.sectionName,
|
||||
outbound.code,
|
||||
);
|
||||
@@ -768,18 +768,18 @@ function formatUrlTestModalValue(value: unknown) {
|
||||
|
||||
function getUrlTestLatencyClass(latency: number) {
|
||||
if (!latency) {
|
||||
return 'pdk_dashboard-page__outbound-grid__item__latency--empty';
|
||||
return 'fkp_dashboard-page__outbound-grid__item__latency--empty';
|
||||
}
|
||||
|
||||
if (latency < 800) {
|
||||
return 'pdk_dashboard-page__outbound-grid__item__latency--green';
|
||||
return 'fkp_dashboard-page__outbound-grid__item__latency--green';
|
||||
}
|
||||
|
||||
if (latency < 1500) {
|
||||
return 'pdk_dashboard-page__outbound-grid__item__latency--yellow';
|
||||
return 'fkp_dashboard-page__outbound-grid__item__latency--yellow';
|
||||
}
|
||||
|
||||
return 'pdk_dashboard-page__outbound-grid__item__latency--red';
|
||||
return 'fkp_dashboard-page__outbound-grid__item__latency--red';
|
||||
}
|
||||
|
||||
function formatUrlTestLatency(latency: number) {
|
||||
@@ -796,7 +796,7 @@ function renderDetailsUrl(value: unknown) {
|
||||
return E(
|
||||
'a',
|
||||
{
|
||||
class: 'pdk_dashboard-page__urltest-details__url',
|
||||
class: 'fkp_dashboard-page__urltest-details__url',
|
||||
href: url,
|
||||
target: '_blank',
|
||||
rel: 'noopener noreferrer',
|
||||
@@ -817,7 +817,7 @@ function getDetectedCountryFlag(country?: string) {
|
||||
);
|
||||
}
|
||||
|
||||
function renderDetailsMemberName(member: Podkop.UrlTestMember) {
|
||||
function renderDetailsMemberName(member: Forkop.UrlTestMember) {
|
||||
const countryFlag = getDetectedCountryFlag(member.country);
|
||||
if (!countryFlag) {
|
||||
return member.displayName;
|
||||
@@ -826,14 +826,14 @@ function renderDetailsMemberName(member: Podkop.UrlTestMember) {
|
||||
return [
|
||||
E(
|
||||
'span',
|
||||
{ class: 'pdk_dashboard-page__urltest-details__country-badge' },
|
||||
{ class: 'fkp_dashboard-page__urltest-details__country-badge' },
|
||||
countryFlag,
|
||||
),
|
||||
member.displayName,
|
||||
];
|
||||
}
|
||||
|
||||
function renderUrlTestSelectedValue(info: Podkop.UrlTestInfo) {
|
||||
function renderUrlTestSelectedValue(info: Forkop.UrlTestInfo) {
|
||||
const selectedMember = info.outbounds.find((member) => member.selected);
|
||||
const selectedName =
|
||||
selectedMember?.displayName || info.selectedName || info.selectedCode || '';
|
||||
@@ -845,18 +845,18 @@ function renderUrlTestSelectedValue(info: Podkop.UrlTestInfo) {
|
||||
|
||||
return E(
|
||||
'span',
|
||||
{ class: 'pdk_dashboard-page__urltest-details__selected-value' },
|
||||
{ class: 'fkp_dashboard-page__urltest-details__selected-value' },
|
||||
[
|
||||
E(
|
||||
'span',
|
||||
{ class: 'pdk_dashboard-page__urltest-details__selected-name' },
|
||||
{ class: 'fkp_dashboard-page__urltest-details__selected-name' },
|
||||
selectedMember ? renderDetailsMemberName(selectedMember) : name,
|
||||
),
|
||||
...(selectedMember?.type
|
||||
? [
|
||||
E(
|
||||
'span',
|
||||
{ class: 'pdk_dashboard-page__urltest-details__selected-type' },
|
||||
{ class: 'fkp_dashboard-page__urltest-details__selected-type' },
|
||||
selectedMember.type,
|
||||
),
|
||||
]
|
||||
@@ -882,7 +882,7 @@ function renderUrlTestCopyButton(
|
||||
'button',
|
||||
{
|
||||
type: 'button',
|
||||
class: 'btn pdk_dashboard-page__urltest-details__copy-button',
|
||||
class: 'btn fkp_dashboard-page__urltest-details__copy-button',
|
||||
title,
|
||||
'aria-label': title,
|
||||
click: onClick,
|
||||
@@ -892,8 +892,8 @@ function renderUrlTestCopyButton(
|
||||
}
|
||||
|
||||
function renderUrlTestInfoModal(
|
||||
section: Podkop.OutboundGroup,
|
||||
outbound: Podkop.Outbound,
|
||||
section: Forkop.OutboundGroup,
|
||||
outbound: Forkop.Outbound,
|
||||
) {
|
||||
const info = outbound.urlTestInfo;
|
||||
|
||||
@@ -920,12 +920,12 @@ function renderUrlTestInfoModal(
|
||||
},
|
||||
];
|
||||
|
||||
return E('div', { class: 'pdk_dashboard-page__urltest-details' }, [
|
||||
return E('div', { class: 'fkp_dashboard-page__urltest-details' }, [
|
||||
E(
|
||||
'dl',
|
||||
{ class: 'pdk_dashboard-page__urltest-details__params' },
|
||||
{ class: 'fkp_dashboard-page__urltest-details__params' },
|
||||
fields.map(({ label, value, children }) =>
|
||||
E('div', { class: 'pdk_dashboard-page__urltest-details__param' }, [
|
||||
E('div', { class: 'fkp_dashboard-page__urltest-details__param' }, [
|
||||
E('dt', {}, label),
|
||||
E(
|
||||
'dd',
|
||||
@@ -935,24 +935,24 @@ function renderUrlTestInfoModal(
|
||||
]),
|
||||
),
|
||||
),
|
||||
E('div', { class: 'pdk_dashboard-page__urltest-details__outbounds' }, [
|
||||
E('div', { class: 'fkp_dashboard-page__urltest-details__outbounds' }, [
|
||||
E(
|
||||
'div',
|
||||
{ class: 'pdk_dashboard-page__urltest-details__outbounds-title' },
|
||||
{ class: 'fkp_dashboard-page__urltest-details__outbounds-title' },
|
||||
_('Nodes'),
|
||||
),
|
||||
E(
|
||||
'div',
|
||||
{ class: 'pdk_dashboard-page__urltest-details__table' },
|
||||
{ class: 'fkp_dashboard-page__urltest-details__table' },
|
||||
info.outbounds.length
|
||||
? info.outbounds.map((member) =>
|
||||
E(
|
||||
'div',
|
||||
{
|
||||
class: [
|
||||
'pdk_dashboard-page__urltest-details__row',
|
||||
'fkp_dashboard-page__urltest-details__row',
|
||||
member.selected
|
||||
? 'pdk_dashboard-page__urltest-details__row--active'
|
||||
? 'fkp_dashboard-page__urltest-details__row--active'
|
||||
: '',
|
||||
]
|
||||
.filter(Boolean)
|
||||
@@ -962,7 +962,7 @@ function renderUrlTestInfoModal(
|
||||
E(
|
||||
'div',
|
||||
{
|
||||
class: 'pdk_dashboard-page__urltest-details__row-name',
|
||||
class: 'fkp_dashboard-page__urltest-details__row-name',
|
||||
},
|
||||
[
|
||||
E('b', {}, renderDetailsMemberName(member)),
|
||||
@@ -972,7 +972,7 @@ function renderUrlTestInfoModal(
|
||||
'span',
|
||||
{
|
||||
class:
|
||||
'pdk_dashboard-page__urltest-details__row-type',
|
||||
'fkp_dashboard-page__urltest-details__row-type',
|
||||
},
|
||||
member.type,
|
||||
),
|
||||
@@ -983,7 +983,7 @@ function renderUrlTestInfoModal(
|
||||
E(
|
||||
'div',
|
||||
{
|
||||
class: 'pdk_dashboard-page__urltest-details__row-meta',
|
||||
class: 'fkp_dashboard-page__urltest-details__row-meta',
|
||||
},
|
||||
[
|
||||
E(
|
||||
@@ -1000,7 +1000,7 @@ function renderUrlTestInfoModal(
|
||||
})
|
||||
: E('span', {
|
||||
class:
|
||||
'pdk_dashboard-page__urltest-details__copy-placeholder',
|
||||
'fkp_dashboard-page__urltest-details__copy-placeholder',
|
||||
}),
|
||||
],
|
||||
),
|
||||
@@ -1008,13 +1008,13 @@ function renderUrlTestInfoModal(
|
||||
: [
|
||||
E(
|
||||
'div',
|
||||
{ class: 'pdk_dashboard-page__urltest-details__empty' },
|
||||
{ class: 'fkp_dashboard-page__urltest-details__empty' },
|
||||
_('Node list is empty'),
|
||||
),
|
||||
],
|
||||
),
|
||||
]),
|
||||
E('div', { class: 'pdk_dashboard-page__urltest-details__footer' }, [
|
||||
E('div', { class: 'fkp_dashboard-page__urltest-details__footer' }, [
|
||||
E(
|
||||
'button',
|
||||
{
|
||||
@@ -1031,8 +1031,8 @@ function renderUrlTestInfoModal(
|
||||
}
|
||||
|
||||
function handleShowUrlTestInfo(
|
||||
section: Podkop.OutboundGroup,
|
||||
outbound: Podkop.Outbound,
|
||||
section: Forkop.OutboundGroup,
|
||||
outbound: Forkop.Outbound,
|
||||
) {
|
||||
if (!outbound.urlTestInfo) {
|
||||
return;
|
||||
@@ -1046,7 +1046,7 @@ function handleShowUrlTestInfo(
|
||||
);
|
||||
}
|
||||
|
||||
function renderPrioritySelectedValue(info: Podkop.PriorityInfo) {
|
||||
function renderPrioritySelectedValue(info: Forkop.PriorityInfo) {
|
||||
const selectedMember = info.outbounds.find((member) => member.selected);
|
||||
const selectedName =
|
||||
selectedMember?.displayName || info.selectedName || info.selectedCode || '';
|
||||
@@ -1058,15 +1058,15 @@ function renderPrioritySelectedValue(info: Podkop.PriorityInfo) {
|
||||
|
||||
return E(
|
||||
'span',
|
||||
{ class: 'pdk_dashboard-page__urltest-details__selected-value' },
|
||||
{ class: 'fkp_dashboard-page__urltest-details__selected-value' },
|
||||
[
|
||||
E(
|
||||
'span',
|
||||
{
|
||||
class: [
|
||||
'pdk_dashboard-page__urltest-details__selected-name',
|
||||
'fkp_dashboard-page__urltest-details__selected-name',
|
||||
selectedMember
|
||||
? 'pdk_dashboard-page__urltest-details__priority-name'
|
||||
? 'fkp_dashboard-page__urltest-details__priority-name'
|
||||
: '',
|
||||
]
|
||||
.filter(Boolean)
|
||||
@@ -1078,7 +1078,7 @@ function renderPrioritySelectedValue(info: Podkop.PriorityInfo) {
|
||||
? [
|
||||
E(
|
||||
'span',
|
||||
{ class: 'pdk_dashboard-page__urltest-details__selected-type' },
|
||||
{ class: 'fkp_dashboard-page__urltest-details__selected-type' },
|
||||
selectedMember.type,
|
||||
),
|
||||
]
|
||||
@@ -1096,31 +1096,31 @@ function renderPrioritySelectedValue(info: Podkop.PriorityInfo) {
|
||||
);
|
||||
}
|
||||
|
||||
function renderPriorityMemberName(member: Podkop.PriorityMember) {
|
||||
function renderPriorityMemberName(member: Forkop.PriorityMember) {
|
||||
const levelName = member.levelName || _('Level');
|
||||
|
||||
return [
|
||||
E(
|
||||
'span',
|
||||
{ class: 'pdk_dashboard-page__urltest-details__priority-number' },
|
||||
{ class: 'fkp_dashboard-page__urltest-details__priority-number' },
|
||||
`#${member.levelIndex + 1}`,
|
||||
),
|
||||
E(
|
||||
'span',
|
||||
{ class: 'pdk_dashboard-page__urltest-details__priority-level' },
|
||||
{ class: 'fkp_dashboard-page__urltest-details__priority-level' },
|
||||
levelName,
|
||||
),
|
||||
E(
|
||||
'span',
|
||||
{ class: 'pdk_dashboard-page__urltest-details__priority-node' },
|
||||
{ class: 'fkp_dashboard-page__urltest-details__priority-node' },
|
||||
renderDetailsMemberName(member),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
function renderPriorityInfoModal(
|
||||
section: Podkop.OutboundGroup,
|
||||
outbound: Podkop.Outbound,
|
||||
section: Forkop.OutboundGroup,
|
||||
outbound: Forkop.Outbound,
|
||||
) {
|
||||
const info = outbound.priorityInfo;
|
||||
|
||||
@@ -1169,12 +1169,12 @@ function renderPriorityInfoModal(
|
||||
},
|
||||
];
|
||||
|
||||
return E('div', { class: 'pdk_dashboard-page__urltest-details' }, [
|
||||
return E('div', { class: 'fkp_dashboard-page__urltest-details' }, [
|
||||
E(
|
||||
'dl',
|
||||
{ class: 'pdk_dashboard-page__urltest-details__params' },
|
||||
{ class: 'fkp_dashboard-page__urltest-details__params' },
|
||||
fields.map(({ label, value, children }) =>
|
||||
E('div', { class: 'pdk_dashboard-page__urltest-details__param' }, [
|
||||
E('div', { class: 'fkp_dashboard-page__urltest-details__param' }, [
|
||||
E('dt', {}, label),
|
||||
E(
|
||||
'dd',
|
||||
@@ -1184,24 +1184,24 @@ function renderPriorityInfoModal(
|
||||
]),
|
||||
),
|
||||
),
|
||||
E('div', { class: 'pdk_dashboard-page__urltest-details__outbounds' }, [
|
||||
E('div', { class: 'fkp_dashboard-page__urltest-details__outbounds' }, [
|
||||
E(
|
||||
'div',
|
||||
{ class: 'pdk_dashboard-page__urltest-details__outbounds-title' },
|
||||
{ class: 'fkp_dashboard-page__urltest-details__outbounds-title' },
|
||||
_('Nodes'),
|
||||
),
|
||||
E(
|
||||
'div',
|
||||
{ class: 'pdk_dashboard-page__urltest-details__table' },
|
||||
{ class: 'fkp_dashboard-page__urltest-details__table' },
|
||||
info.outbounds.length
|
||||
? info.outbounds.map((member) =>
|
||||
E(
|
||||
'div',
|
||||
{
|
||||
class: [
|
||||
'pdk_dashboard-page__urltest-details__row',
|
||||
'fkp_dashboard-page__urltest-details__row',
|
||||
member.selected
|
||||
? 'pdk_dashboard-page__urltest-details__row--active'
|
||||
? 'fkp_dashboard-page__urltest-details__row--active'
|
||||
: '',
|
||||
]
|
||||
.filter(Boolean)
|
||||
@@ -1211,14 +1211,14 @@ function renderPriorityInfoModal(
|
||||
E(
|
||||
'div',
|
||||
{
|
||||
class: 'pdk_dashboard-page__urltest-details__row-name',
|
||||
class: 'fkp_dashboard-page__urltest-details__row-name',
|
||||
},
|
||||
[
|
||||
E(
|
||||
'b',
|
||||
{
|
||||
class:
|
||||
'pdk_dashboard-page__urltest-details__priority-name',
|
||||
'fkp_dashboard-page__urltest-details__priority-name',
|
||||
},
|
||||
renderPriorityMemberName(member),
|
||||
),
|
||||
@@ -1228,7 +1228,7 @@ function renderPriorityInfoModal(
|
||||
'span',
|
||||
{
|
||||
class:
|
||||
'pdk_dashboard-page__urltest-details__row-type',
|
||||
'fkp_dashboard-page__urltest-details__row-type',
|
||||
},
|
||||
member.type,
|
||||
),
|
||||
@@ -1239,7 +1239,7 @@ function renderPriorityInfoModal(
|
||||
E(
|
||||
'div',
|
||||
{
|
||||
class: 'pdk_dashboard-page__urltest-details__row-meta',
|
||||
class: 'fkp_dashboard-page__urltest-details__row-meta',
|
||||
},
|
||||
[
|
||||
E(
|
||||
@@ -1256,7 +1256,7 @@ function renderPriorityInfoModal(
|
||||
})
|
||||
: E('span', {
|
||||
class:
|
||||
'pdk_dashboard-page__urltest-details__copy-placeholder',
|
||||
'fkp_dashboard-page__urltest-details__copy-placeholder',
|
||||
}),
|
||||
],
|
||||
),
|
||||
@@ -1264,13 +1264,13 @@ function renderPriorityInfoModal(
|
||||
: [
|
||||
E(
|
||||
'div',
|
||||
{ class: 'pdk_dashboard-page__urltest-details__empty' },
|
||||
{ class: 'fkp_dashboard-page__urltest-details__empty' },
|
||||
_('Node list is empty'),
|
||||
),
|
||||
],
|
||||
),
|
||||
]),
|
||||
E('div', { class: 'pdk_dashboard-page__urltest-details__footer' }, [
|
||||
E('div', { class: 'fkp_dashboard-page__urltest-details__footer' }, [
|
||||
E(
|
||||
'button',
|
||||
{
|
||||
@@ -1287,8 +1287,8 @@ function renderPriorityInfoModal(
|
||||
}
|
||||
|
||||
function handleShowPriorityInfo(
|
||||
section: Podkop.OutboundGroup,
|
||||
outbound: Podkop.Outbound,
|
||||
section: Forkop.OutboundGroup,
|
||||
outbound: Forkop.Outbound,
|
||||
) {
|
||||
if (!outbound.priorityInfo) {
|
||||
return;
|
||||
@@ -1302,7 +1302,7 @@ function handleShowPriorityInfo(
|
||||
);
|
||||
}
|
||||
|
||||
async function handleUpdateSubscription(section: Podkop.OutboundGroup) {
|
||||
async function handleUpdateSubscription(section: Forkop.OutboundGroup) {
|
||||
if (
|
||||
store.get().sectionsWidget.subscriptionUpdatingSections[section.sectionName]
|
||||
) {
|
||||
@@ -1314,7 +1314,7 @@ async function handleUpdateSubscription(section: Podkop.OutboundGroup) {
|
||||
let ownsJobFollow = false;
|
||||
|
||||
try {
|
||||
const startResponse = await PodkopShellMethods.subscriptionUpdateStart(
|
||||
const startResponse = await ForkopShellMethods.subscriptionUpdateStart(
|
||||
section.sectionName,
|
||||
);
|
||||
|
||||
@@ -1330,7 +1330,7 @@ async function handleUpdateSubscription(section: Podkop.OutboundGroup) {
|
||||
|
||||
followedSubscriptionJobs.add(jobId);
|
||||
ownsJobFollow = true;
|
||||
const response = await PodkopShellMethods.waitSubscriptionUpdateJob(jobId);
|
||||
const response = await ForkopShellMethods.waitSubscriptionUpdateJob(jobId);
|
||||
await completeSubscriptionUpdateJob(jobId, section.sectionName, response);
|
||||
} catch (error) {
|
||||
logger.error('[DASHBOARD]', 'handleUpdateSubscription: failed', error);
|
||||
@@ -1670,14 +1670,14 @@ async function renderServicesInfoWidget() {
|
||||
title: _('Services info'),
|
||||
items: [
|
||||
{
|
||||
key: 'Podkop Plus',
|
||||
value: servicesInfoWidget.data.podkopRunning
|
||||
key: 'Forkop',
|
||||
value: servicesInfoWidget.data.forkopRunning
|
||||
? _('✔ Running')
|
||||
: _('✘ Stopped'),
|
||||
attributes: {
|
||||
class: servicesInfoWidget.data.podkopRunning
|
||||
? 'pdk_dashboard-page__widgets-section__item__row--success'
|
||||
: 'pdk_dashboard-page__widgets-section__item__row--error',
|
||||
class: servicesInfoWidget.data.forkopRunning
|
||||
? 'fkp_dashboard-page__widgets-section__item__row--success'
|
||||
: 'fkp_dashboard-page__widgets-section__item__row--error',
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -1687,8 +1687,8 @@ async function renderServicesInfoWidget() {
|
||||
: _('✘ Stopped'),
|
||||
attributes: {
|
||||
class: servicesInfoWidget.data.singbox
|
||||
? 'pdk_dashboard-page__widgets-section__item__row--success'
|
||||
: 'pdk_dashboard-page__widgets-section__item__row--error',
|
||||
? 'fkp_dashboard-page__widgets-section__item__row--success'
|
||||
: 'fkp_dashboard-page__widgets-section__item__row--error',
|
||||
},
|
||||
},
|
||||
],
|
||||
+50
-50
@@ -6,12 +6,12 @@ import {
|
||||
} from '../../../../icons';
|
||||
import { isCopyableProxyLink, svgEl } from '../../../../helpers';
|
||||
import { prettyBytes } from '../../../../helpers/prettyBytes';
|
||||
import { Podkop } from '../../../types';
|
||||
import { Forkop } from '../../../types';
|
||||
|
||||
interface IRenderSectionsProps {
|
||||
loading: boolean;
|
||||
failed: boolean;
|
||||
section: Podkop.OutboundGroup;
|
||||
section: Forkop.OutboundGroup;
|
||||
onTestLatency: (tag: string | string[]) => void;
|
||||
onChooseOutbound: (
|
||||
sectionName: string,
|
||||
@@ -19,20 +19,20 @@ interface IRenderSectionsProps {
|
||||
tag: string,
|
||||
) => void;
|
||||
onCopyOutbound: (
|
||||
section: Podkop.OutboundGroup,
|
||||
outbound: Podkop.Outbound,
|
||||
section: Forkop.OutboundGroup,
|
||||
outbound: Forkop.Outbound,
|
||||
) => void;
|
||||
onShowUrlTestInfo: (
|
||||
section: Podkop.OutboundGroup,
|
||||
outbound: Podkop.Outbound,
|
||||
section: Forkop.OutboundGroup,
|
||||
outbound: Forkop.Outbound,
|
||||
) => void;
|
||||
onShowPriorityInfo: (
|
||||
section: Podkop.OutboundGroup,
|
||||
outbound: Podkop.Outbound,
|
||||
section: Forkop.OutboundGroup,
|
||||
outbound: Forkop.Outbound,
|
||||
) => void;
|
||||
onUpdateSubscription: (section: Podkop.OutboundGroup) => void;
|
||||
onUpdateSubscription: (section: Forkop.OutboundGroup) => void;
|
||||
latencyFetching: boolean;
|
||||
latencyProgress?: Podkop.LatencyActionProgress;
|
||||
latencyProgress?: Forkop.LatencyActionProgress;
|
||||
subscriptionUpdating: boolean;
|
||||
selectorSwitchingTag?: string;
|
||||
}
|
||||
@@ -41,7 +41,7 @@ function renderFailedState() {
|
||||
return E(
|
||||
'div',
|
||||
{
|
||||
class: 'pdk_dashboard-page__outbound-section centered',
|
||||
class: 'fkp_dashboard-page__outbound-section centered',
|
||||
style: 'height: 127px',
|
||||
},
|
||||
E('span', {}, [E('span', {}, _('Dashboard currently unavailable'))]),
|
||||
@@ -51,7 +51,7 @@ function renderFailedState() {
|
||||
function renderLoadingState() {
|
||||
return E('div', {
|
||||
id: 'dashboard-sections-grid-skeleton',
|
||||
class: 'pdk_dashboard-page__outbound-section skeleton',
|
||||
class: 'fkp_dashboard-page__outbound-section skeleton',
|
||||
style: 'height: 127px',
|
||||
});
|
||||
}
|
||||
@@ -97,7 +97,7 @@ function renderMetadataAction(label: string, url?: string) {
|
||||
return E(
|
||||
'a',
|
||||
{
|
||||
class: 'btn pdk_dashboard-page__subscription-meta__action',
|
||||
class: 'btn fkp_dashboard-page__subscription-meta__action',
|
||||
href: url,
|
||||
target: '_blank',
|
||||
rel: 'noopener noreferrer',
|
||||
@@ -109,7 +109,7 @@ function renderMetadataAction(label: string, url?: string) {
|
||||
}
|
||||
|
||||
function renderSubscriptionMetadata(
|
||||
metadata: Podkop.SubscriptionMetadata | undefined,
|
||||
metadata: Forkop.SubscriptionMetadata | undefined,
|
||||
) {
|
||||
if (!metadata || Object.keys(metadata).length <= 1) {
|
||||
return undefined;
|
||||
@@ -141,33 +141,33 @@ function renderSubscriptionMetadata(
|
||||
renderMetadataAction('More details', metadata.announceUrl),
|
||||
].filter(Boolean) as HTMLElement[];
|
||||
|
||||
return E('div', { class: 'pdk_dashboard-page__subscription-meta' }, [
|
||||
E('div', { class: 'pdk_dashboard-page__subscription-meta__main' }, [
|
||||
return E('div', { class: 'fkp_dashboard-page__subscription-meta' }, [
|
||||
E('div', { class: 'fkp_dashboard-page__subscription-meta__main' }, [
|
||||
E(
|
||||
'div',
|
||||
{ class: 'pdk_dashboard-page__subscription-meta__heading' },
|
||||
{ class: 'fkp_dashboard-page__subscription-meta__heading' },
|
||||
_('Subscription info:'),
|
||||
),
|
||||
title
|
||||
? E(
|
||||
'div',
|
||||
{ class: 'pdk_dashboard-page__subscription-meta__title' },
|
||||
{ class: 'fkp_dashboard-page__subscription-meta__title' },
|
||||
title,
|
||||
)
|
||||
: '',
|
||||
rows.length
|
||||
? E(
|
||||
'div',
|
||||
{ class: 'pdk_dashboard-page__subscription-meta__facts' },
|
||||
{ class: 'fkp_dashboard-page__subscription-meta__facts' },
|
||||
rows.map((row) =>
|
||||
E(
|
||||
'div',
|
||||
{ class: 'pdk_dashboard-page__subscription-meta__fact' },
|
||||
{ class: 'fkp_dashboard-page__subscription-meta__fact' },
|
||||
[
|
||||
E(
|
||||
'span',
|
||||
{
|
||||
class: 'pdk_dashboard-page__subscription-meta__fact-key',
|
||||
class: 'fkp_dashboard-page__subscription-meta__fact-key',
|
||||
},
|
||||
row.label,
|
||||
),
|
||||
@@ -175,7 +175,7 @@ function renderSubscriptionMetadata(
|
||||
'span',
|
||||
{
|
||||
class:
|
||||
'pdk_dashboard-page__subscription-meta__fact-value',
|
||||
'fkp_dashboard-page__subscription-meta__fact-value',
|
||||
},
|
||||
row.value,
|
||||
),
|
||||
@@ -187,7 +187,7 @@ function renderSubscriptionMetadata(
|
||||
actions.length
|
||||
? E(
|
||||
'div',
|
||||
{ class: 'pdk_dashboard-page__subscription-meta__actions' },
|
||||
{ class: 'fkp_dashboard-page__subscription-meta__actions' },
|
||||
actions,
|
||||
)
|
||||
: '',
|
||||
@@ -195,7 +195,7 @@ function renderSubscriptionMetadata(
|
||||
metadata.announce
|
||||
? E(
|
||||
'blockquote',
|
||||
{ class: 'pdk_dashboard-page__subscription-meta__announce' },
|
||||
{ class: 'fkp_dashboard-page__subscription-meta__announce' },
|
||||
metadata.announce,
|
||||
)
|
||||
: '',
|
||||
@@ -203,9 +203,9 @@ function renderSubscriptionMetadata(
|
||||
}
|
||||
|
||||
function renderSubscriptionUpdateAction(
|
||||
section: Podkop.OutboundGroup,
|
||||
section: Forkop.OutboundGroup,
|
||||
subscriptionUpdating: boolean,
|
||||
onUpdateSubscription: (section: Podkop.OutboundGroup) => void,
|
||||
onUpdateSubscription: (section: Forkop.OutboundGroup) => void,
|
||||
) {
|
||||
if (!section.subscriptionSourceCount) {
|
||||
return undefined;
|
||||
@@ -215,7 +215,7 @@ function renderSubscriptionUpdateAction(
|
||||
'button',
|
||||
{
|
||||
type: 'button',
|
||||
class: 'btn pdk_dashboard-page__outbound-section__subscription-update',
|
||||
class: 'btn fkp_dashboard-page__outbound-section__subscription-update',
|
||||
'aria-label': _('Update subscriptions'),
|
||||
disabled: subscriptionUpdating ? true : undefined,
|
||||
click: (event: MouseEvent) => {
|
||||
@@ -235,7 +235,7 @@ function renderSubscriptionUpdateAction(
|
||||
}
|
||||
|
||||
export function getLatencyTestLabel(
|
||||
latencyProgress?: Podkop.LatencyActionProgress,
|
||||
latencyProgress?: Forkop.LatencyActionProgress,
|
||||
) {
|
||||
const total = Math.trunc(Number(latencyProgress?.total ?? 0));
|
||||
if (!Number.isFinite(total) || total <= 0) {
|
||||
@@ -280,21 +280,21 @@ function renderDefaultState({
|
||||
}
|
||||
}
|
||||
|
||||
function renderOutbound(outbound: Podkop.Outbound) {
|
||||
function renderOutbound(outbound: Forkop.Outbound) {
|
||||
function getLatencyClass() {
|
||||
if (!outbound.latency) {
|
||||
return 'pdk_dashboard-page__outbound-grid__item__latency--empty';
|
||||
return 'fkp_dashboard-page__outbound-grid__item__latency--empty';
|
||||
}
|
||||
|
||||
if (outbound.latency < 800) {
|
||||
return 'pdk_dashboard-page__outbound-grid__item__latency--green';
|
||||
return 'fkp_dashboard-page__outbound-grid__item__latency--green';
|
||||
}
|
||||
|
||||
if (outbound.latency < 1500) {
|
||||
return 'pdk_dashboard-page__outbound-grid__item__latency--yellow';
|
||||
return 'fkp_dashboard-page__outbound-grid__item__latency--yellow';
|
||||
}
|
||||
|
||||
return 'pdk_dashboard-page__outbound-grid__item__latency--red';
|
||||
return 'fkp_dashboard-page__outbound-grid__item__latency--red';
|
||||
}
|
||||
|
||||
const canCopyLink =
|
||||
@@ -307,18 +307,18 @@ function renderDefaultState({
|
||||
!selectorSwitching &&
|
||||
!outbound.selected;
|
||||
const className = [
|
||||
'pdk_dashboard-page__outbound-grid__item',
|
||||
'fkp_dashboard-page__outbound-grid__item',
|
||||
outbound.selected
|
||||
? 'pdk_dashboard-page__outbound-grid__item--active'
|
||||
? 'fkp_dashboard-page__outbound-grid__item--active'
|
||||
: '',
|
||||
canChooseOutbound
|
||||
? 'pdk_dashboard-page__outbound-grid__item--selectable'
|
||||
? 'fkp_dashboard-page__outbound-grid__item--selectable'
|
||||
: '',
|
||||
section.withTagSelect && !canChooseOutbound
|
||||
? 'pdk_dashboard-page__outbound-grid__item--disabled'
|
||||
? 'fkp_dashboard-page__outbound-grid__item--disabled'
|
||||
: '',
|
||||
outboundSwitching
|
||||
? 'pdk_dashboard-page__outbound-grid__item--switching'
|
||||
? 'fkp_dashboard-page__outbound-grid__item--switching'
|
||||
: '',
|
||||
]
|
||||
.filter(Boolean)
|
||||
@@ -339,7 +339,7 @@ function renderDefaultState({
|
||||
? [
|
||||
svgEl(
|
||||
'svg',
|
||||
{ class: 'pdk_dashboard-page__outbound-grid__item__snake' },
|
||||
{ class: 'fkp_dashboard-page__outbound-grid__item__snake' },
|
||||
[
|
||||
svgEl('rect', {
|
||||
width: '100%',
|
||||
@@ -353,7 +353,7 @@ function renderDefaultState({
|
||||
),
|
||||
]
|
||||
: []),
|
||||
E('div', { class: 'pdk_dashboard-page__outbound-grid__item__header' }, [
|
||||
E('div', { class: 'fkp_dashboard-page__outbound-grid__item__header' }, [
|
||||
E('b', {}, outbound.displayName),
|
||||
...(canCopyLink
|
||||
? [
|
||||
@@ -362,7 +362,7 @@ function renderDefaultState({
|
||||
{
|
||||
type: 'button',
|
||||
class:
|
||||
'btn pdk_dashboard-page__outbound-grid__item__copy-button',
|
||||
'btn fkp_dashboard-page__outbound-grid__item__copy-button',
|
||||
title: _('Copy proxy link'),
|
||||
'aria-label': _('Copy proxy link'),
|
||||
click: (event: MouseEvent) => {
|
||||
@@ -381,7 +381,7 @@ function renderDefaultState({
|
||||
{
|
||||
type: 'button',
|
||||
class:
|
||||
'btn pdk_dashboard-page__outbound-grid__item__copy-button',
|
||||
'btn fkp_dashboard-page__outbound-grid__item__copy-button',
|
||||
title: _('URLTest details'),
|
||||
'aria-label': _('URLTest details'),
|
||||
click: (event: MouseEvent) => {
|
||||
@@ -400,7 +400,7 @@ function renderDefaultState({
|
||||
{
|
||||
type: 'button',
|
||||
class:
|
||||
'btn pdk_dashboard-page__outbound-grid__item__copy-button',
|
||||
'btn fkp_dashboard-page__outbound-grid__item__copy-button',
|
||||
title: _('Priority details'),
|
||||
'aria-label': _('Priority details'),
|
||||
click: (event: MouseEvent) => {
|
||||
@@ -413,10 +413,10 @@ function renderDefaultState({
|
||||
]
|
||||
: []),
|
||||
]),
|
||||
E('div', { class: 'pdk_dashboard-page__outbound-grid__item__footer' }, [
|
||||
E('div', { class: 'fkp_dashboard-page__outbound-grid__item__footer' }, [
|
||||
E(
|
||||
'div',
|
||||
{ class: 'pdk_dashboard-page__outbound-grid__item__type' },
|
||||
{ class: 'fkp_dashboard-page__outbound-grid__item__type' },
|
||||
[outbound.type].filter(Boolean),
|
||||
),
|
||||
E(
|
||||
@@ -438,20 +438,20 @@ function renderDefaultState({
|
||||
onUpdateSubscription,
|
||||
);
|
||||
|
||||
return E('div', { class: 'pdk_dashboard-page__outbound-section' }, [
|
||||
return E('div', { class: 'fkp_dashboard-page__outbound-section' }, [
|
||||
// Title with test latency
|
||||
E('div', { class: 'pdk_dashboard-page__outbound-section__title-section' }, [
|
||||
E('div', { class: 'fkp_dashboard-page__outbound-section__title-section' }, [
|
||||
E(
|
||||
'div',
|
||||
{
|
||||
class: 'pdk_dashboard-page__outbound-section__title-section__title',
|
||||
class: 'fkp_dashboard-page__outbound-section__title-section__title',
|
||||
},
|
||||
section.displayName,
|
||||
),
|
||||
E(
|
||||
'div',
|
||||
{
|
||||
class: 'pdk_dashboard-page__outbound-section__title-section__actions',
|
||||
class: 'fkp_dashboard-page__outbound-section__title-section__actions',
|
||||
},
|
||||
[
|
||||
...(subscriptionUpdateAction ? [subscriptionUpdateAction] : []),
|
||||
@@ -494,7 +494,7 @@ function renderDefaultState({
|
||||
],
|
||||
),
|
||||
]),
|
||||
E('div', { class: 'pdk_dashboard-page__outbound-grid' }, [
|
||||
E('div', { class: 'fkp_dashboard-page__outbound-grid' }, [
|
||||
...metadataNodes,
|
||||
...section.outbounds.map((outbound) => renderOutbound(outbound)),
|
||||
]),
|
||||
+7
-7
@@ -17,7 +17,7 @@ function renderFailedState() {
|
||||
{
|
||||
id: '',
|
||||
style: 'height: 78px',
|
||||
class: 'pdk_dashboard-page__widgets-section__item centered',
|
||||
class: 'fkp_dashboard-page__widgets-section__item centered',
|
||||
},
|
||||
_('Currently unavailable'),
|
||||
);
|
||||
@@ -29,34 +29,34 @@ function renderLoadingState() {
|
||||
{
|
||||
id: '',
|
||||
style: 'height: 78px',
|
||||
class: 'pdk_dashboard-page__widgets-section__item skeleton',
|
||||
class: 'fkp_dashboard-page__widgets-section__item skeleton',
|
||||
},
|
||||
'',
|
||||
);
|
||||
}
|
||||
|
||||
function renderDefaultState({ title, items }: IRenderWidgetProps) {
|
||||
return E('div', { class: 'pdk_dashboard-page__widgets-section__item' }, [
|
||||
return E('div', { class: 'fkp_dashboard-page__widgets-section__item' }, [
|
||||
E(
|
||||
'b',
|
||||
{ class: 'pdk_dashboard-page__widgets-section__item__title' },
|
||||
{ class: 'fkp_dashboard-page__widgets-section__item__title' },
|
||||
title,
|
||||
),
|
||||
...items.map((item) =>
|
||||
E(
|
||||
'div',
|
||||
{
|
||||
class: `pdk_dashboard-page__widgets-section__item__row ${item?.attributes?.class || ''}`,
|
||||
class: `fkp_dashboard-page__widgets-section__item__row ${item?.attributes?.class || ''}`,
|
||||
},
|
||||
[
|
||||
E(
|
||||
'span',
|
||||
{ class: 'pdk_dashboard-page__widgets-section__item__row__key' },
|
||||
{ class: 'fkp_dashboard-page__widgets-section__item__row__key' },
|
||||
`${item.key}: `,
|
||||
),
|
||||
E(
|
||||
'span',
|
||||
{ class: 'pdk_dashboard-page__widgets-section__item__row__value' },
|
||||
{ class: 'fkp_dashboard-page__widgets-section__item__row__value' },
|
||||
item.value,
|
||||
),
|
||||
],
|
||||
+5
-5
@@ -5,22 +5,22 @@ export function render() {
|
||||
'div',
|
||||
{
|
||||
id: 'dashboard-status',
|
||||
class: 'pdk_dashboard-page',
|
||||
class: 'fkp_dashboard-page',
|
||||
},
|
||||
[
|
||||
E(
|
||||
'div',
|
||||
{
|
||||
class: 'pdk_dashboard-page__service-stopped',
|
||||
class: 'fkp_dashboard-page__service-stopped',
|
||||
role: 'status',
|
||||
},
|
||||
_(
|
||||
'Podkop Plus service is stopped. Start the service to display the dashboard.',
|
||||
'Forkop service is stopped. Start the service to display the dashboard.',
|
||||
),
|
||||
),
|
||||
E('div', { class: 'pdk_dashboard-page__content' }, [
|
||||
E('div', { class: 'fkp_dashboard-page__content' }, [
|
||||
// Widgets section
|
||||
E('div', { class: 'pdk_dashboard-page__widgets-section' }, [
|
||||
E('div', { class: 'fkp_dashboard-page__widgets-section' }, [
|
||||
E(
|
||||
'div',
|
||||
{ id: 'dashboard-widget-traffic' },
|
||||
+105
-105
@@ -1,31 +1,31 @@
|
||||
// language=CSS
|
||||
import { PODKOP_UCI_PACKAGE as PODKOP_CBI_PREFIX } from '../../../constants';
|
||||
import { FORKOP_UCI_PACKAGE as FORKOP_CBI_PREFIX } from '../../../constants';
|
||||
|
||||
export const styles = `
|
||||
#cbi-${PODKOP_CBI_PREFIX}-dashboard-_mount_node > .cbi-value-title {
|
||||
#cbi-${FORKOP_CBI_PREFIX}-dashboard-_mount_node > .cbi-value-title {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#cbi-${PODKOP_CBI_PREFIX}-dashboard-_mount_node > .cbi-value-field {
|
||||
#cbi-${FORKOP_CBI_PREFIX}-dashboard-_mount_node > .cbi-value-field {
|
||||
margin-left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#cbi-${PODKOP_CBI_PREFIX}-dashboard-_mount_node > div {
|
||||
#cbi-${FORKOP_CBI_PREFIX}-dashboard-_mount_node > div {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#cbi-${PODKOP_CBI_PREFIX}-dashboard > h3 {
|
||||
#cbi-${FORKOP_CBI_PREFIX}-dashboard > h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page {
|
||||
.fkp_dashboard-page {
|
||||
width: 100%;
|
||||
--dashboard-grid-columns: 4;
|
||||
--dashboard-grid-min-width: 180px;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__service-stopped {
|
||||
.fkp_dashboard-page__service-stopped {
|
||||
display: none;
|
||||
width: 100%;
|
||||
min-height: 180px;
|
||||
@@ -46,72 +46,72 @@ export const styles = `
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page--service-stopped {
|
||||
.fkp_dashboard-page--service-stopped {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--dashboard-grid-columns), minmax(var(--dashboard-grid-min-width), 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page--service-stopped .pdk_dashboard-page__service-stopped {
|
||||
.fkp_dashboard-page--service-stopped .fkp_dashboard-page__service-stopped {
|
||||
display: flex;
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page--service-stopped .pdk_dashboard-page__content {
|
||||
.fkp_dashboard-page--service-stopped .fkp_dashboard-page__content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.pdk_dashboard-page {
|
||||
.fkp_dashboard-page {
|
||||
--dashboard-grid-columns: 2;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 560px) {
|
||||
.pdk_dashboard-page {
|
||||
.fkp_dashboard-page {
|
||||
--dashboard-grid-columns: 1;
|
||||
--dashboard-grid-min-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__widgets-section {
|
||||
.fkp_dashboard-page__widgets-section {
|
||||
margin-top: 10px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--dashboard-grid-columns), minmax(var(--dashboard-grid-min-width), 1fr));
|
||||
grid-gap: 10px;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__widgets-section__item {
|
||||
.fkp_dashboard-page__widgets-section__item {
|
||||
border: 2px var(--background-color-low, lightgray) solid;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__widgets-section__item__title {}
|
||||
.fkp_dashboard-page__widgets-section__item__title {}
|
||||
|
||||
.pdk_dashboard-page__widgets-section__item__row {}
|
||||
.fkp_dashboard-page__widgets-section__item__row {}
|
||||
|
||||
.pdk_dashboard-page__widgets-section__item__row--success .pdk_dashboard-page__widgets-section__item__row__value {
|
||||
.fkp_dashboard-page__widgets-section__item__row--success .fkp_dashboard-page__widgets-section__item__row__value {
|
||||
color: var(--success-color-medium, green);
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__widgets-section__item__row--error .pdk_dashboard-page__widgets-section__item__row__value {
|
||||
.fkp_dashboard-page__widgets-section__item__row--error .fkp_dashboard-page__widgets-section__item__row__value {
|
||||
color: var(--error-color-medium, red);
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__widgets-section__item__row__key {}
|
||||
.fkp_dashboard-page__widgets-section__item__row__key {}
|
||||
|
||||
.pdk_dashboard-page__widgets-section__item__row__value {}
|
||||
.fkp_dashboard-page__widgets-section__item__row__value {}
|
||||
|
||||
.pdk_dashboard-page__outbound-section {
|
||||
.fkp_dashboard-page__outbound-section {
|
||||
margin-top: 10px;
|
||||
border: 2px var(--background-color-low, lightgray) solid;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-section__title-section {
|
||||
.fkp_dashboard-page__outbound-section__title-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
@@ -119,14 +119,14 @@ export const styles = `
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-section__title-section__title {
|
||||
.fkp_dashboard-page__outbound-section__title-section__title {
|
||||
color: var(--text-color-high);
|
||||
font-weight: 700;
|
||||
min-width: 0;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-section__title-section__actions {
|
||||
.fkp_dashboard-page__outbound-section__title-section__actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
@@ -134,7 +134,7 @@ export const styles = `
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page .btn.pdk_dashboard-page__outbound-section__subscription-update {
|
||||
.fkp_dashboard-page .btn.fkp_dashboard-page__outbound-section__subscription-update {
|
||||
min-width: 130px;
|
||||
min-height: 28px;
|
||||
display: inline-flex;
|
||||
@@ -143,19 +143,19 @@ export const styles = `
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-section__subscription-update svg {
|
||||
.fkp_dashboard-page__outbound-section__subscription-update svg {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
display: block;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-section__subscription-update[disabled] {
|
||||
.fkp_dashboard-page__outbound-section__subscription-update[disabled] {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.65;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page .btn.dashboard-sections-grid-item-test-latency {
|
||||
.fkp_dashboard-page .btn.dashboard-sections-grid-item-test-latency {
|
||||
min-width: 99px;
|
||||
min-height: 28px;
|
||||
display: inline-flex;
|
||||
@@ -164,26 +164,26 @@ export const styles = `
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page .btn.dashboard-sections-grid-item-test-latency svg {
|
||||
.fkp_dashboard-page .btn.dashboard-sections-grid-item-test-latency svg {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
display: block;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page .btn.dashboard-sections-grid-item-test-latency[disabled] {
|
||||
.fkp_dashboard-page .btn.dashboard-sections-grid-item-test-latency[disabled] {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.65;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-grid {
|
||||
.fkp_dashboard-page__outbound-grid {
|
||||
margin-top: 5px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--dashboard-grid-columns), minmax(var(--dashboard-grid-min-width), 1fr));
|
||||
grid-gap: 10px;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__subscription-meta {
|
||||
.fkp_dashboard-page__subscription-meta {
|
||||
--subscription-meta-action-size: 28px;
|
||||
--subscription-meta-action-gap: 6px;
|
||||
grid-column: 1 / -1;
|
||||
@@ -193,14 +193,14 @@ export const styles = `
|
||||
background: var(--background-color-high, transparent);
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__subscription-meta__main {
|
||||
.fkp_dashboard-page__subscription-meta__main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px 10px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__subscription-meta__heading {
|
||||
.fkp_dashboard-page__subscription-meta__heading {
|
||||
flex: 0 0 auto;
|
||||
color: var(--text-color-high);
|
||||
font-weight: 700;
|
||||
@@ -208,7 +208,7 @@ export const styles = `
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__subscription-meta__title {
|
||||
.fkp_dashboard-page__subscription-meta__title {
|
||||
flex: 0 1 auto;
|
||||
width: max-content;
|
||||
max-width: min(28ch, 30%);
|
||||
@@ -219,7 +219,7 @@ export const styles = `
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__subscription-meta__facts {
|
||||
.fkp_dashboard-page__subscription-meta__facts {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
@@ -228,7 +228,7 @@ export const styles = `
|
||||
gap: 5px 12px;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__subscription-meta__fact {
|
||||
.fkp_dashboard-page__subscription-meta__fact {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 4px;
|
||||
@@ -236,19 +236,19 @@ export const styles = `
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__subscription-meta__fact-key {
|
||||
.fkp_dashboard-page__subscription-meta__fact-key {
|
||||
color: var(--text-color-medium);
|
||||
font-size: 12px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__subscription-meta__fact-value {
|
||||
.fkp_dashboard-page__subscription-meta__fact-value {
|
||||
color: var(--text-color-high);
|
||||
font-weight: 600;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__subscription-meta__actions {
|
||||
.fkp_dashboard-page__subscription-meta__actions {
|
||||
flex: 0 0 auto;
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
@@ -256,7 +256,7 @@ export const styles = `
|
||||
gap: var(--subscription-meta-action-gap);
|
||||
}
|
||||
|
||||
.pdk_dashboard-page .btn.pdk_dashboard-page__subscription-meta__action {
|
||||
.fkp_dashboard-page .btn.fkp_dashboard-page__subscription-meta__action {
|
||||
width: var(--subscription-meta-action-size);
|
||||
height: var(--subscription-meta-action-size);
|
||||
min-width: var(--subscription-meta-action-size);
|
||||
@@ -271,14 +271,14 @@ export const styles = `
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__subscription-meta__action svg {
|
||||
.fkp_dashboard-page__subscription-meta__action svg {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
display: block;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__subscription-meta__announce {
|
||||
.fkp_dashboard-page__subscription-meta__announce {
|
||||
margin: 6px 0 0;
|
||||
border-left: 3px solid var(--primary-color-medium, dodgerblue);
|
||||
padding: 4px 8px;
|
||||
@@ -290,31 +290,31 @@ export const styles = `
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.pdk_dashboard-page__subscription-meta__main {
|
||||
.fkp_dashboard-page__subscription-meta__main {
|
||||
align-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__subscription-meta__heading,
|
||||
.pdk_dashboard-page__subscription-meta__title {
|
||||
.fkp_dashboard-page__subscription-meta__heading,
|
||||
.fkp_dashboard-page__subscription-meta__title {
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__subscription-meta__actions {
|
||||
.fkp_dashboard-page__subscription-meta__actions {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__subscription-meta__facts {
|
||||
.fkp_dashboard-page__subscription-meta__facts {
|
||||
order: 3;
|
||||
flex-basis: 100%;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__subscription-meta__title {
|
||||
.fkp_dashboard-page__subscription-meta__title {
|
||||
max-width: calc(100% - 42px);
|
||||
}
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-grid__item {
|
||||
.fkp_dashboard-page__outbound-grid__item {
|
||||
border: 2px var(--background-color-low, lightgray) solid;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
@@ -323,29 +323,29 @@ export const styles = `
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-grid__item--selectable {
|
||||
.fkp_dashboard-page__outbound-grid__item--selectable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-grid__item--selectable:hover {
|
||||
.fkp_dashboard-page__outbound-grid__item--selectable:hover {
|
||||
border-color: var(--primary-color-high, dodgerblue);
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-grid__item--active {
|
||||
.fkp_dashboard-page__outbound-grid__item--active {
|
||||
border-color: var(--success-color-medium, green);
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-grid__item--disabled {
|
||||
.fkp_dashboard-page__outbound-grid__item--disabled {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-grid__item--switching {
|
||||
.fkp_dashboard-page__outbound-grid__item--switching {
|
||||
border-color: transparent !important;
|
||||
overflow: hidden;
|
||||
cursor: wait;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-grid__item__snake {
|
||||
.fkp_dashboard-page__outbound-grid__item__snake {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
@@ -356,13 +356,13 @@ export const styles = `
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-grid__item__snake rect {
|
||||
.fkp_dashboard-page__outbound-grid__item__snake rect {
|
||||
stroke: var(--primary-color-high, dodgerblue);
|
||||
stroke-width: 4;
|
||||
animation: pdk-dashboard-selector-snake-svg 1.2s linear infinite;
|
||||
animation: fkp-dashboard-selector-snake-svg 1.2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes pdk-dashboard-selector-snake-svg {
|
||||
@keyframes fkp-dashboard-selector-snake-svg {
|
||||
0% {
|
||||
stroke-dasharray: 30 70;
|
||||
stroke-dashoffset: 100;
|
||||
@@ -373,20 +373,20 @@ export const styles = `
|
||||
}
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-grid__item__header {
|
||||
.fkp_dashboard-page__outbound-grid__item__header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-grid__item__header b {
|
||||
.fkp_dashboard-page__outbound-grid__item__header b {
|
||||
min-width: 0;
|
||||
line-height: 1.25;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page .btn.pdk_dashboard-page__outbound-grid__item__copy-button {
|
||||
.fkp_dashboard-page .btn.fkp_dashboard-page__outbound-grid__item__copy-button {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
min-width: 22px;
|
||||
@@ -400,14 +400,14 @@ export const styles = `
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-grid__item__copy-button svg {
|
||||
.fkp_dashboard-page__outbound-grid__item__copy-button svg {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
display: block;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-grid__item__footer {
|
||||
.fkp_dashboard-page__outbound-grid__item__footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
@@ -415,51 +415,51 @@ export const styles = `
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-grid__item__type {
|
||||
.fkp_dashboard-page__outbound-grid__item__type {
|
||||
min-width: 0;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-grid__item__latency--empty {
|
||||
.fkp_dashboard-page__outbound-grid__item__latency--empty {
|
||||
color: var(--primary-color-low, lightgray);
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-grid__item__latency--green {
|
||||
.fkp_dashboard-page__outbound-grid__item__latency--green {
|
||||
color: var(--success-color-medium, green);
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-grid__item__latency--yellow {
|
||||
.fkp_dashboard-page__outbound-grid__item__latency--yellow {
|
||||
color: var(--warn-color-medium, orange);
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__outbound-grid__item__latency--red {
|
||||
.fkp_dashboard-page__outbound-grid__item__latency--red {
|
||||
color: var(--error-color-medium, red);
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details {
|
||||
.fkp_dashboard-page__urltest-details {
|
||||
box-sizing: border-box;
|
||||
width: min(760px, calc(100vw - 56px));
|
||||
max-width: 100%;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__params {
|
||||
.fkp_dashboard-page__urltest-details__params {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(120px, max-content) minmax(0, 1fr);
|
||||
gap: 8px 16px;
|
||||
margin: 0 0 18px;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__param {
|
||||
.fkp_dashboard-page__urltest-details__param {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__param dt {
|
||||
.fkp_dashboard-page__urltest-details__param dt {
|
||||
color: var(--text-color-medium, #666);
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__param dd {
|
||||
.fkp_dashboard-page__urltest-details__param dd {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
@@ -467,23 +467,23 @@ export const styles = `
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__param dd span {
|
||||
.fkp_dashboard-page__urltest-details__param dd span {
|
||||
min-width: 0;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__url {
|
||||
.fkp_dashboard-page__urltest-details__url {
|
||||
min-width: 0;
|
||||
color: var(--primary-color-high, #337ab7);
|
||||
text-decoration: none;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__url:hover {
|
||||
.fkp_dashboard-page__urltest-details__url:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__selected-value {
|
||||
.fkp_dashboard-page__urltest-details__selected-value {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
@@ -497,22 +497,22 @@ export const styles = `
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__selected-name {
|
||||
.fkp_dashboard-page__urltest-details__selected-name {
|
||||
min-width: 0;
|
||||
font-weight: 600;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__selected-type {
|
||||
.fkp_dashboard-page__urltest-details__selected-type {
|
||||
color: var(--text-color-medium, #666);
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__outbounds-title {
|
||||
.fkp_dashboard-page__urltest-details__outbounds-title {
|
||||
margin-bottom: 8px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__table {
|
||||
.fkp_dashboard-page__urltest-details__table {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
width: calc(100% + 14px);
|
||||
@@ -524,7 +524,7 @@ export const styles = `
|
||||
scrollbar-gutter: auto;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__row {
|
||||
.fkp_dashboard-page__urltest-details__row {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) minmax(54px, max-content) 20px;
|
||||
align-items: center;
|
||||
@@ -538,13 +538,13 @@ export const styles = `
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__row--active {
|
||||
.fkp_dashboard-page__urltest-details__row--active {
|
||||
border-color: var(--success-color-low, #2d7d46);
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__row-name,
|
||||
.pdk_dashboard-page__urltest-details__row-meta {
|
||||
.fkp_dashboard-page__urltest-details__row-name,
|
||||
.fkp_dashboard-page__urltest-details__row-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
@@ -552,24 +552,24 @@ export const styles = `
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__row-name {
|
||||
.fkp_dashboard-page__urltest-details__row-name {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__row-name b {
|
||||
.fkp_dashboard-page__urltest-details__row-name b {
|
||||
min-width: 0;
|
||||
overflow-wrap: anywhere;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__priority-name {
|
||||
.fkp_dashboard-page__urltest-details__priority-name {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 2px 0;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__priority-number {
|
||||
.fkp_dashboard-page__urltest-details__priority-number {
|
||||
margin-right: 6px;
|
||||
color: var(--text-color-medium, #aaa);
|
||||
font-family: monospace;
|
||||
@@ -577,7 +577,7 @@ export const styles = `
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__priority-level {
|
||||
.fkp_dashboard-page__urltest-details__priority-level {
|
||||
margin-right: 8px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
@@ -587,7 +587,7 @@ export const styles = `
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__country-badge {
|
||||
.fkp_dashboard-page__urltest-details__country-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
user-select: none;
|
||||
@@ -599,27 +599,27 @@ export const styles = `
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__priority-node {
|
||||
.fkp_dashboard-page__urltest-details__priority-node {
|
||||
color: var(--text-color-high, #fff);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__row-type,
|
||||
.pdk_dashboard-page__urltest-details__row-meta {
|
||||
.fkp_dashboard-page__urltest-details__row-type,
|
||||
.fkp_dashboard-page__urltest-details__row-meta {
|
||||
color: var(--text-color-medium, #666);
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__row-type {
|
||||
.fkp_dashboard-page__urltest-details__row-type {
|
||||
white-space: nowrap;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__row-meta {
|
||||
.fkp_dashboard-page__urltest-details__row-meta {
|
||||
justify-content: flex-end;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__copy-button {
|
||||
.fkp_dashboard-page__urltest-details__copy-button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -631,19 +631,19 @@ export const styles = `
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__copy-button svg {
|
||||
.fkp_dashboard-page__urltest-details__copy-button svg {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__copy-placeholder {
|
||||
.fkp_dashboard-page__urltest-details__copy-placeholder {
|
||||
display: block;
|
||||
width: 20px;
|
||||
min-width: 20px;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__empty {
|
||||
.fkp_dashboard-page__urltest-details__empty {
|
||||
margin-top: 4px;
|
||||
padding: 24px 0;
|
||||
border: 1px dashed var(--border-color-high, #555);
|
||||
@@ -654,22 +654,22 @@ export const styles = `
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__footer {
|
||||
.fkp_dashboard-page__urltest-details__footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
@media (max-width: 560px) {
|
||||
.pdk_dashboard-page__urltest-details__params {
|
||||
.fkp_dashboard-page__urltest-details__params {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__row {
|
||||
.fkp_dashboard-page__urltest-details__row {
|
||||
grid-template-columns: minmax(0, 1fr) 20px;
|
||||
}
|
||||
|
||||
.pdk_dashboard-page__urltest-details__row-meta {
|
||||
.fkp_dashboard-page__urltest-details__row-meta {
|
||||
grid-column: 1 / -1;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
import type { Podkop } from '../../../types';
|
||||
import type { Forkop } from '../../../types';
|
||||
import { getMeta } from '../helpers/getMeta';
|
||||
|
||||
type DnsCheckState = 'error' | 'success' | 'warning';
|
||||
|
||||
export function getDnsCheckPresentation(data: Podkop.DnsCheckResult) {
|
||||
export function getDnsCheckPresentation(data: Forkop.DnsCheckResult) {
|
||||
const dhcpManagedManually = Boolean(data.dont_touch_dhcp);
|
||||
const dhcpCheckOk = dhcpManagedManually || Boolean(data.dhcp_config_status);
|
||||
|
||||
+11
-13
@@ -1,5 +1,5 @@
|
||||
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||
import { PodkopShellMethods } from '../../../methods';
|
||||
import { ForkopShellMethods } 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 PodkopShellMethods.getByedpiStatus();
|
||||
const byedpiStatus = await ForkopShellMethods.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 podkopRuntimeReady =
|
||||
const forkopRuntimeReady =
|
||||
!hasByedpiRules ||
|
||||
(runningProcesses === expectedProcesses &&
|
||||
supervisorProcesses === expectedProcesses);
|
||||
@@ -81,20 +81,20 @@ export async function runByedpiCheck() {
|
||||
},
|
||||
{
|
||||
state:
|
||||
unexpectedRuntime || !podkopRuntimeReady
|
||||
unexpectedRuntime || !forkopRuntimeReady
|
||||
? 'error'
|
||||
: runtimeUnstable
|
||||
? 'warning'
|
||||
: 'success',
|
||||
key: hasByedpiRules
|
||||
? runtimeUnstable
|
||||
? _('Podkop Plus-managed ciadpi runtime has restarted')
|
||||
: podkopRuntimeReady
|
||||
? _('Podkop Plus-managed ciadpi runtime is ready')
|
||||
: _('Podkop Plus-managed ciadpi runtime is not ready')
|
||||
? _('Forkop-managed ciadpi runtime has restarted')
|
||||
: forkopRuntimeReady
|
||||
? _('Forkop-managed ciadpi runtime is ready')
|
||||
: _('Forkop-managed ciadpi runtime is not ready')
|
||||
: unexpectedRuntime
|
||||
? _('Unexpected Podkop Plus-managed ciadpi runtime is running')
|
||||
: _('Podkop Plus-managed ciadpi runtime is not running'),
|
||||
? _('Unexpected Forkop-managed ciadpi runtime is running')
|
||||
: _('Forkop-managed ciadpi runtime is not running'),
|
||||
value: hasByedpiRules
|
||||
? runtimeUnstable
|
||||
? `${restartCount}`
|
||||
@@ -116,9 +116,7 @@ export async function runByedpiCheck() {
|
||||
: 'success',
|
||||
key: standaloneServiceRunning
|
||||
? hasByedpiRules
|
||||
? _(
|
||||
'Standalone ByeDPI is active together with Podkop Plus ByeDPI rules',
|
||||
)
|
||||
? _('Standalone ByeDPI is active together with Forkop ByeDPI rules')
|
||||
: _('Standalone ByeDPI service is active')
|
||||
: standaloneAutostartRisk
|
||||
? _('Standalone ByeDPI autostart is enabled')
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { insertIf } from '../../../../helpers';
|
||||
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||
import { PodkopShellMethods } from '../../../methods';
|
||||
import { ForkopShellMethods } 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 PodkopShellMethods.checkDNSAvailable();
|
||||
const dnsChecks = await ForkopShellMethods.checkDNSAvailable();
|
||||
|
||||
if (!dnsChecks.success) {
|
||||
updateCheckStore({
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { insertIf } from '../../../../helpers';
|
||||
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||
import { PodkopShellMethods, RemoteFakeIPMethods } from '../../../methods';
|
||||
import { ForkopShellMethods, 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 PodkopShellMethods.checkFakeIP();
|
||||
const routerFakeIPResponse = await ForkopShellMethods.checkFakeIP();
|
||||
const checkFakeIPResponse = await RemoteFakeIPMethods.getFakeIpCheck();
|
||||
const checkIPResponse = await RemoteFakeIPMethods.getIpCheck();
|
||||
const browserFakeIPCheckUnavailable = !checkFakeIPResponse.success;
|
||||
+8
-8
@@ -1,20 +1,20 @@
|
||||
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||
import { PodkopShellMethods } from '../../../methods';
|
||||
import { ForkopShellMethods } from '../../../methods';
|
||||
import { updateCheckStore } from './updateCheckStore';
|
||||
import { getMeta } from '../helpers/getMeta';
|
||||
import { IDiagnosticsChecksItem } from '../../../services';
|
||||
import { Podkop } from '../../../types';
|
||||
import { Forkop } from '../../../types';
|
||||
|
||||
function serverPrefix(item: Podkop.InboundCheckItem) {
|
||||
function serverPrefix(item: Forkop.InboundCheckItem) {
|
||||
return `${item.label}:`;
|
||||
}
|
||||
|
||||
function formatListen(item: Podkop.InboundCheckItem) {
|
||||
function formatListen(item: Forkop.InboundCheckItem) {
|
||||
return `${item.listen}:${Number(item.listen_port || 0)} [${item.required_proto}]`;
|
||||
}
|
||||
|
||||
function getPortConflictItem(
|
||||
item: Podkop.InboundCheckItem,
|
||||
item: Forkop.InboundCheckItem,
|
||||
): IDiagnosticsChecksItem {
|
||||
const key = `${serverPrefix(item)} ${_('Port conflict')}`;
|
||||
|
||||
@@ -34,7 +34,7 @@ function getPortConflictItem(
|
||||
}
|
||||
|
||||
function getPublicHostItem(
|
||||
item: Podkop.InboundCheckItem,
|
||||
item: Forkop.InboundCheckItem,
|
||||
wanIp: string,
|
||||
): IDiagnosticsChecksItem {
|
||||
const key = `${serverPrefix(item)} ${_('Public host')}`;
|
||||
@@ -79,7 +79,7 @@ function getPublicHostItem(
|
||||
}
|
||||
|
||||
function getServerItems(
|
||||
item: Podkop.InboundCheckItem,
|
||||
item: Forkop.InboundCheckItem,
|
||||
wanIp: string,
|
||||
): IDiagnosticsChecksItem[] {
|
||||
const prefix = serverPrefix(item);
|
||||
@@ -162,7 +162,7 @@ export async function runInboundsCheck() {
|
||||
items: [],
|
||||
});
|
||||
|
||||
const inboundsChecks = await PodkopShellMethods.checkInbounds();
|
||||
const inboundsChecks = await ForkopShellMethods.checkInbounds();
|
||||
|
||||
if (!inboundsChecks.success) {
|
||||
updateCheckStore({
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||
import { RemoteFakeIPMethods, PodkopShellMethods } from '../../../methods';
|
||||
import { RemoteFakeIPMethods, ForkopShellMethods } 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 PodkopShellMethods.checkNftRules();
|
||||
const nftablesChecks = await ForkopShellMethods.checkNftRules();
|
||||
|
||||
if (!nftablesChecks.success) {
|
||||
updateCheckStore({
|
||||
+6
-5
@@ -1,5 +1,5 @@
|
||||
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||
import { PodkopShellMethods } from '../../../methods';
|
||||
import { ForkopShellMethods } 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 PodkopShellMethods.getClashApiProxyLatency(
|
||||
const latencyProxy = await ForkopShellMethods.getClashApiProxyLatency(
|
||||
selectedOutbound.code,
|
||||
section.latencyTestTimeout,
|
||||
);
|
||||
@@ -91,8 +91,9 @@ export async function runSectionsCheck() {
|
||||
};
|
||||
}
|
||||
|
||||
const latencyGroup =
|
||||
await PodkopShellMethods.getClashApiGroupLatency(section.code);
|
||||
const latencyGroup = await ForkopShellMethods.getClashApiGroupLatency(
|
||||
section.code,
|
||||
);
|
||||
const success = latencyGroup.success && !latencyGroup.data.message;
|
||||
|
||||
if (success) {
|
||||
@@ -124,7 +125,7 @@ export async function runSectionsCheck() {
|
||||
}
|
||||
|
||||
const selectedOutbound = section.outbounds[0];
|
||||
const latencyProxy = await PodkopShellMethods.getClashApiProxyLatency(
|
||||
const latencyProxy = await ForkopShellMethods.getClashApiProxyLatency(
|
||||
section.code,
|
||||
section.latencyTestTimeout,
|
||||
);
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||
import { PodkopShellMethods } from '../../../methods';
|
||||
import { ForkopShellMethods } from '../../../methods';
|
||||
import { updateCheckStore } from './updateCheckStore';
|
||||
import { getMeta } from '../helpers/getMeta';
|
||||
|
||||
@@ -15,7 +15,7 @@ export async function runSingBoxCheck() {
|
||||
items: [],
|
||||
});
|
||||
|
||||
const singBoxChecks = await PodkopShellMethods.checkSingBox();
|
||||
const singBoxChecks = await ForkopShellMethods.checkSingBox();
|
||||
|
||||
if (!singBoxChecks.success) {
|
||||
updateCheckStore({
|
||||
+10
-12
@@ -1,5 +1,5 @@
|
||||
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||
import { PodkopShellMethods } from '../../../methods';
|
||||
import { ForkopShellMethods } 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 PodkopShellMethods.getZapret2Status();
|
||||
const zapret2Status = await ForkopShellMethods.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 podkopRuntimeReady =
|
||||
const forkopRuntimeReady =
|
||||
!hasZapret2Rules ||
|
||||
(runningProcesses === expectedProcesses &&
|
||||
supervisorProcesses === expectedProcesses);
|
||||
@@ -83,14 +83,14 @@ export async function runZapret2Check() {
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
state: unexpectedRuntime || !podkopRuntimeReady ? 'error' : 'success',
|
||||
state: unexpectedRuntime || !forkopRuntimeReady ? 'error' : 'success',
|
||||
key: hasZapret2Rules
|
||||
? podkopRuntimeReady
|
||||
? _('Podkop Plus-managed nfqws2 runtime is ready')
|
||||
: _('Podkop Plus-managed nfqws2 runtime is not ready')
|
||||
? forkopRuntimeReady
|
||||
? _('Forkop-managed nfqws2 runtime is ready')
|
||||
: _('Forkop-managed nfqws2 runtime is not ready')
|
||||
: unexpectedRuntime
|
||||
? _('Unexpected Podkop Plus-managed nfqws2 runtime is running')
|
||||
: _('Podkop Plus-managed nfqws2 runtime is not running'),
|
||||
? _('Unexpected Forkop-managed nfqws2 runtime is running')
|
||||
: _('Forkop-managed nfqws2 runtime is not running'),
|
||||
value: hasZapret2Rules ? `${runningProcesses}/${expectedProcesses}` : '',
|
||||
},
|
||||
{
|
||||
@@ -115,9 +115,7 @@ export async function runZapret2Check() {
|
||||
: 'success',
|
||||
key: standaloneServiceRunning
|
||||
? hasZapret2Rules
|
||||
? _(
|
||||
'Standalone Zapret2 is active together with Podkop Plus Zapret2 rules',
|
||||
)
|
||||
? _('Standalone Zapret2 is active together with Forkop Zapret2 rules')
|
||||
: _('Standalone Zapret2 service is active')
|
||||
: standaloneAutostartRisk
|
||||
? _('Standalone Zapret2 autostart is enabled')
|
||||
+10
-12
@@ -1,5 +1,5 @@
|
||||
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||
import { PodkopShellMethods } from '../../../methods';
|
||||
import { ForkopShellMethods } 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 PodkopShellMethods.getZapretStatus();
|
||||
const zapretStatus = await ForkopShellMethods.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 podkopRuntimeReady =
|
||||
const forkopRuntimeReady =
|
||||
!hasZapretRules ||
|
||||
(runningProcesses === expectedProcesses &&
|
||||
supervisorProcesses === expectedProcesses);
|
||||
@@ -80,14 +80,14 @@ export async function runZapretCheck() {
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
state: unexpectedRuntime || !podkopRuntimeReady ? 'error' : 'success',
|
||||
state: unexpectedRuntime || !forkopRuntimeReady ? 'error' : 'success',
|
||||
key: hasZapretRules
|
||||
? podkopRuntimeReady
|
||||
? _('Podkop Plus-managed nfqws runtime is ready')
|
||||
: _('Podkop Plus-managed nfqws runtime is not ready')
|
||||
? forkopRuntimeReady
|
||||
? _('Forkop-managed nfqws runtime is ready')
|
||||
: _('Forkop-managed nfqws runtime is not ready')
|
||||
: unexpectedRuntime
|
||||
? _('Unexpected Podkop Plus-managed nfqws runtime is running')
|
||||
: _('Podkop Plus-managed nfqws runtime is not running'),
|
||||
? _('Unexpected Forkop-managed nfqws runtime is running')
|
||||
: _('Forkop-managed nfqws runtime is not running'),
|
||||
value: hasZapretRules ? `${runningProcesses}/${expectedProcesses}` : '',
|
||||
},
|
||||
{
|
||||
@@ -108,9 +108,7 @@ export async function runZapretCheck() {
|
||||
state: standaloneConflict ? 'warning' : 'success',
|
||||
key: standaloneServiceRunning
|
||||
? hasZapretRules
|
||||
? _(
|
||||
'Standalone Zapret is active together with Podkop Plus Zapret rules',
|
||||
)
|
||||
? _('Standalone Zapret is active together with Forkop Zapret rules')
|
||||
: _('Standalone Zapret service is active')
|
||||
: _('Standalone Zapret service is inactive'),
|
||||
value: '',
|
||||
+1
-1
@@ -8,7 +8,7 @@ const mocks = vi.hoisted(() => ({
|
||||
}));
|
||||
|
||||
vi.mock('../../../../methods', () => ({
|
||||
PodkopShellMethods: {
|
||||
ForkopShellMethods: {
|
||||
getZapretStatus: mocks.getZapretStatus,
|
||||
getZapret2Status: mocks.getZapret2Status,
|
||||
getByedpiStatus: mocks.getByedpiStatus,
|
||||
+1
-1
@@ -12,7 +12,7 @@ vi.mock('../../../../methods/custom/getDashboardSections', () => ({
|
||||
}));
|
||||
|
||||
vi.mock('../../../../methods', () => ({
|
||||
PodkopShellMethods: {
|
||||
ForkopShellMethods: {
|
||||
getClashApiProxyLatency: mocks.getClashApiProxyLatency,
|
||||
getClashApiGroupLatency: mocks.getClashApiGroupLatency,
|
||||
},
|
||||
+5
-5
@@ -77,8 +77,8 @@ export const initialDiagnosticStore: Pick<
|
||||
loading: true,
|
||||
loaded: false,
|
||||
providerInfoLoaded: false,
|
||||
podkop_version: 'loading',
|
||||
podkop_latest_version: 'loading',
|
||||
forkop_version: 'loading',
|
||||
forkop_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: {
|
||||
podkopCheck: { loading: false },
|
||||
podkopInstall: { loading: false },
|
||||
forkopCheck: { loading: false },
|
||||
forkopInstall: { loading: false },
|
||||
singBoxCheck: { loading: false },
|
||||
singBoxInstall: { loading: false },
|
||||
singBoxInstallExtended: { loading: false },
|
||||
@@ -143,7 +143,7 @@ export const initialDiagnosticStore: Pick<
|
||||
byedpiRemove: { loading: false },
|
||||
},
|
||||
updatesChecks: {
|
||||
podkop: { status: null, latest_version: '', release_url: '' },
|
||||
forkop: { 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: '' },
|
||||
+1
-1
@@ -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 = 'podkop-plus:diagnostic-run:v1';
|
||||
const DIAGNOSTIC_RUN_STORAGE_KEY = 'forkop: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'];
|
||||
+4
-4
@@ -28,7 +28,7 @@ const SING_BOX_MASKED_KEYS = new Set([
|
||||
'source_ip_cidr',
|
||||
]);
|
||||
|
||||
const PODKOP_MASK_AFTER_TOKEN = [
|
||||
const FORKOP_MASK_AFTER_TOKEN = [
|
||||
'option proxy_string',
|
||||
'option subscription_url',
|
||||
'list subscription_urls',
|
||||
@@ -47,7 +47,7 @@ const PODKOP_MASK_AFTER_TOKEN = [
|
||||
'option yacd_secret_key',
|
||||
];
|
||||
|
||||
const PODKOP_MASK_AFTER_TOKEN_SPACE = [
|
||||
const FORKOP_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 PODKOP_MASK_AFTER_TOKEN) {
|
||||
for (const token of FORKOP_MASK_AFTER_TOKEN) {
|
||||
maskedLine = maskAfterToken(maskedLine, token);
|
||||
}
|
||||
|
||||
for (const token of PODKOP_MASK_AFTER_TOKEN_SPACE) {
|
||||
for (const token of FORKOP_MASK_AFTER_TOKEN_SPACE) {
|
||||
maskedLine = maskAfterTokenSpace(maskedLine, token);
|
||||
}
|
||||
|
||||
+52
-52
@@ -32,14 +32,14 @@ import {
|
||||
renderRunAction,
|
||||
renderSystemInfo,
|
||||
} from './partials';
|
||||
import { PodkopShellMethods } from '../../methods';
|
||||
import { ForkopShellMethods } from '../../methods';
|
||||
import { fetchServicesInfo } from '../../fetchers/fetchServicesInfo';
|
||||
import { normalizeCompiledVersion } from '../../../helpers/normalizeCompiledVersion';
|
||||
import { renderModal } from '../../../partials';
|
||||
import { PODKOP_LUCI_APP_VERSION } from '../../../constants';
|
||||
import { FORKOP_LUCI_APP_VERSION } from '../../../constants';
|
||||
import { renderWikiDisclaimer } from './partials/renderWikiDisclaimer';
|
||||
import { runSectionsCheck } from './checks/runSectionsCheck';
|
||||
import { Podkop } from '../../types';
|
||||
import { Forkop } from '../../types';
|
||||
import {
|
||||
getAvailableActionsDisabledState,
|
||||
getServiceTransition,
|
||||
@@ -156,11 +156,11 @@ function isLocalMutatingServiceActionLoading() {
|
||||
function isMutatingServiceActionLoading() {
|
||||
return (
|
||||
isLocalMutatingServiceActionLoading() ||
|
||||
isServiceTransitionStatus(store.get().servicesInfoWidget.data.podkopStatus)
|
||||
isServiceTransitionStatus(store.get().servicesInfoWidget.data.forkopStatus)
|
||||
);
|
||||
}
|
||||
|
||||
function getPodkopStatusText(running: boolean, enabled: boolean) {
|
||||
function getForkopStatusText(running: boolean, enabled: boolean) {
|
||||
if (running) {
|
||||
return enabled ? 'running & enabled' : 'running but disabled';
|
||||
}
|
||||
@@ -168,9 +168,9 @@ function getPodkopStatusText(running: boolean, enabled: boolean) {
|
||||
return enabled ? 'stopped but enabled' : 'stopped & disabled';
|
||||
}
|
||||
|
||||
function setDisplayedPodkopRunning(running: boolean) {
|
||||
function setDisplayedForkopRunning(running: boolean) {
|
||||
const servicesInfoWidget = store.get().servicesInfoWidget;
|
||||
const enabled = Boolean(servicesInfoWidget.data.podkopEnabled);
|
||||
const enabled = Boolean(servicesInfoWidget.data.forkopEnabled);
|
||||
|
||||
store.set({
|
||||
servicesInfoWidget: {
|
||||
@@ -178,8 +178,8 @@ function setDisplayedPodkopRunning(running: boolean) {
|
||||
loading: false,
|
||||
data: {
|
||||
...servicesInfoWidget.data,
|
||||
podkopRunning: running ? 1 : 0,
|
||||
podkopStatus: getPodkopStatusText(running, enabled),
|
||||
forkopRunning: running ? 1 : 0,
|
||||
forkopStatus: getForkopStatusText(running, enabled),
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -232,17 +232,17 @@ async function refreshDiagnosticServicesInfo({
|
||||
return promise;
|
||||
}
|
||||
|
||||
async function waitForPodkopRunningState(expectedRunning: boolean) {
|
||||
async function waitForForkopRunningState(expectedRunning: boolean) {
|
||||
const startedAt = Date.now();
|
||||
|
||||
while (Date.now() - startedAt < SERVICE_ACTION_STATUS_TIMEOUT_MS) {
|
||||
await refreshDiagnosticServicesInfo({ force: true, allowInactive: true });
|
||||
|
||||
const podkopRunning = Boolean(
|
||||
store.get().servicesInfoWidget.data.podkopRunning,
|
||||
const forkopRunning = Boolean(
|
||||
store.get().servicesInfoWidget.data.forkopRunning,
|
||||
);
|
||||
|
||||
if (podkopRunning === expectedRunning) {
|
||||
if (forkopRunning === expectedRunning) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -274,13 +274,13 @@ function stopServiceActionStateWatcher() {
|
||||
}
|
||||
|
||||
function isVisibleServiceRuntimeAction(
|
||||
action: Podkop.ServiceActionState['action'],
|
||||
action: Forkop.ServiceActionState['action'],
|
||||
): action is ServiceRuntimeAction {
|
||||
return action === 'restart' || action === 'start' || action === 'stop';
|
||||
}
|
||||
|
||||
function setServiceActionStateLoading(
|
||||
state: Podkop.ServiceActionState,
|
||||
state: Forkop.ServiceActionState,
|
||||
loading: boolean,
|
||||
) {
|
||||
if (!isVisibleServiceRuntimeAction(state.action)) {
|
||||
@@ -290,7 +290,7 @@ function setServiceActionStateLoading(
|
||||
setDiagnosticActionLoading(state.action, loading);
|
||||
}
|
||||
|
||||
async function followServiceActionState(state: Podkop.ServiceActionState) {
|
||||
async function followServiceActionState(state: Forkop.ServiceActionState) {
|
||||
const jobId = state.job_id;
|
||||
|
||||
if (!jobId || followedServiceActionJobs.has(jobId)) {
|
||||
@@ -308,7 +308,7 @@ async function followServiceActionState(state: Podkop.ServiceActionState) {
|
||||
|
||||
try {
|
||||
if (state.running) {
|
||||
await PodkopShellMethods.waitServiceActionJob(jobId);
|
||||
await ForkopShellMethods.waitServiceActionJob(jobId);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('[DIAGNOSTIC]', 'followServiceActionState failed', error);
|
||||
@@ -316,13 +316,13 @@ async function followServiceActionState(state: Podkop.ServiceActionState) {
|
||||
handledServiceActionJobs.add(jobId);
|
||||
setServiceActionStateLoading(state, false);
|
||||
await refreshDiagnosticServicesInfo({ force: true, allowInactive: true });
|
||||
void PodkopShellMethods.uiActionAck('service', jobId);
|
||||
void ForkopShellMethods.uiActionAck('service', jobId);
|
||||
followedServiceActionJobs.delete(jobId);
|
||||
resetDiagnosticsChecks();
|
||||
}
|
||||
}
|
||||
|
||||
function followServiceActionsFromUiState(uiState?: Podkop.UiState) {
|
||||
function followServiceActionsFromUiState(uiState?: Forkop.UiState) {
|
||||
if (!uiState) {
|
||||
return;
|
||||
}
|
||||
@@ -411,10 +411,10 @@ async function fetchDiagnosticsProviderInfo({
|
||||
|
||||
const [zapretRuntime, zapret2Runtime, byedpiRuntime, inboundsConfig] =
|
||||
await Promise.all([
|
||||
PodkopShellMethods.checkZapretRuntime(),
|
||||
PodkopShellMethods.checkZapret2Runtime(),
|
||||
PodkopShellMethods.checkByedpiRuntime(),
|
||||
PodkopShellMethods.checkInboundsConfig(),
|
||||
ForkopShellMethods.checkZapretRuntime(),
|
||||
ForkopShellMethods.checkZapret2Runtime(),
|
||||
ForkopShellMethods.checkByedpiRuntime(),
|
||||
ForkopShellMethods.checkInboundsConfig(),
|
||||
]);
|
||||
|
||||
if (requestId !== latestProviderInfoRequestId) {
|
||||
@@ -514,7 +514,7 @@ function renderDiagnosticsChecks() {
|
||||
const diagnosticsChecks = [...store.get().diagnosticsChecks].sort(
|
||||
(a, b) => a.order - b.order,
|
||||
);
|
||||
const container = document.getElementById('pdk_diagnostic-page-checks');
|
||||
const container = document.getElementById('fkp_diagnostic-page-checks');
|
||||
|
||||
const renderedDiagnosticsChecks = diagnosticsChecks.map((check) =>
|
||||
renderCheckSection(check),
|
||||
@@ -532,15 +532,15 @@ function renderDiagnosticRunActionWidget() {
|
||||
const providerInfoLoaded =
|
||||
store.get().diagnosticsSystemInfo.providerInfoLoaded;
|
||||
const servicesInfoWidget = store.get().servicesInfoWidget;
|
||||
const podkopRunning = Boolean(servicesInfoWidget.data.podkopRunning);
|
||||
const container = document.getElementById('pdk_diagnostic-page-run-check');
|
||||
const forkopRunning = Boolean(servicesInfoWidget.data.forkopRunning);
|
||||
const container = document.getElementById('fkp_diagnostic-page-run-check');
|
||||
|
||||
const renderedAction = renderRunAction({
|
||||
loading,
|
||||
disabled: shouldDisableDiagnosticRunAction({
|
||||
providerInfoLoaded,
|
||||
servicesInfoLoading: servicesInfoWidget.loading,
|
||||
podkopRunning,
|
||||
forkopRunning,
|
||||
mutatingServiceActionLoading: isMutatingServiceActionLoading(),
|
||||
}),
|
||||
click: () => runChecks(),
|
||||
@@ -566,11 +566,11 @@ async function handleServiceRuntimeAction({
|
||||
let delegatedToWatcher = false;
|
||||
|
||||
if (optimisticRunning !== undefined) {
|
||||
setDisplayedPodkopRunning(optimisticRunning);
|
||||
setDisplayedForkopRunning(optimisticRunning);
|
||||
}
|
||||
|
||||
try {
|
||||
const startResponse = await PodkopShellMethods.serviceActionStart(action);
|
||||
const startResponse = await ForkopShellMethods.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 PodkopShellMethods.waitServiceActionJob(jobId);
|
||||
const result = await ForkopShellMethods.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 waitForPodkopRunningState(expectedRunning);
|
||||
await waitForForkopRunningState(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 PodkopShellMethods.uiActionAck('service', jobId);
|
||||
void ForkopShellMethods.uiActionAck('service', jobId);
|
||||
}
|
||||
resetDiagnosticsChecks();
|
||||
}
|
||||
@@ -640,7 +640,7 @@ async function handleEnable() {
|
||||
setDiagnosticActionLoading('enable', true);
|
||||
|
||||
try {
|
||||
await PodkopShellMethods.enable();
|
||||
await ForkopShellMethods.enable();
|
||||
} catch (e) {
|
||||
logger.error('[DIAGNOSTIC]', 'handleEnable - e', e);
|
||||
} finally {
|
||||
@@ -656,7 +656,7 @@ async function handleDisable() {
|
||||
setDiagnosticActionLoading('disable', true);
|
||||
|
||||
try {
|
||||
await PodkopShellMethods.disable();
|
||||
await ForkopShellMethods.disable();
|
||||
} catch (e) {
|
||||
logger.error('[DIAGNOSTIC]', 'handleDisable - e', e);
|
||||
} finally {
|
||||
@@ -672,7 +672,7 @@ async function handleShowGlobalCheck() {
|
||||
setDiagnosticActionLoading('globalCheck', true);
|
||||
|
||||
try {
|
||||
const globalCheck = await PodkopShellMethods.globalCheck(false);
|
||||
const globalCheck = await ForkopShellMethods.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 PodkopShellMethods.checkLogs();
|
||||
const viewLogs = await ForkopShellMethods.checkLogs();
|
||||
|
||||
if (viewLogs.success) {
|
||||
const getLatestLogs = async () => {
|
||||
const latestLogs = await PodkopShellMethods.checkLogs();
|
||||
const latestLogs = await ForkopShellMethods.checkLogs();
|
||||
|
||||
if (!latestLogs.success) {
|
||||
throw latestLogs;
|
||||
@@ -737,7 +737,7 @@ async function handleShowSingBoxConfig() {
|
||||
setDiagnosticActionLoading('showSingBoxConfig', true);
|
||||
|
||||
try {
|
||||
const showSingBoxConfig = await PodkopShellMethods.showSingBoxConfig(false);
|
||||
const showSingBoxConfig = await ForkopShellMethods.showSingBoxConfig(false);
|
||||
|
||||
if (showSingBoxConfig.success) {
|
||||
const rawSingBoxConfigText = stringifySingBoxConfig(
|
||||
@@ -786,7 +786,7 @@ function renderWikiDisclaimerWidget() {
|
||||
return 'default';
|
||||
}
|
||||
|
||||
const container = document.getElementById('pdk_diagnostic-page-wiki');
|
||||
const container = document.getElementById('fkp_diagnostic-page-wiki');
|
||||
|
||||
return preserveScrollForPage(() => {
|
||||
container!.replaceChildren(renderWikiDisclaimer(getWikiKind()));
|
||||
@@ -799,10 +799,10 @@ function renderDiagnosticAvailableActionsWidget() {
|
||||
const servicesInfoWidget = store.get().servicesInfoWidget;
|
||||
logger.debug('[DIAGNOSTIC]', 'renderDiagnosticAvailableActionsWidget');
|
||||
|
||||
const podkopEnabled = Boolean(servicesInfoWidget.data.podkopEnabled);
|
||||
const podkopRunning = Boolean(servicesInfoWidget.data.podkopRunning);
|
||||
const forkopEnabled = Boolean(servicesInfoWidget.data.forkopEnabled);
|
||||
const forkopRunning = Boolean(servicesInfoWidget.data.forkopRunning);
|
||||
const serviceTransition = getServiceTransition(
|
||||
servicesInfoWidget.data.podkopStatus,
|
||||
servicesInfoWidget.data.forkopStatus,
|
||||
);
|
||||
const restartLoading =
|
||||
diagnosticsActions.restart.loading || serviceTransition.restarting;
|
||||
@@ -824,25 +824,25 @@ function renderDiagnosticAvailableActionsWidget() {
|
||||
componentActionLoading,
|
||||
});
|
||||
const startVisible = shouldShowStartAction({
|
||||
podkopRunning,
|
||||
forkopRunning,
|
||||
restartLoading,
|
||||
startLoading,
|
||||
stopLoading,
|
||||
});
|
||||
const stopVisible = shouldShowStopAction({
|
||||
podkopRunning,
|
||||
forkopRunning,
|
||||
restartLoading,
|
||||
startLoading,
|
||||
stopLoading,
|
||||
});
|
||||
|
||||
const container = document.getElementById('pdk_diagnostic-page-actions');
|
||||
const container = document.getElementById('fkp_diagnostic-page-actions');
|
||||
|
||||
const renderedActions = renderAvailableActions({
|
||||
restart: {
|
||||
loading: restartLoading,
|
||||
visible: shouldShowRestartAction({
|
||||
podkopRunning,
|
||||
forkopRunning,
|
||||
restartLoading,
|
||||
startLoading,
|
||||
stopLoading,
|
||||
@@ -864,13 +864,13 @@ function renderDiagnosticAvailableActionsWidget() {
|
||||
},
|
||||
enable: {
|
||||
loading: diagnosticsActions.enable.loading,
|
||||
visible: !podkopEnabled,
|
||||
visible: !forkopEnabled,
|
||||
onClick: handleEnable,
|
||||
disabled: serviceControlsDisabled,
|
||||
},
|
||||
disable: {
|
||||
loading: diagnosticsActions.disable.loading,
|
||||
visible: podkopEnabled,
|
||||
visible: forkopEnabled,
|
||||
onClick: handleDisable,
|
||||
disabled: serviceControlsDisabled,
|
||||
},
|
||||
@@ -903,16 +903,16 @@ function renderDiagnosticSystemInfoWidget() {
|
||||
logger.debug('[DIAGNOSTIC]', 'renderDiagnosticSystemInfoWidget');
|
||||
const diagnosticsSystemInfo = store.get().diagnosticsSystemInfo;
|
||||
|
||||
const container = document.getElementById('pdk_diagnostic-page-system-info');
|
||||
const container = document.getElementById('fkp_diagnostic-page-system-info');
|
||||
|
||||
const items = [
|
||||
{
|
||||
key: 'Podkop Plus',
|
||||
value: normalizeCompiledVersion(diagnosticsSystemInfo.podkop_version),
|
||||
key: 'Forkop',
|
||||
value: normalizeCompiledVersion(diagnosticsSystemInfo.forkop_version),
|
||||
},
|
||||
{
|
||||
key: 'Luci App',
|
||||
value: normalizeCompiledVersion(PODKOP_LUCI_APP_VERSION),
|
||||
value: normalizeCompiledVersion(FORKOP_LUCI_APP_VERSION),
|
||||
},
|
||||
{
|
||||
key: 'Sing-box',
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user