mirror of
https://github.com/itdoginfo/podkop.git
synced 2026-06-10 13:28:14 +03:00
Compare commits
135 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de7b73af3c | ||
|
|
3c34bd1fd0 | ||
|
|
847895598d | ||
|
|
4146804e5a | ||
|
|
daef80b7b8 | ||
|
|
6e7b8a6be2 | ||
|
|
1365febaa4 | ||
|
|
1543d974cc | ||
|
|
4b03c28c41 | ||
|
|
c3281773d5 | ||
|
|
c9e0b54f2c | ||
|
|
7f33cfcb98 | ||
|
|
177469e212 | ||
|
|
1802818044 | ||
|
|
c62cb2de14 | ||
|
|
f253e4e36f | ||
|
|
41e696c9b2 | ||
|
|
835b455915 | ||
|
|
6089ef4c9b | ||
|
|
617e9a93bc | ||
|
|
6d9aedd236 | ||
|
|
fc9cf79221 | ||
|
|
2184c0c7d4 | ||
|
|
03736c613b | ||
|
|
c37ea6a4d3 | ||
|
|
a0869da4a5 | ||
|
|
23ac3a8d12 | ||
|
|
d8bd87a7da | ||
|
|
b93403c3e3 | ||
|
|
5629425853 | ||
|
|
8b2abc0b28 | ||
|
|
21085f3ac3 | ||
|
|
9a015bbde4 | ||
|
|
a7b6c36dfb | ||
|
|
f39e2d9ca9 | ||
|
|
00594f23fd | ||
|
|
0379cf5966 | ||
|
|
cfee6cec9a | ||
|
|
ad760a78bf | ||
|
|
d854caa4cc | ||
|
|
b44274d7f2 | ||
|
|
12d8537d90 | ||
|
|
8e18426a53 | ||
|
|
41a4f67fd0 | ||
|
|
c30160d8d3 | ||
|
|
42f75c3374 | ||
|
|
2cce383b33 | ||
|
|
81963bfbdf | ||
|
|
f3d2fa5a52 | ||
|
|
474f4b197f | ||
|
|
6083009c80 | ||
|
|
0672c55188 | ||
|
|
e14a7e7dd1 | ||
|
|
3f7e7cbc4b | ||
|
|
782f08b71b | ||
|
|
a40240bb3f | ||
|
|
1e9a7bffa4 | ||
|
|
4448c09c34 | ||
|
|
af95c0dcd0 | ||
|
|
d2fbff17bf | ||
|
|
a73def1f9a | ||
|
|
9976065696 | ||
|
|
aa8f2cef41 | ||
|
|
96f6def701 | ||
|
|
0152f073b7 | ||
|
|
06ce944e1c | ||
|
|
64369a93b0 | ||
|
|
53a3c943f0 | ||
|
|
7c7e1c6244 | ||
|
|
7fc1f39dd6 | ||
|
|
1c4285dfa8 | ||
|
|
ea1273e05e | ||
|
|
5fc3c95928 | ||
|
|
dd3e70153a | ||
|
|
622e092317 | ||
|
|
c045f8f224 | ||
|
|
b45088dad7 | ||
|
|
82345047cb | ||
|
|
0a4ed367bc | ||
|
|
c3f322ae61 | ||
|
|
eb9239696e | ||
|
|
5b3421498e | ||
|
|
6a48a060e1 | ||
|
|
14f704fcb8 | ||
|
|
ff43f477e9 | ||
|
|
576e58fd17 | ||
|
|
d72c98a254 | ||
|
|
7a497f1e31 | ||
|
|
d52f6e26ae | ||
|
|
68c61aed50 | ||
|
|
626ac981eb | ||
|
|
352d10a047 | ||
|
|
031c419ffb | ||
|
|
c13fdf5785 | ||
|
|
1b7ab606ba | ||
|
|
2bf208ecac | ||
|
|
e256e4bee5 | ||
|
|
32c385b309 | ||
|
|
56829c74c8 | ||
|
|
9d78cd2ce4 | ||
|
|
d9ce3b361e | ||
|
|
c67aadf267 | ||
|
|
ac4d7570f3 | ||
|
|
86897fd0af | ||
|
|
230ffbce46 | ||
|
|
dd5ddd1a14 | ||
|
|
cc947f9734 | ||
|
|
f8510cd828 | ||
|
|
23cbe7be4a | ||
|
|
f168fb7e31 | ||
|
|
fe84b3154f | ||
|
|
d09fdc0b95 | ||
|
|
835cd85970 | ||
|
|
8a3b41ec9c | ||
|
|
10d7617739 | ||
|
|
68010ed5f7 | ||
|
|
557e3666eb | ||
|
|
01bff8ccfb | ||
|
|
675a6af89c | ||
|
|
f1a6ff3469 | ||
|
|
d4b3377d68 | ||
|
|
d2ef640d76 | ||
|
|
47457f2c27 | ||
|
|
8a29e176f2 | ||
|
|
9653310208 | ||
|
|
3540610c78 | ||
|
|
fb54d62a7f | ||
|
|
288b8d4cc2 | ||
|
|
e014396ae2 | ||
|
|
694e4ca35a | ||
|
|
788c539e16 | ||
|
|
743cba8936 | ||
|
|
d1d703764c | ||
|
|
2efd415305 | ||
|
|
407b19b3ed |
29
.github/workflows/close-invalid-issues.yml
vendored
Normal file
29
.github/workflows/close-invalid-issues.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
name: Close Invalid Issues
|
||||||
|
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types: [labeled]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
close-invalid:
|
||||||
|
if: github.event.label.name == 'Close as invalid'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
steps:
|
||||||
|
- name: Close issue
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
await github.rest.issues.createComment({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
body: 'This issue has been marked as invalid and is being closed automatically.'
|
||||||
|
});
|
||||||
|
await github.rest.issues.update({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
state: 'closed'
|
||||||
|
});
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM itdoginfo/openwrt-sdk-apk:09102025
|
FROM itdoginfo/openwrt-sdk-apk:25.12.3
|
||||||
|
|
||||||
ARG PODKOP_VERSION
|
ARG PODKOP_VERSION
|
||||||
ENV PODKOP_VERSION=${PODKOP_VERSION}
|
ENV PODKOP_VERSION=${PODKOP_VERSION}
|
||||||
@@ -7,5 +7,5 @@ COPY ./podkop /builder/package/feeds/utilities/podkop
|
|||||||
COPY ./luci-app-podkop /builder/package/feeds/luci/luci-app-podkop
|
COPY ./luci-app-podkop /builder/package/feeds/luci/luci-app-podkop
|
||||||
|
|
||||||
RUN make defconfig && \
|
RUN make defconfig && \
|
||||||
make package/podkop/compile -j1 V=s && \
|
make package/podkop/compile -j4 V=s && \
|
||||||
make package/luci-app-podkop/compile -j1 V=s
|
make package/luci-app-podkop/compile -j4 V=s
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM itdoginfo/openwrt-sdk-ipk:24.10.3
|
FROM itdoginfo/openwrt-sdk-ipk:24.10.6
|
||||||
|
|
||||||
ARG PODKOP_VERSION
|
ARG PODKOP_VERSION
|
||||||
|
|
||||||
|
|||||||
83
README.md
83
README.md
@@ -1,61 +1,54 @@
|
|||||||
# Вещи, которые вам нужно знать перед установкой
|
# Podkop
|
||||||
|
|
||||||
|
Маршрутизация трафика для OpenWrt.
|
||||||
|
|
||||||
|
Направляйте нужные ресурсы в туннель, а остальное — напрямую. Открытое программное обеспечение на базе [sing-box](https://github.com/SagerNet/sing-box).
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> Проект находится в стадии бета-версии. Возможны ошибки, нестабильная работа и существенные изменения функциональности.
|
||||||
|
|
||||||
|
# Вещи, которые необходимо знать перед установкой
|
||||||
|
|
||||||
|
### Обновления и конфигурация
|
||||||
|
- При обновлении **обязательно** [очищайте кэш LuCI](https://podkop.net/docs/clear-browser-cache/).
|
||||||
|
- После обновления проверяйте конфигурацию — она может изменяться между версиями.
|
||||||
|
- При старте Podkop модифицируется конфигурация Dnsmasq.
|
||||||
|
- Podkop изменяет конфигурацию sing-box. Если вы используете собственную конфигурацию, заранее сохраните её.
|
||||||
|
|
||||||
|
### Системные требования
|
||||||
|
- Требуется OpenWrt 24.10 или выше.
|
||||||
|
- Необходимо минимум 25 МБ свободного места на устройстве. Устройства с флеш-памятью 16 МБ не поддерживаются.
|
||||||
|
|
||||||
|
### Важные ограничения и особенности
|
||||||
|
- Если установлен Getdomains, его [необходимо удалить](https://github.com/itdoginfo/domain-routing-openwrt?tab=readme-ov-file#скрипт-для-удаления)
|
||||||
|
- Dashboard доступен только при подключении по HTTP (из-за особенностей Clash API). При использовании HTTPS или домена работа может быть недоступна.
|
||||||
|
|
||||||
|
### Поддержка и диагностика
|
||||||
|
- [Руководство по диагностике](https://podkop.net/docs/diagnostics/)
|
||||||
|
- Актуальные изменения публикуются в [Telegram-чате](https://t.me/itdogchat/81758/420321). Пожалуйста, ознакомьтесь с закрепленными сообщениями.
|
||||||
|
- При возникновении проблем оставляйте технически грамотный фидбэк в GitHub Issues и Telegram-чате.
|
||||||
|
|
||||||
- Это бета-версия, которая находится в активной разработке. Из версии в версию что-то может меняться.
|
|
||||||
- При возникновении проблем, нужен технически грамотный фидбэк в чат. Ознакомьтесь с закрепом в топике.
|
|
||||||
- При обновлении **обязательно** [сбрасывайте кэш LuCI](https://podkop.net/docs/clear-browser-cache/).
|
|
||||||
- Также при обновлении всегда заходите в конфигурацию и проверяйте свои настройки. Конфигурация может измениться.
|
|
||||||
- Необходимо минимум 25МБ свободного места на роутере. Роутеры с флешками на 16МБ сразу мимо.
|
|
||||||
- При старте программы редактируется конфиг Dnsmasq.
|
|
||||||
- Podkop редактирует конфиг sing-box. Обязательно сохраните ваш конфиг sing-box перед установкой, если он вам нужен.
|
|
||||||
- Информация здесь может быть устаревшей. Все изменения фиксируются в [телеграм-чате](https://t.me/itdogchat/81758/420321).
|
|
||||||
- [Если у вас что-то не работает.](https://podkop.net/docs/diagnostics/)
|
|
||||||
- Если у вас установлен Getdomains, [его следует удалить](https://github.com/itdoginfo/domain-routing-openwrt?tab=readme-ov-file#%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82-%D0%B4%D0%BB%D1%8F-%D1%83%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F).
|
|
||||||
- Требуется версия OpenWrt 24.10.
|
|
||||||
- Dashboard доступен, если вы заходите по http (из-за особенностей clash api). И не будет работать, если вы заходите по https и/или домену.
|
|
||||||
|
|
||||||
# Документация
|
# Документация
|
||||||
https://podkop.net/
|
https://podkop.net/
|
||||||
|
|
||||||
# Установка Podkop
|
# Установка Podkop
|
||||||
Полная информация в [документации](https://podkop.net/docs/install/)
|
Полное руководство доступно в [документации](https://podkop.net/docs/install/)
|
||||||
|
|
||||||
Вкратце, достаточно одного скрипта для установки и обновления:
|
Для установки и обновления достаточно выполнить один скрипт:
|
||||||
```
|
```
|
||||||
sh <(wget -O - https://raw.githubusercontent.com/itdoginfo/podkop/refs/heads/main/install.sh)
|
sh <(wget -O - https://raw.githubusercontent.com/itdoginfo/podkop/refs/heads/main/install.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Изменения 0.7.0
|
## Будущее
|
||||||
Начиная с версии 0.7.0 изменена структура конфига `/etc/config/podkop`. Старые значения несовместимы с новыми. Нужно заново настроить Podkop.
|
Планы развития проекта в настоящее время не публикуются в виде открытого roadmap. Обсуждение направлений и задач разработки ведётся авторами и контрибьюторами.
|
||||||
|
|
||||||
Скрипт установки обнаружит старую версию и предупредит вас об этом. Если вы согласитесь, то он сделает автоматически написанное ниже.
|
|
||||||
|
|
||||||
При обновлении вручную нужно:
|
|
||||||
|
|
||||||
0. Не ныть в issue и чатик.
|
|
||||||
1. Забэкапить старый конфиг:
|
|
||||||
```
|
|
||||||
mv /etc/config/podkop /etc/config/podkop-070
|
|
||||||
```
|
|
||||||
2. Стянуть новый дефолтный конфиг:
|
|
||||||
```
|
|
||||||
wget -O /etc/config/podkop https://raw.githubusercontent.com/itdoginfo/podkop/refs/heads/main/podkop/files/etc/config/podkop
|
|
||||||
```
|
|
||||||
3. Настроить заново ваш Podkop через Luci или UCI.
|
|
||||||
|
|
||||||
# ToDo
|
|
||||||
|
|
||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> PR принимаются только по issues, у которых стоит label "enhancement". Либо по согласованию с авторами в ТГ-чате. Остальные PR на данный момент не рассматриваются.
|
> Pull Request принимаются только после согласования с авторами в Telegram-чате. На данный момент PR без предварительного обсуждения не рассматриваются.
|
||||||
|
|
||||||
## Будущее
|
> [!WARNING]
|
||||||
- [ ] [Подписка](https://github.com/itdoginfo/podkop/issues/118). Здесь нужна реализация, чтоб для каждой секции помимо ручного выбора, был выбор фильтрации по тегу. Например, для main выбираем ключевые слова NL, DE, FI. А для extra секции фильтруем по RU. И создаётся outbound c urltest в которых перечислены outbound из фильтров.
|
> Данное программное обеспечение предоставляется «как есть», без каких-либо явных или подразумеваемых гарантий, включая гарантии коммерческой пригодности и соответствия определённой цели.
|
||||||
- [ ] Весь трафик в sing-box и маршрутизация полностью на его уровне.
|
>
|
||||||
- [ ] При успешном запуске переходит в фоновый режим и следит за состоянием sing-box. Если вдруг идёт exit 1, выполняется dnsmasq restore и снова следит за состоянием. Вопрос в том, как это искусственно провернуть. Попробовать положить прокси и посмотреть, останется ли работать DNS в этом случае. И здесь, вероятно, можно обойтись триггером в init.d. [Issue](https://github.com/itdoginfo/podkop/issues/111)
|
> Правообладатели и участники проекта не несут ответственности за любые прямые, косвенные, случайные, специальные или иные убытки, возникшие в результате использования программного обеспечения, включая потерю данных, прибыли или прерывание деятельности, даже если они были предупреждены о возможности таких последствий.
|
||||||
- [ ] Галочка, которая режет доступ к doh серверам.
|
|
||||||
- [ ] IPv6. Только после наполнения Wiki.
|
|
||||||
|
|
||||||
## Тесты
|
|
||||||
- [ ] Unit тесты (BATS)
|
|
||||||
- [ ] Интеграционные тесты бекенда (OpenWrt rootfs + BATS)
|
|
||||||
|
|
||||||
[](https://deepwiki.com/itdoginfo/podkop)
|
[](https://deepwiki.com/itdoginfo/podkop)
|
||||||
@@ -34,6 +34,7 @@ vless://4d21ce62-8723-4c4d-93e3-d586b107aa40@127.0.0.1:51394?type=ws&encryption=
|
|||||||
# gRPC
|
# gRPC
|
||||||
vless://974b39e3-f7bf-42b9-933c-16699c635e77@127.0.0.1:15633?type=grpc&encryption=none&serviceName=TunService&authority=&security=none#vless-gRPC-none
|
vless://974b39e3-f7bf-42b9-933c-16699c635e77@127.0.0.1:15633?type=grpc&encryption=none&serviceName=TunService&authority=&security=none#vless-gRPC-none
|
||||||
vless://651e7eca-5152-46f1-baf2-d502e0af7b27@127.0.0.1:28535?type=grpc&encryption=none&serviceName=TunService&authority=authority&security=reality&pbk=nhZ7NiKfcqESa5ZeBFfsq9o18W-OWOAHLln9UmuVXSk&fp=chrome&sni=google.com&sid=11cbaeaa&spx=%2F#vless-gRPC-reality
|
vless://651e7eca-5152-46f1-baf2-d502e0af7b27@127.0.0.1:28535?type=grpc&encryption=none&serviceName=TunService&authority=authority&security=reality&pbk=nhZ7NiKfcqESa5ZeBFfsq9o18W-OWOAHLln9UmuVXSk&fp=chrome&sni=google.com&sid=11cbaeaa&spx=%2F#vless-gRPC-reality
|
||||||
|
vless://221ff905-b783-41a0-a6a6-8089eaf3b34b@abc.def.xyz:443?security=reality&type=grpc&headerType=&authority=abc.def.xyz&serviceName=name&mode=gun&sni=abc.def.xyz&fp=chrome&pbk=C3nhDJw02ZU_rjx4GbC54Sp79-ysF5lWIQVWdY4FOnE&sid=#vless-gRPC-reality-mode
|
||||||
vless://af1f8b5f-26c9-4fe8-8ce7-6d6366c5c9ce@127.0.0.1:47904?type=grpc&encryption=none&serviceName=TunService&authority=authority&security=tls&fp=chrome&alpn=h2%2Chttp%2F1.1&sni=google.com#vless-gRPC-tls
|
vless://af1f8b5f-26c9-4fe8-8ce7-6d6366c5c9ce@127.0.0.1:47904?type=grpc&encryption=none&serviceName=TunService&authority=authority&security=tls&fp=chrome&alpn=h2%2Chttp%2F1.1&sni=google.com#vless-gRPC-tls
|
||||||
vless://95f2c4bb-abcb-47ba-bfad-e181c03e4659@127.0.0.1:34530?type=grpc&encryption=none&serviceName=TunService&authority=authority&security=tls&fp=chrome&alpn=h2%2Chttp%2F1.1&allowInsecure=1&sni=google.com#vless-gRPC-tls-insecure
|
vless://95f2c4bb-abcb-47ba-bfad-e181c03e4659@127.0.0.1:34530?type=grpc&encryption=none&serviceName=TunService&authority=authority&security=tls&fp=chrome&alpn=h2%2Chttp%2F1.1&allowInsecure=1&sni=google.com#vless-gRPC-tls-insecure
|
||||||
vless://bd39490f-9a4f-49b2-96b6-824190cf89e9@127.0.0.1:27779?type=grpc&encryption=none&serviceName=TunService&authority=authority&security=tls&fp=chrome&alpn=h2%2Chttp%2F1.1&sni=google.com&ech=AF3%2BDQBZAAAgACBc%2FiNdo4QkTt9eQCQgkOiJVSfA9G6UWAyipaBFtBD%2FVQAkAAEAAQABAAIAAQADAAIAAQACAAIAAgADAAMAAQADAAIAAwADAApnb29nbGUuY29tAAA%3D#vless-gRPC-tls-ech
|
vless://bd39490f-9a4f-49b2-96b6-824190cf89e9@127.0.0.1:27779?type=grpc&encryption=none&serviceName=TunService&authority=authority&security=tls&fp=chrome&alpn=h2%2Chttp%2F1.1&sni=google.com&ech=AF3%2BDQBZAAAgACBc%2FiNdo4QkTt9eQCQgkOiJVSfA9G6UWAyipaBFtBD%2FVQAkAAEAAQABAAIAAQADAAIAAQACAAIAAgADAAMAAQADAAIAAwADAApnb29nbGUuY29tAAA%3D#vless-gRPC-tls-ech
|
||||||
@@ -81,4 +82,38 @@ trojan://ou8pLSyx9N@127.0.0.1:17737?type=httpupgrade&path=%2Fhttpupgradepath&hos
|
|||||||
|
|
||||||
# XHTTP
|
# XHTTP
|
||||||
trojan://VEetltxLtw@127.0.0.1:59072?type=xhttp&path=%2Fxhttppath&host=google.com&mode=auto&security=none#trojan-xhttp
|
trojan://VEetltxLtw@127.0.0.1:59072?type=xhttp&path=%2Fxhttppath&host=google.com&mode=auto&security=none#trojan-xhttp
|
||||||
|
```
|
||||||
|
|
||||||
|
## Hysteria2
|
||||||
|
|
||||||
|
hysteria2://
|
||||||
|
```
|
||||||
|
# With password
|
||||||
|
hysteria2://password@example.com:443/#hysteria2-password
|
||||||
|
hysteria2://password@example.com:443/?insecure=1#hysteria2-password-insecure
|
||||||
|
|
||||||
|
# With SNI
|
||||||
|
hysteria2://password@example.com:443/?sni=example.com#hysteria2-password-sni
|
||||||
|
|
||||||
|
# With obfuscation
|
||||||
|
hysteria2://password@example.com:443/?obfs=salamander&obfs-password=obfspassword#hysteria2-obfs
|
||||||
|
|
||||||
|
# All parameters combined
|
||||||
|
hysteria2://mypassword@example.com:8443/?sni=example.com&obfs=salamander&obfs-password=obfspass&insecure=1#hysteria2-all-params
|
||||||
|
```
|
||||||
|
|
||||||
|
hy2://
|
||||||
|
```
|
||||||
|
# With password
|
||||||
|
hy2://password@example.com:443/#hysteria2-password
|
||||||
|
hy2://password@example.com:443/?insecure=1#hysteria2-password-insecure
|
||||||
|
|
||||||
|
# With SNI
|
||||||
|
hy2://password@example.com:443/?sni=example.com#hysteria2-password-sni
|
||||||
|
|
||||||
|
# With obfuscation
|
||||||
|
hy2://password@example.com:443/?obfs=salamander&obfs-password=obfspassword#hysteria2-obfs
|
||||||
|
|
||||||
|
# All parameters combined
|
||||||
|
hy2://mypassword@example.com:8443/?sni=example.com&obfs=salamander&obfs-password=obfspass&insecure=1#hysteria2-all-params
|
||||||
```
|
```
|
||||||
63
TRADEMARK.md
Normal file
63
TRADEMARK.md
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
Trademark Guidelines
|
||||||
|
|
||||||
|
Version 1.0 dated May 28, 2026
|
||||||
|
|
||||||
|
This trademark policy was prepared to help you understand how to use the Podkop trademarks, service marks, and logos in connection with the Podkop open source project and related software.
|
||||||
|
|
||||||
|
While the Podkop software is available under an open source license, that license does not grant permission to use the Podkop trademarks, service marks, or logos. This policy explains acceptable use of the Podkop brand and related marks.
|
||||||
|
|
||||||
|
This Policy covers:
|
||||||
|
1. Our word trademarks and service marks: Podkop
|
||||||
|
2. Our logos, icons, and other Podkop brand assets
|
||||||
|
|
||||||
|
This policy encompasses all trademarks and service marks, whether they are registered or not.
|
||||||
|
|
||||||
|
## 1. General Guidelines
|
||||||
|
|
||||||
|
Whenever you use one of our marks, you must always do so in a way that does not mislead anyone about what they are getting and from whom. For example, you cannot say you are distributing Podkop software when you are distributing a modified version of it, because recipients may not understand the differences between your modified versions and our own.
|
||||||
|
|
||||||
|
You also cannot use our logo on your website in a way that suggests that your website is an official website or that we endorse your website.
|
||||||
|
|
||||||
|
You can, however, say that you like the Podkop project, that you participate in the Podkop community, or that you are providing an unmodified version of the Podkop software.
|
||||||
|
|
||||||
|
You may not use or register our marks, or variations of them as part of your own trademark, service mark, domain name, company name, trade name, product name or service name.
|
||||||
|
|
||||||
|
Trademark law does not allow your use of names or trademarks that are too similar to ours. You therefore may not use an obvious variation of any of our marks or any phonetic equivalent, foreign language equivalent, takeoff, or abbreviation for a similar or compatible product or service. For example, we would consider the following too similar to one of our Marks:
|
||||||
|
|
||||||
|
- MyPodkop
|
||||||
|
- Open-Podkop
|
||||||
|
- PodkopX
|
||||||
|
- Podkop Lite
|
||||||
|
- Podkop Pro
|
||||||
|
|
||||||
|
## 2. Acceptable Uses
|
||||||
|
### Unmodified Code
|
||||||
|
|
||||||
|
When you redistribute an unmodified copy of Podkop software, you must not remove any Podkop trademarks, notices, or branding included in the original distribution.
|
||||||
|
|
||||||
|
### Modified Code
|
||||||
|
|
||||||
|
If you distribute a modified version of Podkop software, you may not use the Podkop name, trademarks, or logos in connection with your modified version, except to accurately describe the origin of the software in factual statements.
|
||||||
|
|
||||||
|
You must replace any Podkop branding, including names displayed in user interfaces, logs, documentation, and other user-facing elements, with your own distinct name and branding, so that your modified version is clearly distinguishable from the original Podkop software.
|
||||||
|
|
||||||
|
You must remove all Podkop logos and any other brand assets from the modified version.
|
||||||
|
|
||||||
|
You may not present your modified version as Podkop or as an official Podkop release, nor may you use the Podkop name in a way that suggests endorsement, affiliation, or official status.
|
||||||
|
|
||||||
|
You may only refer to Podkop in a factual and descriptive manner, for example: “This software is derived from Podkop open-source software.”
|
||||||
|
|
||||||
|
### Statements about Compatibility
|
||||||
|
|
||||||
|
You may use the word marks, exclusively for descriptive and factual purposes, to truthfully and accurately describe the relationship between your software and ours, including compatibility or origin. Any other use may imply that we have certified or approved your software.
|
||||||
|
|
||||||
|
### No Domain Names
|
||||||
|
|
||||||
|
You must not register any domain that includes our word marks or any variant or combination of them.
|
||||||
|
|
||||||
|
## 3. How to Display our Marks
|
||||||
|
### Use of Trademarks in Text
|
||||||
|
|
||||||
|
Always use trademarks in their exact form with correct spelling. They must not be abbreviated, modified, hyphenated, or combined with other words in a way that creates a new product or service name.
|
||||||
|
|
||||||
|
Unacceptable: Podcop
|
||||||
65
TRADEMARK_RU.md
Normal file
65
TRADEMARK_RU.md
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
Руководство по использованию товарных знаков
|
||||||
|
|
||||||
|
Версия 1.0 от 28 мая 2026 года
|
||||||
|
|
||||||
|
Настоящая политика в отношении товарных знаков подготовлена для того, чтобы помочь вам понять, как использовать товарные знаки, знаки обслуживания и логотипы Podkop в связи с открытым исходным кодом проекта Podkop и связанным программным обеспечением.
|
||||||
|
|
||||||
|
Хотя программное обеспечение Podkop распространяется под лицензией с открытым исходным кодом, эта лицензия не предоставляет разрешения на использование товарных знаков Podkop, знаков обслуживания или логотипов. Данная политика объясняет допустимое использование бренда Podkop и связанных обозначений.
|
||||||
|
|
||||||
|
Настоящая Политика охватывает:
|
||||||
|
1. Наши словесные товарные знаки и знаки обслуживания: Podkop
|
||||||
|
2. Наши логотипы, иконки и другие бренд-активы Podkop
|
||||||
|
|
||||||
|
Данная политика распространяется на все товарные знаки и знаки обслуживания, независимо от того, зарегистрированы они или нет.
|
||||||
|
|
||||||
|
## 1. Общие рекомендации
|
||||||
|
|
||||||
|
При использовании любого из наших знаков вы всегда должны делать это таким образом, чтобы никого не вводить в заблуждение относительно того, что именно они получают и от кого. Например, вы не можете утверждать, что распространяете программное обеспечение Podkop, если вы распространяете его модифицированную версию, поскольку получатели могут не понимать различий между вашей модифицированной версией и нашей оригинальной.
|
||||||
|
|
||||||
|
Вы также не можете использовать наш логотип на своём сайте таким образом, чтобы это создавало впечатление, что ваш сайт является официальным сайтом или что мы одобряем ваш сайт.
|
||||||
|
|
||||||
|
Однако вы можете указывать, что вам нравится проект Podkop, что вы участвуете в сообществе Podkop или что вы распространяете немодифицированную версию программного обеспечения Podkop.
|
||||||
|
|
||||||
|
Вы не имеете права использовать или регистрировать наши знаки, а также их вариации, как часть вашего собственного товарного знака, знака обслуживания, доменного имени, названия компании, коммерческого наименования, названия продукта или услуги.
|
||||||
|
|
||||||
|
Закон о товарных знаках не допускает использование названий или знаков, которые слишком похожи на наши. Поэтому вы не можете использовать очевидные вариации наших знаков или любые фонетически, иностранно-языковые эквиваленты, производные, аббревиатуры для похожего или совместимого продукта или услуги. Например, мы считаем слишком похожими на наши знаки следующие варианты:
|
||||||
|
|
||||||
|
- MyPodkop
|
||||||
|
- Open-Podkop
|
||||||
|
- PodkopX
|
||||||
|
- Podkop Lite
|
||||||
|
- Podkop Pro
|
||||||
|
|
||||||
|
## 2. Допустимое использование
|
||||||
|
|
||||||
|
### Немодифицированный код
|
||||||
|
|
||||||
|
При распространении немодифицированной копии программного обеспечения Podkop вы не должны удалять товарные знаки, уведомления или брендинг Podkop, включённые в исходное распространение.
|
||||||
|
|
||||||
|
### Модифицированный код
|
||||||
|
|
||||||
|
Если вы распространяете модифицированную версию программного обеспечения Podkop, вы не можете использовать название Podkop, товарные знаки или логотипы в связи с вашей модифицированной версией, за исключением точного описания происхождения программного обеспечения в фактических утверждениях.
|
||||||
|
|
||||||
|
Вы обязаны заменить все элементы брендинга Podkop, включая названия, отображаемые в пользовательском интерфейсе, логах, документации и других пользовательских элементах, на собственное отличительное название и брендинг, чтобы ваша модифицированная версия была явно отличима от оригинального программного обеспечения Podkop.
|
||||||
|
|
||||||
|
Вы должны удалить все логотипы Podkop и любые другие бренд-материалы из модифицированной версии.
|
||||||
|
|
||||||
|
Вы не можете представлять вашу модифицированную версию как Podkop или как официальную версию Podkop, а также использовать название Podkop таким образом, чтобы это подразумевало одобрение, аффилированность или официальный статус.
|
||||||
|
|
||||||
|
Вы можете ссылаться на Podkop только в фактическом и описательном контексте, например: «Это программное обеспечение основано на программном обеспечении Podkop с открытым исходным кодом».
|
||||||
|
|
||||||
|
### Упоминания о совместимости
|
||||||
|
|
||||||
|
Вы можете использовать словесные знаки исключительно в описательных и фактических целях для правдивого и точного описания связи вашего программного обеспечения с нашим, включая совместимость или происхождение. Любое другое использование может создавать впечатление, что мы сертифицировали или одобрили ваше программное обеспечение.
|
||||||
|
|
||||||
|
### Запрет на доменные имена
|
||||||
|
|
||||||
|
Вы не должны регистрировать доменные имена, содержащие наши словесные знаки или любые их варианты или комбинации.
|
||||||
|
|
||||||
|
## 3. Как отображать наши знаки
|
||||||
|
|
||||||
|
### Использование товарных знаков в тексте
|
||||||
|
|
||||||
|
Всегда используйте товарные знаки в их точной форме с корректным написанием. Их нельзя сокращать, изменять, соединять дефисами или объединять с другими словами таким образом, чтобы это создавало новое название продукта или услуги.
|
||||||
|
|
||||||
|
Недопустимо: Podcop
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,38 +1,38 @@
|
|||||||
# SOME DESCRIPTIVE TITLE.
|
# SOME DESCRIPTIVE TITLE.
|
||||||
# Copyright (C) 2025 THE PACKAGE'S COPYRIGHT HOLDER
|
# Copyright (C) 2026 THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
# This file is distributed under the same license as the PODKOP package.
|
# This file is distributed under the same license as the PODKOP package.
|
||||||
# divocat <divocatt@gmail.com>, 2025.
|
# divocatt <210179590+divocatt@users.noreply.github.com>, 2026.
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PODKOP\n"
|
"Project-Id-Version: PODKOP\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-10-23 17:43+0300\n"
|
"POT-Creation-Date: 2026-05-29 13:40+0300\n"
|
||||||
"PO-Revision-Date: 2025-10-23 17:43+0300\n"
|
"PO-Revision-Date: 2026-05-29 13:40+0300\n"
|
||||||
"Last-Translator: divocat <divocatt@gmail.com>\n"
|
"Last-Translator: divocatt <210179590+divocatt@users.noreply.github.com>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
"Language: \n"
|
"Language: \n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:342
|
#: src/podkop/tabs/dashboard/initController.ts:345
|
||||||
msgid "✔ Enabled"
|
msgid "✔ Enabled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:353
|
#: src/podkop/tabs/dashboard/initController.ts:356
|
||||||
msgid "✔ Running"
|
msgid "✔ Running"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:343
|
#: src/podkop/tabs/dashboard/initController.ts:346
|
||||||
msgid "✘ Disabled"
|
msgid "✘ Disabled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:354
|
#: src/podkop/tabs/dashboard/initController.ts:357
|
||||||
msgid "✘ Stopped"
|
msgid "✘ Stopped"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:304
|
#: src/podkop/tabs/dashboard/initController.ts:307
|
||||||
msgid "Active Connections"
|
msgid "Active Connections"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -40,15 +40,19 @@ msgstr ""
|
|||||||
msgid "Additional marking rules found"
|
msgid "Additional marking rules found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:111
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:247
|
||||||
|
msgid "Allows access to YACD from the WAN. Make sure to open the appropriate port in your firewall."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:199
|
||||||
msgid "Applicable for SOCKS and Shadowsocks proxy"
|
msgid "Applicable for SOCKS and Shadowsocks proxy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:356
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:444
|
||||||
msgid "At least one valid domain must be specified. Comments-only content is not allowed."
|
msgid "At least one valid domain must be specified. Comments-only content is not allowed."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:437
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:525
|
||||||
msgid "At least one valid subnet or IP must be specified. Comments-only content is not allowed."
|
msgid "At least one valid subnet or IP must be specified. Comments-only content is not allowed."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -72,16 +76,17 @@ msgstr ""
|
|||||||
msgid "Browser is using FakeIP correctly"
|
msgid "Browser is using FakeIP correctly"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:329
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:348
|
||||||
msgid "Cache File Path"
|
msgid "Cache File Path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:343
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:362
|
||||||
msgid "Cache file path cannot be empty"
|
msgid "Cache file path cannot be empty"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:27
|
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:27
|
||||||
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:28
|
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:28
|
||||||
|
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:27
|
||||||
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:25
|
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:25
|
||||||
msgid "Cannot receive checks result"
|
msgid "Cannot receive checks result"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -89,6 +94,7 @@ msgstr ""
|
|||||||
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:15
|
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:15
|
||||||
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:15
|
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:15
|
||||||
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:13
|
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:13
|
||||||
|
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:15
|
||||||
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:13
|
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:13
|
||||||
msgid "Checking, please wait"
|
msgid "Checking, please wait"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -113,11 +119,11 @@ msgstr ""
|
|||||||
msgid "Close"
|
msgid "Close"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:211
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:299
|
||||||
msgid "Community Lists"
|
msgid "Community Lists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:316
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:335
|
||||||
msgid "Config File Path"
|
msgid "Config File Path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -125,7 +131,7 @@ msgstr ""
|
|||||||
msgid "Configuration for Podkop service"
|
msgid "Configuration for Podkop service"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:22
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:23
|
||||||
msgid "Configuration Type"
|
msgid "Configuration Type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -133,7 +139,7 @@ msgstr ""
|
|||||||
msgid "Connection Type"
|
msgid "Connection Type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:25
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:26
|
||||||
msgid "Connection URL"
|
msgid "Connection URL"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -173,16 +179,16 @@ msgstr ""
|
|||||||
msgid "Disable autostart"
|
msgid "Disable autostart"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:246
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:265
|
||||||
msgid "Disable QUIC"
|
msgid "Disable QUIC"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:247
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:266
|
||||||
msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming"
|
msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:302
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:390
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:382
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:470
|
||||||
msgid "Disabled"
|
msgid "Disabled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -190,17 +196,17 @@ msgstr ""
|
|||||||
msgid "DNS on router"
|
msgid "DNS on router"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:179
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:267
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:15
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:15
|
||||||
msgid "DNS over HTTPS (DoH)"
|
msgid "DNS over HTTPS (DoH)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:180
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:268
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:16
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:16
|
||||||
msgid "DNS over TLS (DoT)"
|
msgid "DNS over TLS (DoT)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:176
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:264
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:12
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:12
|
||||||
msgid "DNS Protocol Type"
|
msgid "DNS Protocol Type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -209,7 +215,7 @@ msgstr ""
|
|||||||
msgid "DNS Rewrite TTL"
|
msgid "DNS Rewrite TTL"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:189
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:277
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:24
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:24
|
||||||
msgid "DNS Server"
|
msgid "DNS Server"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -222,16 +228,16 @@ msgstr ""
|
|||||||
msgid "Do not panic, everything can be fixed, just..."
|
msgid "Do not panic, everything can be fixed, just..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:166
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:254
|
||||||
msgid "Domain Resolver"
|
msgid "Domain Resolver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:307
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:326
|
||||||
msgid "Dont Touch My DHCP!"
|
msgid "Dont Touch My DHCP!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:238
|
#: src/podkop/tabs/dashboard/initController.ts:241
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:272
|
#: src/podkop/tabs/dashboard/initController.ts:275
|
||||||
msgid "Downlink"
|
msgid "Downlink"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -239,24 +245,21 @@ msgstr ""
|
|||||||
msgid "Download"
|
msgid "Download"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:269
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:288
|
||||||
msgid "Download Lists via Proxy/VPN"
|
msgid "Download Lists via Proxy/VPN"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:278
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:297
|
||||||
msgid "Download Lists via specific proxy section"
|
msgid "Download Lists via specific proxy section"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:270
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:289
|
||||||
msgid "Downloading all lists via main Proxy/VPN"
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:298
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:279
|
|
||||||
msgid "Downloading all lists via specific Proxy/VPN"
|
msgid "Downloading all lists via specific Proxy/VPN"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:303
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:391
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:383
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:471
|
||||||
msgid "Dynamic List"
|
msgid "Dynamic List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -264,11 +267,15 @@ msgstr ""
|
|||||||
msgid "Enable autostart"
|
msgid "Enable autostart"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:167
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:255
|
||||||
msgid "Enable built-in DNS resolver for domains handled by this section"
|
msgid "Enable built-in DNS resolver for domains handled by this section"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:575
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:691
|
||||||
|
msgid "Enable DNS resolve to get real IP when routing"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:665
|
||||||
msgid "Enable Mixed Proxy"
|
msgid "Enable Mixed Proxy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -276,7 +283,7 @@ msgstr ""
|
|||||||
msgid "Enable Output Network Interface"
|
msgid "Enable Output Network Interface"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:576
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:666
|
||||||
msgid "Enable the mixed proxy, allowing this section to route traffic through both HTTP and SOCKS proxies"
|
msgid "Enable the mixed proxy, allowing this section to route traffic through both HTTP and SOCKS proxies"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -284,27 +291,47 @@ msgstr ""
|
|||||||
msgid "Enable YACD"
|
msgid "Enable YACD"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:65
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:246
|
||||||
|
msgid "Enable YACD WAN Access"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:66
|
||||||
msgid "Enter complete outbound configuration in JSON format"
|
msgid "Enter complete outbound configuration in JSON format"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:338
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:426
|
||||||
msgid "Enter domain names separated by commas, spaces, or newlines. You can add comments using //"
|
msgid "Enter domain names separated by commas, spaces, or newlines. You can add comments using //"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:312
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:400
|
||||||
msgid "Enter domain names without protocols, e.g. example.com or sub.example.com"
|
msgid "Enter domain names without protocols, e.g. example.com or sub.example.com"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:392
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:480
|
||||||
msgid "Enter subnets in CIDR notation (e.g. 103.21.244.0/22) or single IP addresses"
|
msgid "Enter subnets in CIDR notation (e.g. 103.21.244.0/22) or single IP addresses"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:365
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:138
|
||||||
|
msgid "Every 1 minute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:139
|
||||||
|
msgid "Every 3 minutes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:137
|
||||||
|
msgid "Every 30 seconds"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:140
|
||||||
|
msgid "Every 5 minutes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:402
|
||||||
msgid "Exclude NTP"
|
msgid "Exclude NTP"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:366
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:403
|
||||||
msgid "Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN"
|
msgid "Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -312,20 +339,21 @@ msgstr ""
|
|||||||
msgid "Failed to copy!"
|
msgid "Failed to copy!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:226
|
#: src/podkop/tabs/diagnostic/initController.ts:227
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:230
|
#: src/podkop/tabs/diagnostic/initController.ts:231
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:260
|
#: src/podkop/tabs/diagnostic/initController.ts:261
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:264
|
#: src/podkop/tabs/diagnostic/initController.ts:265
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:298
|
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:302
|
#: src/podkop/tabs/diagnostic/initController.ts:302
|
||||||
|
#: src/podkop/tabs/diagnostic/initController.ts:306
|
||||||
msgid "Failed to execute!"
|
msgid "Failed to execute!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/methods/custom/getDashboardSections.ts:117
|
#: src/podkop/methods/custom/getDashboardSections.ts:148
|
||||||
|
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:59
|
||||||
msgid "Fastest"
|
msgid "Fastest"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:550
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:638
|
||||||
msgid "Fully Routed IPs"
|
msgid "Fully Routed IPs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -333,7 +361,7 @@ msgstr ""
|
|||||||
msgid "Get global check"
|
msgid "Get global check"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:221
|
#: src/podkop/tabs/diagnostic/initController.ts:222
|
||||||
msgid "Global check"
|
msgid "Global check"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -366,11 +394,63 @@ msgstr ""
|
|||||||
msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y"
|
msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:90
|
||||||
|
msgid "Invalid HY2 URL: insecure must be 0 or 1"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:77
|
||||||
|
msgid "Invalid HY2 URL: invalid port number"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:30
|
||||||
|
msgid "Invalid HY2 URL: missing credentials/server"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:47
|
||||||
|
msgid "Invalid HY2 URL: missing host"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:41
|
||||||
|
msgid "Invalid HY2 URL: missing host & port"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:36
|
||||||
|
msgid "Invalid HY2 URL: missing password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:50
|
||||||
|
msgid "Invalid HY2 URL: missing port"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:18
|
||||||
|
msgid "Invalid HY2 URL: must not contain spaces"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:12
|
||||||
|
msgid "Invalid HY2 URL: must start with hysteria2:// or hy2://"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:108
|
||||||
|
msgid "Invalid HY2 URL: obfs-password required when obfs is set"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:122
|
||||||
|
msgid "Invalid HY2 URL: parsing failed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:116
|
||||||
|
msgid "Invalid HY2 URL: sni cannot be empty"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:98
|
||||||
|
msgid "Invalid HY2 URL: unsupported obfs type"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/validators/validateIp.ts:11
|
#: src/validators/validateIp.ts:11
|
||||||
msgid "Invalid IP address"
|
msgid "Invalid IP address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/validators/validateOutboundJson.ts:19
|
#: src/validators/validateOutboundJson.ts:9
|
||||||
msgid "Invalid JSON format"
|
msgid "Invalid JSON format"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -466,7 +546,8 @@ msgstr ""
|
|||||||
msgid "Invalid Trojan URL: parsing failed"
|
msgid "Invalid Trojan URL: parsing failed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/validators/validateUrl.ts:18
|
#: src/validators/validateUrl.ts:8
|
||||||
|
#: src/validators/validateUrl.ts:31
|
||||||
msgid "Invalid URL format"
|
msgid "Invalid URL format"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -482,31 +563,35 @@ msgstr ""
|
|||||||
msgid "Issues detected"
|
msgid "Issues detected"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:452
|
#: src/podkop/tabs/diagnostic/helpers/getPodkopVersionRow.ts:48
|
||||||
msgid "Latest"
|
msgid "Latest"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:257
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:276
|
||||||
msgid "List Update Frequency"
|
msgid "List Update Frequency"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:458
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:546
|
||||||
msgid "Local Domain Lists"
|
msgid "Local Domain Lists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:481
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:569
|
||||||
msgid "Local Subnet Lists"
|
msgid "Local Subnet Lists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:384
|
||||||
|
msgid "Log Level"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:72
|
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:72
|
||||||
msgid "Main DNS"
|
msgid "Main DNS"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:308
|
#: src/podkop/tabs/dashboard/initController.ts:311
|
||||||
msgid "Memory Usage"
|
msgid "Memory Usage"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:586
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:678
|
||||||
msgid "Mixed Proxy Port"
|
msgid "Mixed Proxy Port"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -514,7 +599,11 @@ msgstr ""
|
|||||||
msgid "Monitored Interfaces"
|
msgid "Monitored Interfaces"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:120
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:164
|
||||||
|
msgid "Must be a number in the range of 50 - 1000"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:208
|
||||||
msgid "Network Interface"
|
msgid "Network Interface"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -526,10 +615,17 @@ msgstr ""
|
|||||||
msgid "Not implement yet"
|
msgid "Not implement yet"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:75
|
||||||
|
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:81
|
||||||
|
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:100
|
||||||
|
msgid "Not responding"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:55
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:55
|
||||||
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:63
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:63
|
||||||
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:71
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:71
|
||||||
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:79
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:79
|
||||||
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:87
|
||||||
msgid "Not running"
|
msgid "Not running"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -537,19 +633,15 @@ msgstr ""
|
|||||||
msgid "Operation timed out"
|
msgid "Operation timed out"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:26
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:29
|
||||||
msgid "Outbound Config"
|
msgid "Outbound Config"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:64
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:65
|
||||||
msgid "Outbound Configuration"
|
msgid "Outbound Configuration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/validators/validateOutboundJson.ts:11
|
#: src/podkop/tabs/diagnostic/helpers/getPodkopVersionRow.ts:38
|
||||||
msgid "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:442
|
|
||||||
msgid "Outdated"
|
msgid "Outdated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -561,26 +653,27 @@ msgstr ""
|
|||||||
msgid "Path cannot be empty"
|
msgid "Path cannot be empty"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:347
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:366
|
||||||
msgid "Path must be absolute (start with /)"
|
msgid "Path must be absolute (start with /)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:356
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:375
|
||||||
msgid "Path must contain at least one directory (like /tmp/cache.db)"
|
msgid "Path must contain at least one directory (like /tmp/cache.db)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:351
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:370
|
||||||
msgid "Path must end with cache.db"
|
msgid "Path must end with cache.db"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:95
|
|
||||||
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:103
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:103
|
||||||
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:111
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:111
|
||||||
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:119
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:119
|
||||||
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:127
|
||||||
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:135
|
||||||
msgid "Pending"
|
msgid "Pending"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:340
|
#: src/podkop/tabs/dashboard/initController.ts:343
|
||||||
msgid "Podkop"
|
msgid "Podkop"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -588,11 +681,11 @@ msgstr ""
|
|||||||
msgid "Podkop Settings"
|
msgid "Podkop Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:308
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:327
|
||||||
msgid "Podkop will not modify your DHCP configuration"
|
msgid "Podkop will not modify your DHCP configuration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:34
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:36
|
||||||
msgid "Proxy Configuration URL"
|
msgid "Proxy Configuration URL"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -604,18 +697,22 @@ msgstr ""
|
|||||||
msgid "Proxy traffic is routed via FakeIP"
|
msgid "Proxy traffic is routed via FakeIP"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:245
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:333
|
||||||
msgid "Regional options cannot be used together"
|
msgid "Regional options cannot be used together"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:504
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:592
|
||||||
msgid "Remote Domain Lists"
|
msgid "Remote Domain Lists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:527
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:615
|
||||||
msgid "Remote Subnet Lists"
|
msgid "Remote Subnet Lists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:690
|
||||||
|
msgid "Resolve real IP for routing"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:49
|
#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:49
|
||||||
msgid "Restart podkop"
|
msgid "Restart podkop"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -628,7 +725,7 @@ msgstr ""
|
|||||||
msgid "Router DNS is routed through sing-box"
|
msgid "Router DNS is routed through sing-box"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:376
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:413
|
||||||
msgid "Routing Excluded IPs"
|
msgid "Routing Excluded IPs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -660,15 +757,19 @@ msgstr ""
|
|||||||
msgid "Run Diagnostic"
|
msgid "Run Diagnostic"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:264
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:352
|
||||||
msgid "Russia inside restrictions"
|
msgid "Russia inside restrictions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:257
|
||||||
|
msgid "Secret key for authenticating remote access to YACD when WAN access is enabled."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:36
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:36
|
||||||
msgid "Sections"
|
msgid "Sections"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:212
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:300
|
||||||
msgid "Select a predefined list for routing"
|
msgid "Select a predefined list for routing"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -680,43 +781,47 @@ msgstr ""
|
|||||||
msgid "Select DNS protocol to use"
|
msgid "Select DNS protocol to use"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:258
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:277
|
||||||
msgid "Select how often the domain or subnet lists are updated automatically"
|
msgid "Select how often the domain or subnet lists are updated automatically"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:23
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:24
|
||||||
msgid "Select how to configure the proxy"
|
msgid "Select how to configure the proxy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:121
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:209
|
||||||
msgid "Select network interface for VPN connection"
|
msgid "Select network interface for VPN connection"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:190
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:278
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:25
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:25
|
||||||
msgid "Select or enter DNS server address"
|
msgid "Select or enter DNS server address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:330
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:349
|
||||||
msgid "Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing"
|
msgid "Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:317
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:336
|
||||||
msgid "Select path for sing-box config file. Change this ONLY if you know what you are doing"
|
msgid "Select path for sing-box config file. Change this ONLY if you know what you are doing"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:177
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:265
|
||||||
msgid "Select the DNS protocol type for the domain resolver"
|
msgid "Select the DNS protocol type for the domain resolver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:300
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:388
|
||||||
msgid "Select the list type for adding custom domains"
|
msgid "Select the list type for adding custom domains"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:380
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:468
|
||||||
msgid "Select the list type for adding custom subnets"
|
msgid "Select the list type for adding custom subnets"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:385
|
||||||
|
msgid "Select the log level for sing-box"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:90
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:90
|
||||||
msgid "Select the network interface from which the traffic will originate"
|
msgid "Select the network interface from which the traffic will originate"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -729,7 +834,15 @@ msgstr ""
|
|||||||
msgid "Select the WAN interfaces to be monitored"
|
msgid "Select the WAN interfaces to be monitored"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:337
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:27
|
||||||
|
msgid "Selector"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:88
|
||||||
|
msgid "Selector Proxy Links"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/podkop/tabs/dashboard/initController.ts:340
|
||||||
msgid "Services info"
|
msgid "Services info"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -737,12 +850,12 @@ msgstr ""
|
|||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:289
|
#: src/podkop/tabs/diagnostic/initController.ts:290
|
||||||
#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:116
|
#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:116
|
||||||
msgid "Show sing-box config"
|
msgid "Show sing-box config"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:351
|
#: src/podkop/tabs/dashboard/initController.ts:354
|
||||||
msgid "Sing-box"
|
msgid "Sing-box"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -767,31 +880,31 @@ msgid "Sing-box service exist"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:67
|
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:67
|
||||||
msgid "Sing-box version >= 1.12.4"
|
msgid "Sing-box version is compatible (newer than 1.12.4)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:89
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:89
|
||||||
msgid "Source Network Interface"
|
msgid "Source Network Interface"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:377
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:414
|
||||||
msgid "Specify a local IP address to be excluded from routing"
|
msgid "Specify a local IP address to be excluded from routing"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:551
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:639
|
||||||
msgid "Specify local IP addresses or subnets whose traffic will always be routed through the configured route"
|
msgid "Specify local IP addresses or subnets whose traffic will always be routed through the configured route"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:505
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:593
|
||||||
msgid "Specify remote URLs to download and use domain lists"
|
msgid "Specify remote URLs to download and use domain lists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:528
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:616
|
||||||
msgid "Specify remote URLs to download and use subnet lists"
|
msgid "Specify remote URLs to download and use subnet lists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:459
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:547
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:482
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:570
|
||||||
msgid "Specify the path to the list file located on the router filesystem"
|
msgid "Specify the path to the list file located on the router filesystem"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -807,7 +920,7 @@ msgstr ""
|
|||||||
msgid "Successfully copied!"
|
msgid "Successfully copied!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:301
|
#: src/podkop/tabs/dashboard/initController.ts:304
|
||||||
msgid "System info"
|
msgid "System info"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -823,27 +936,36 @@ msgstr ""
|
|||||||
msgid "Test latency"
|
msgid "Test latency"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:304
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:392
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:472
|
||||||
msgid "Text List"
|
msgid "Text List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:384
|
|
||||||
msgid "Text List (comma/space/newline separated)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:46
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:46
|
||||||
msgid "The DNS server used to look up the IP address of an upstream DNS server"
|
msgid "The DNS server used to look up the IP address of an upstream DNS server"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:135
|
||||||
|
msgid "The interval between connectivity tests"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:148
|
||||||
|
msgid "The maximum difference in response times (ms) allowed when comparing servers"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:171
|
||||||
|
msgid "The URL used to test server connectivity"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:69
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:69
|
||||||
msgid "Time in seconds for DNS record caching (default: 60)"
|
msgid "Time in seconds for DNS record caching (default: 60)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:235
|
#: src/podkop/tabs/dashboard/initController.ts:238
|
||||||
msgid "Traffic"
|
msgid "Traffic"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:265
|
#: src/podkop/tabs/dashboard/initController.ts:268
|
||||||
msgid "Traffic Total"
|
msgid "Traffic Total"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -859,22 +981,22 @@ msgstr ""
|
|||||||
msgid "TTL value cannot be empty"
|
msgid "TTL value cannot be empty"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:181
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:269
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:17
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:17
|
||||||
msgid "UDP (Unprotected DNS)"
|
msgid "UDP (Unprotected DNS)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:110
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:198
|
||||||
msgid "UDP over TCP"
|
msgid "UDP over TCP"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:37
|
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:38
|
#: src/podkop/tabs/diagnostic/initController.ts:38
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:39
|
#: src/podkop/tabs/diagnostic/initController.ts:39
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:40
|
#: src/podkop/tabs/diagnostic/initController.ts:40
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:41
|
#: src/podkop/tabs/diagnostic/initController.ts:41
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:42
|
#: src/podkop/tabs/diagnostic/initController.ts:42
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:416
|
#: src/podkop/tabs/diagnostic/initController.ts:43
|
||||||
|
#: src/podkop/tabs/diagnostic/helpers/getPodkopVersionRow.ts:7
|
||||||
msgid "unknown"
|
msgid "unknown"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -882,48 +1004,60 @@ msgstr ""
|
|||||||
msgid "Unknown error"
|
msgid "Unknown error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:237
|
#: src/podkop/tabs/dashboard/initController.ts:240
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:268
|
#: src/podkop/tabs/dashboard/initController.ts:271
|
||||||
msgid "Uplink"
|
msgid "Uplink"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/validators/validateProxyUrl.ts:29
|
#: src/validators/validateProxyUrl.ts:37
|
||||||
msgid "URL must start with vless://, ss://, trojan://, or socks4/5://"
|
msgid "URL must start with vless://, ss://, trojan://, socks4/5://, or hysteria2://hy2://"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/validators/validateUrl.ts:13
|
#: src/validators/validateUrl.ts:17
|
||||||
msgid "URL must use one of the following protocols:"
|
msgid "URL must use one of the following protocols:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:27
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:28
|
||||||
msgid "URLTest"
|
msgid "URLTest"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:87
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:134
|
||||||
|
msgid "URLTest Check Interval"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:111
|
||||||
msgid "URLTest Proxy Links"
|
msgid "URLTest Proxy Links"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:299
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:170
|
||||||
|
msgid "URLTest Testing URL"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:147
|
||||||
|
msgid "URLTest Tolerance"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:387
|
||||||
msgid "User Domain List Type"
|
msgid "User Domain List Type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:311
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:399
|
||||||
msgid "User Domains"
|
msgid "User Domains"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:337
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:425
|
||||||
msgid "User Domains List"
|
msgid "User Domains List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:379
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:467
|
||||||
msgid "User Subnet List Type"
|
msgid "User Subnet List Type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:391
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:479
|
||||||
msgid "User Subnets"
|
msgid "User Subnets"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:417
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:505
|
||||||
msgid "User Subnets List"
|
msgid "User Subnets List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -931,24 +1065,25 @@ msgstr ""
|
|||||||
#: src/validators/validateDns.ts:18
|
#: src/validators/validateDns.ts:18
|
||||||
#: src/validators/validateDomain.ts:13
|
#: src/validators/validateDomain.ts:13
|
||||||
#: src/validators/validateDomain.ts:30
|
#: src/validators/validateDomain.ts:30
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:120
|
||||||
#: src/validators/validateIp.ts:8
|
#: src/validators/validateIp.ts:8
|
||||||
#: src/validators/validateOutboundJson.ts:17
|
#: src/validators/validateOutboundJson.ts:7
|
||||||
#: src/validators/validatePath.ts:16
|
#: src/validators/validatePath.ts:16
|
||||||
#: src/validators/validateShadowsocksUrl.ts:95
|
#: src/validators/validateShadowsocksUrl.ts:95
|
||||||
#: src/validators/validateSocksUrl.ts:80
|
#: src/validators/validateSocksUrl.ts:80
|
||||||
#: src/validators/validateSubnet.ts:38
|
#: src/validators/validateSubnet.ts:38
|
||||||
#: src/validators/validateTrojanUrl.ts:59
|
#: src/validators/validateTrojanUrl.ts:59
|
||||||
#: src/validators/validateUrl.ts:16
|
#: src/validators/validateUrl.ts:28
|
||||||
#: src/validators/validateVlessUrl.ts:108
|
#: src/validators/validateVlessUrl.ts:108
|
||||||
msgid "Valid"
|
msgid "Valid"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:370
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:458
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:449
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:537
|
||||||
msgid "Validation errors:"
|
msgid "Validation errors:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:255
|
#: src/podkop/tabs/diagnostic/initController.ts:256
|
||||||
#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:107
|
#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:107
|
||||||
msgid "View logs"
|
msgid "View logs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -957,14 +1092,24 @@ msgstr ""
|
|||||||
msgid "Visit Wiki"
|
msgid "Visit Wiki"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:247
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:37
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:89
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:112
|
||||||
|
msgid "vless://, ss://, trojan://, socks4/5://, hy2/hysteria2:// links"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:335
|
||||||
msgid "Warning: %s cannot be used together with %s. Previous selections have been removed."
|
msgid "Warning: %s cannot be used together with %s. Previous selections have been removed."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:266
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:354
|
||||||
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
|
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:256
|
||||||
|
msgid "YACD Secret Key"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:127
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:127
|
||||||
msgid "You can select Output Network Interface, by default autodetect"
|
msgid "You can select Output Network Interface, by default autodetect"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
# RU translations for PODKOP package.
|
# RU translations for PODKOP package.
|
||||||
# Copyright (C) 2025 THE PODKOP'S COPYRIGHT HOLDER
|
# Copyright (C) 2026 THE PODKOP'S COPYRIGHT HOLDER
|
||||||
# This file is distributed under the same license as the PODKOP package.
|
# This file is distributed under the same license as the PODKOP package.
|
||||||
# divocat, 2025.
|
# divocatt, 2026.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PODKOP\n"
|
"Project-Id-Version: PODKOP\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-10-23 20:43+0300\n"
|
"POT-Creation-Date: 2026-05-29 16:40+0300\n"
|
||||||
"PO-Revision-Date: 2025-10-23 20:43+0300\n"
|
"PO-Revision-Date: 2026-05-29 16:40+0300\n"
|
||||||
"Last-Translator: divocat\n"
|
"Last-Translator: divocatt\n"
|
||||||
"Language-Team: none\n"
|
"Language-Team: none\n"
|
||||||
"Language: ru\n"
|
"Language: ru\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@@ -35,6 +35,9 @@ msgstr "Активные соединения"
|
|||||||
msgid "Additional marking rules found"
|
msgid "Additional marking rules found"
|
||||||
msgstr "Найдены дополнительные правила маркировки"
|
msgstr "Найдены дополнительные правила маркировки"
|
||||||
|
|
||||||
|
msgid "Allows access to YACD from the WAN. Make sure to open the appropriate port in your firewall."
|
||||||
|
msgstr "Обеспечивает доступ к YACD из WAN. Убедитесь, что в брандмауэре открыт соответствующий порт."
|
||||||
|
|
||||||
msgid "Applicable for SOCKS and Shadowsocks proxy"
|
msgid "Applicable for SOCKS and Shadowsocks proxy"
|
||||||
msgstr "Применимо для SOCKS и Shadowsocks прокси"
|
msgstr "Применимо для SOCKS и Shadowsocks прокси"
|
||||||
|
|
||||||
@@ -182,9 +185,6 @@ msgstr "Скачивать списки через Proxy/VPN"
|
|||||||
msgid "Download Lists via specific proxy section"
|
msgid "Download Lists via specific proxy section"
|
||||||
msgstr "Скачивать списки через выбранную секцию"
|
msgstr "Скачивать списки через выбранную секцию"
|
||||||
|
|
||||||
msgid "Downloading all lists via main Proxy/VPN"
|
|
||||||
msgstr "Загрузка всех списков через основной прокси/VPN"
|
|
||||||
|
|
||||||
msgid "Downloading all lists via specific Proxy/VPN"
|
msgid "Downloading all lists via specific Proxy/VPN"
|
||||||
msgstr "Загрузка всех списков через указанный прокси/VPN"
|
msgstr "Загрузка всех списков через указанный прокси/VPN"
|
||||||
|
|
||||||
@@ -197,6 +197,9 @@ msgstr "Включить автостарт"
|
|||||||
msgid "Enable built-in DNS resolver for domains handled by this section"
|
msgid "Enable built-in DNS resolver for domains handled by this section"
|
||||||
msgstr "Включить встроенный DNS-резолвер для доменов, обрабатываемых в этом разделе"
|
msgstr "Включить встроенный DNS-резолвер для доменов, обрабатываемых в этом разделе"
|
||||||
|
|
||||||
|
msgid "Enable DNS resolve to get real IP when routing"
|
||||||
|
msgstr "Разрешать домены в реальные IP-адреса перед маршрутизацией в outbound"
|
||||||
|
|
||||||
msgid "Enable Mixed Proxy"
|
msgid "Enable Mixed Proxy"
|
||||||
msgstr "Включить смешанный прокси"
|
msgstr "Включить смешанный прокси"
|
||||||
|
|
||||||
@@ -209,6 +212,9 @@ msgstr "Включить смешанный прокси-сервер, разр
|
|||||||
msgid "Enable YACD"
|
msgid "Enable YACD"
|
||||||
msgstr "Включить YACD"
|
msgstr "Включить YACD"
|
||||||
|
|
||||||
|
msgid "Enable YACD WAN Access"
|
||||||
|
msgstr "Включить доступ YACD WAN"
|
||||||
|
|
||||||
msgid "Enter complete outbound configuration in JSON format"
|
msgid "Enter complete outbound configuration in JSON format"
|
||||||
msgstr "Введите полную конфигурацию исходящего соединения в формате JSON"
|
msgstr "Введите полную конфигурацию исходящего соединения в формате JSON"
|
||||||
|
|
||||||
@@ -221,6 +227,18 @@ msgstr "Введите доменные имена без протоколов,
|
|||||||
msgid "Enter subnets in CIDR notation (e.g. 103.21.244.0/22) or single IP addresses"
|
msgid "Enter subnets in CIDR notation (e.g. 103.21.244.0/22) or single IP addresses"
|
||||||
msgstr "Введите подсети в нотации CIDR (например, 103.21.244.0/22) или отдельные IP-адреса"
|
msgstr "Введите подсети в нотации CIDR (например, 103.21.244.0/22) или отдельные IP-адреса"
|
||||||
|
|
||||||
|
msgid "Every 1 minute"
|
||||||
|
msgstr "Каждую минуту"
|
||||||
|
|
||||||
|
msgid "Every 3 minutes"
|
||||||
|
msgstr "Каждые 3 минуты"
|
||||||
|
|
||||||
|
msgid "Every 30 seconds"
|
||||||
|
msgstr "Каждые 30 секунд"
|
||||||
|
|
||||||
|
msgid "Every 5 minutes"
|
||||||
|
msgstr "Каждые 5 минут"
|
||||||
|
|
||||||
msgid "Exclude NTP"
|
msgid "Exclude NTP"
|
||||||
msgstr "Исключить NTP"
|
msgstr "Исключить NTP"
|
||||||
|
|
||||||
@@ -266,6 +284,45 @@ msgstr "Неверный домен"
|
|||||||
msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y"
|
msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y"
|
||||||
msgstr "Неверный формат. Используйте X.X.X.X или X.X.X.X/Y"
|
msgstr "Неверный формат. Используйте X.X.X.X или X.X.X.X/Y"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: insecure must be 0 or 1"
|
||||||
|
msgstr "Неверный URL Hysteria2: параметр insecure должен быть 0 или 1"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: invalid port number"
|
||||||
|
msgstr "Неверный URL Hysteria2: неверный номер порта"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: missing credentials/server"
|
||||||
|
msgstr "Неверный URL Hysteria2: отсутствуют учетные данные/сервер"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: missing host"
|
||||||
|
msgstr "Неверный URL Hysteria2: отсутствует хост"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: missing host & port"
|
||||||
|
msgstr "Неверный URL Hysteria2: отсутствуют хост и порт"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: missing password"
|
||||||
|
msgstr "Неверный URL Hysteria2: отсутствует пароль"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: missing port"
|
||||||
|
msgstr "Неверный URL Hysteria2: отсутствует порт"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: must not contain spaces"
|
||||||
|
msgstr "Неверный URL Hysteria2: не должен содержать пробелов"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: must start with hysteria2:// or hy2://"
|
||||||
|
msgstr "Неверный URL Hysteria2: должен начинаться с hysteria2:// или hy2://"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: obfs-password required when obfs is set"
|
||||||
|
msgstr "Неверный URL Hysteria2: требуется obfs-password, когда установлен obfs"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: parsing failed"
|
||||||
|
msgstr "Неверный URL Hysteria2: ошибка разбора"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: sni cannot be empty"
|
||||||
|
msgstr "Неверный URL Hysteria2: sni не может быть пустым"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: unsupported obfs type"
|
||||||
|
msgstr "Неверный URL Hysteria2: неподдерживаемый тип obfs"
|
||||||
|
|
||||||
msgid "Invalid IP address"
|
msgid "Invalid IP address"
|
||||||
msgstr "Неверный IP-адрес"
|
msgstr "Неверный IP-адрес"
|
||||||
|
|
||||||
@@ -365,6 +422,9 @@ msgstr "Локальные списки доменов"
|
|||||||
msgid "Local Subnet Lists"
|
msgid "Local Subnet Lists"
|
||||||
msgstr "Локальные списки подсетей"
|
msgstr "Локальные списки подсетей"
|
||||||
|
|
||||||
|
msgid "Log Level"
|
||||||
|
msgstr "Уровень логов"
|
||||||
|
|
||||||
msgid "Main DNS"
|
msgid "Main DNS"
|
||||||
msgstr "Основной DNS"
|
msgstr "Основной DNS"
|
||||||
|
|
||||||
@@ -377,6 +437,9 @@ msgstr "Порт смешанного прокси"
|
|||||||
msgid "Monitored Interfaces"
|
msgid "Monitored Interfaces"
|
||||||
msgstr "Наблюдаемые интерфейсы"
|
msgstr "Наблюдаемые интерфейсы"
|
||||||
|
|
||||||
|
msgid "Must be a number in the range of 50 - 1000"
|
||||||
|
msgstr "Должно быть числом от 50 до 1000"
|
||||||
|
|
||||||
msgid "Network Interface"
|
msgid "Network Interface"
|
||||||
msgstr "Сетевой интерфейс"
|
msgstr "Сетевой интерфейс"
|
||||||
|
|
||||||
@@ -386,6 +449,9 @@ msgstr "Другие правила маркировки не найдены"
|
|||||||
msgid "Not implement yet"
|
msgid "Not implement yet"
|
||||||
msgstr "Ещё не реализовано"
|
msgstr "Ещё не реализовано"
|
||||||
|
|
||||||
|
msgid "Not responding"
|
||||||
|
msgstr "Не отвечает"
|
||||||
|
|
||||||
msgid "Not running"
|
msgid "Not running"
|
||||||
msgstr "Не запущено"
|
msgstr "Не запущено"
|
||||||
|
|
||||||
@@ -398,9 +464,6 @@ msgstr "Конфигурация Outbound"
|
|||||||
msgid "Outbound Configuration"
|
msgid "Outbound Configuration"
|
||||||
msgstr "Конфигурация исходящего соединения"
|
msgstr "Конфигурация исходящего соединения"
|
||||||
|
|
||||||
msgid "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields"
|
|
||||||
msgstr "JSON должен содержать поля \"type\", \"server\" и \"server_port\""
|
|
||||||
|
|
||||||
msgid "Outdated"
|
msgid "Outdated"
|
||||||
msgstr "Устаревшая"
|
msgstr "Устаревшая"
|
||||||
|
|
||||||
@@ -449,6 +512,9 @@ msgstr "Внешние списки доменов"
|
|||||||
msgid "Remote Subnet Lists"
|
msgid "Remote Subnet Lists"
|
||||||
msgstr "Внешние списки подсетей"
|
msgstr "Внешние списки подсетей"
|
||||||
|
|
||||||
|
msgid "Resolve real IP for routing"
|
||||||
|
msgstr "Разрешение реальных IP-адресов"
|
||||||
|
|
||||||
msgid "Restart podkop"
|
msgid "Restart podkop"
|
||||||
msgstr "Перезапустить Podkop"
|
msgstr "Перезапустить Podkop"
|
||||||
|
|
||||||
@@ -485,6 +551,9 @@ msgstr "Запустить диагностику"
|
|||||||
msgid "Russia inside restrictions"
|
msgid "Russia inside restrictions"
|
||||||
msgstr "Ограничения Russia inside"
|
msgstr "Ограничения Russia inside"
|
||||||
|
|
||||||
|
msgid "Secret key for authenticating remote access to YACD when WAN access is enabled."
|
||||||
|
msgstr "Секретный ключ для аутентификации удаленного доступа к YACD при включенном доступе через WAN."
|
||||||
|
|
||||||
msgid "Sections"
|
msgid "Sections"
|
||||||
msgstr "Секции"
|
msgstr "Секции"
|
||||||
|
|
||||||
@@ -524,6 +593,9 @@ msgstr "Выберите тип списка для добавления пол
|
|||||||
msgid "Select the list type for adding custom subnets"
|
msgid "Select the list type for adding custom subnets"
|
||||||
msgstr "Выберите тип списка для добавления пользовательских подсетей"
|
msgstr "Выберите тип списка для добавления пользовательских подсетей"
|
||||||
|
|
||||||
|
msgid "Select the log level for sing-box"
|
||||||
|
msgstr "Выберите уровень логов для sing-box"
|
||||||
|
|
||||||
msgid "Select the network interface from which the traffic will originate"
|
msgid "Select the network interface from which the traffic will originate"
|
||||||
msgstr "Выберите сетевой интерфейс, с которого будет исходить трафик"
|
msgstr "Выберите сетевой интерфейс, с которого будет исходить трафик"
|
||||||
|
|
||||||
@@ -533,6 +605,12 @@ msgstr "Выберите сетевой интерфейс, на который
|
|||||||
msgid "Select the WAN interfaces to be monitored"
|
msgid "Select the WAN interfaces to be monitored"
|
||||||
msgstr "Выберите WAN интерфейсы для мониторинга"
|
msgstr "Выберите WAN интерфейсы для мониторинга"
|
||||||
|
|
||||||
|
msgid "Selector"
|
||||||
|
msgstr "Selector"
|
||||||
|
|
||||||
|
msgid "Selector Proxy Links"
|
||||||
|
msgstr "Ссылки прокси для Selector"
|
||||||
|
|
||||||
msgid "Services info"
|
msgid "Services info"
|
||||||
msgstr "Информация о сервисах"
|
msgstr "Информация о сервисах"
|
||||||
|
|
||||||
@@ -560,8 +638,8 @@ msgstr "Процесс sing-box запущен"
|
|||||||
msgid "Sing-box service exist"
|
msgid "Sing-box service exist"
|
||||||
msgstr "Сервис sing-box существует"
|
msgstr "Сервис sing-box существует"
|
||||||
|
|
||||||
msgid "Sing-box version >= 1.12.4"
|
msgid "Sing-box version is compatible (newer than 1.12.4)"
|
||||||
msgstr "Версия sing-box >= 1.12.4"
|
msgstr "Версия Sing-box совместима (новее 1.12.4)"
|
||||||
|
|
||||||
msgid "Source Network Interface"
|
msgid "Source Network Interface"
|
||||||
msgstr "Сетевой интерфейс источника"
|
msgstr "Сетевой интерфейс источника"
|
||||||
@@ -605,12 +683,18 @@ msgstr "Тестирование задержки"
|
|||||||
msgid "Text List"
|
msgid "Text List"
|
||||||
msgstr "Текстовый список"
|
msgstr "Текстовый список"
|
||||||
|
|
||||||
msgid "Text List (comma/space/newline separated)"
|
|
||||||
msgstr "Текстовый список (через запятую, пробел или новую строку)"
|
|
||||||
|
|
||||||
msgid "The DNS server used to look up the IP address of an upstream DNS server"
|
msgid "The DNS server used to look up the IP address of an upstream DNS server"
|
||||||
msgstr "DNS-сервер, используемый для поиска IP-адреса вышестоящего DNS-сервера"
|
msgstr "DNS-сервер, используемый для поиска IP-адреса вышестоящего DNS-сервера"
|
||||||
|
|
||||||
|
msgid "The interval between connectivity tests"
|
||||||
|
msgstr "Интервал между тестами подключения"
|
||||||
|
|
||||||
|
msgid "The maximum difference in response times (ms) allowed when comparing servers"
|
||||||
|
msgstr "Максимально допустимая разница во времени отклика (мс) при сравнении серверов"
|
||||||
|
|
||||||
|
msgid "The URL used to test server connectivity"
|
||||||
|
msgstr "URL-адрес, используемый для проверки подключения к серверу"
|
||||||
|
|
||||||
msgid "Time in seconds for DNS record caching (default: 60)"
|
msgid "Time in seconds for DNS record caching (default: 60)"
|
||||||
msgstr "Время в секундах для кэширования DNS записей (по умолчанию: 60)"
|
msgstr "Время в секундах для кэширования DNS записей (по умолчанию: 60)"
|
||||||
|
|
||||||
@@ -644,8 +728,8 @@ msgstr "Неизвестная ошибка"
|
|||||||
msgid "Uplink"
|
msgid "Uplink"
|
||||||
msgstr "Исходящий"
|
msgstr "Исходящий"
|
||||||
|
|
||||||
msgid "URL must start with vless://, ss://, trojan://, or socks4/5://"
|
msgid "URL must start with vless://, ss://, trojan://, socks4/5://, or hysteria2://hy2://"
|
||||||
msgstr "URL должен начинаться с vless://, ss://, trojan:// или socks4/5://"
|
msgstr "URL должен начинаться с vless://, ss://, trojan://, socks4/5:// или hysteria2:// hy2://"
|
||||||
|
|
||||||
msgid "URL must use one of the following protocols:"
|
msgid "URL must use one of the following protocols:"
|
||||||
msgstr "URL должен использовать один из следующих протоколов:"
|
msgstr "URL должен использовать один из следующих протоколов:"
|
||||||
@@ -653,9 +737,18 @@ msgstr "URL должен использовать один из следующи
|
|||||||
msgid "URLTest"
|
msgid "URLTest"
|
||||||
msgstr "URLTest"
|
msgstr "URLTest"
|
||||||
|
|
||||||
|
msgid "URLTest Check Interval"
|
||||||
|
msgstr "Интервал проверки URLTest"
|
||||||
|
|
||||||
msgid "URLTest Proxy Links"
|
msgid "URLTest Proxy Links"
|
||||||
msgstr "Ссылки прокси для URLTest"
|
msgstr "Ссылки прокси для URLTest"
|
||||||
|
|
||||||
|
msgid "URLTest Testing URL"
|
||||||
|
msgstr "URLTest ссылка для проверки"
|
||||||
|
|
||||||
|
msgid "URLTest Tolerance"
|
||||||
|
msgstr "URLTest допустимое отклонение"
|
||||||
|
|
||||||
msgid "User Domain List Type"
|
msgid "User Domain List Type"
|
||||||
msgstr "Тип пользовательского списка доменов"
|
msgstr "Тип пользовательского списка доменов"
|
||||||
|
|
||||||
@@ -686,11 +779,17 @@ msgstr "Посмотреть логи"
|
|||||||
msgid "Visit Wiki"
|
msgid "Visit Wiki"
|
||||||
msgstr "Перейти в wiki"
|
msgstr "Перейти в wiki"
|
||||||
|
|
||||||
|
msgid "vless://, ss://, trojan://, socks4/5://, hy2/hysteria2:// links"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Warning: %s cannot be used together with %s. Previous selections have been removed."
|
msgid "Warning: %s cannot be used together with %s. Previous selections have been removed."
|
||||||
msgstr "Предупреждение: %s нельзя использовать вместе с %s. Предыдущие варианты были удалены."
|
msgstr "Предупреждение: %s нельзя использовать вместе с %s. Предыдущие варианты были удалены."
|
||||||
|
|
||||||
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
|
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 и будет удален из выбранных."
|
msgstr "Предупреждение: Russia inside может быть использован только с %s. %s уже есть в Russia inside и будет удален из выбранных."
|
||||||
|
|
||||||
|
msgid "YACD Secret Key"
|
||||||
|
msgstr "Секретный ключ YACD"
|
||||||
|
|
||||||
msgid "You can select Output Network Interface, by default autodetect"
|
msgid "You can select Output Network Interface, by default autodetect"
|
||||||
msgstr "Вы можете выбрать выходной сетевой интерфейс, по умолчанию он определяется автоматически."
|
msgstr "Вы можете выбрать выходной сетевой интерфейс, по умолчанию он определяется автоматически."
|
||||||
|
|||||||
@@ -13,11 +13,11 @@
|
|||||||
"test": "vitest",
|
"test": "vitest",
|
||||||
"ci": "yarn format && yarn lint --max-warnings=0 && yarn test --run && yarn build",
|
"ci": "yarn format && yarn lint --max-warnings=0 && yarn test --run && yarn build",
|
||||||
"watch:sftp": "node watch-upload.js",
|
"watch:sftp": "node watch-upload.js",
|
||||||
"locales:exctract-calls": "node extract-calls.js",
|
"locales:extract-calls": "node extract-calls.js",
|
||||||
"locales:generate-pot": "node generate-pot.js",
|
"locales:generate-pot": "node generate-pot.js",
|
||||||
"locales:generate-po:ru": "node generate-po.js ru",
|
"locales:generate-po:ru": "node generate-po.js ru",
|
||||||
"locales:distribute": "node distribute-locales.js",
|
"locales:distribute": "node distribute-locales.js",
|
||||||
"locales:actualize": "yarn locales:exctract-calls && yarn locales:generate-pot && yarn locales:generate-po:ru && yarn locales:distribute"
|
"locales:actualize": "yarn locales:extract-calls && yarn locales:generate-pot && yarn locales:generate-po:ru && yarn locales:distribute"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/parser": "7.28.4",
|
"@babel/parser": "7.28.4",
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ export const ALLOWED_WITH_RUSSIA_INSIDE = [
|
|||||||
'hetzner',
|
'hetzner',
|
||||||
'ovh',
|
'ovh',
|
||||||
'hodca',
|
'hodca',
|
||||||
|
'roblox',
|
||||||
'digitalocean',
|
'digitalocean',
|
||||||
'cloudfront',
|
'cloudfront',
|
||||||
];
|
];
|
||||||
@@ -50,6 +51,7 @@ export const DOMAIN_LIST_OPTIONS = {
|
|||||||
google_ai: 'Google AI',
|
google_ai: 'Google AI',
|
||||||
google_play: 'Google Play',
|
google_play: 'Google Play',
|
||||||
hodca: 'H.O.D.C.A',
|
hodca: 'H.O.D.C.A',
|
||||||
|
roblox: 'Roblox',
|
||||||
hetzner: 'Hetzner ASN',
|
hetzner: 'Hetzner ASN',
|
||||||
ovh: 'OVH ASN',
|
ovh: 'OVH ASN',
|
||||||
digitalocean: 'Digital Ocean ASN',
|
digitalocean: 'Digital Ocean ASN',
|
||||||
|
|||||||
3
fe-app-podkop/src/helpers/removeVersionPrefix.ts
Normal file
3
fe-app-podkop/src/helpers/removeVersionPrefix.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export function removeVersionPrefix(version: string) {
|
||||||
|
return version.replace(/^v/, '');
|
||||||
|
}
|
||||||
@@ -4,6 +4,9 @@
|
|||||||
'require uci';
|
'require uci';
|
||||||
'require ui';
|
'require ui';
|
||||||
|
|
||||||
|
if (typeof structuredClone !== 'function')
|
||||||
|
globalThis.structuredClone = (obj) => JSON.parse(JSON.stringify(obj));
|
||||||
|
|
||||||
export * from './validators';
|
export * from './validators';
|
||||||
export * from './helpers';
|
export * from './helpers';
|
||||||
export * from './podkop';
|
export * from './podkop';
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { getConfigSections } from './getConfigSections';
|
||||||
|
|
||||||
|
export async function getClashApiSecret() {
|
||||||
|
const sections = await getConfigSections();
|
||||||
|
|
||||||
|
const settings = sections.find((section) => section['.type'] === 'settings');
|
||||||
|
|
||||||
|
return settings?.yacd_secret_key || '';
|
||||||
|
}
|
||||||
@@ -29,7 +29,9 @@ export async function getDashboardSections(): Promise<IGetDashboardSectionsRespo
|
|||||||
const data = configSections
|
const data = configSections
|
||||||
.filter(
|
.filter(
|
||||||
(section) =>
|
(section) =>
|
||||||
section.connection_type !== 'block' && section['.type'] !== 'settings',
|
section.connection_type !== 'block' &&
|
||||||
|
section.connection_type !== 'exclusion' &&
|
||||||
|
section['.type'] !== 'settings',
|
||||||
)
|
)
|
||||||
.map((section) => {
|
.map((section) => {
|
||||||
if (section.connection_type === 'proxy') {
|
if (section.connection_type === 'proxy') {
|
||||||
@@ -86,6 +88,37 @@ export async function getDashboardSections(): Promise<IGetDashboardSectionsRespo
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (section.proxy_config_type === 'selector') {
|
||||||
|
const selector = proxies.find(
|
||||||
|
(proxy) => proxy.code === `${section['.name']}-out`,
|
||||||
|
);
|
||||||
|
|
||||||
|
const links = section.selector_proxy_links ?? [];
|
||||||
|
|
||||||
|
const outbounds = links
|
||||||
|
.map((link, index) => ({
|
||||||
|
link,
|
||||||
|
outbound: proxies.find(
|
||||||
|
(item) => item.code === `${section['.name']}-${index + 1}-out`,
|
||||||
|
),
|
||||||
|
}))
|
||||||
|
.map((item) => ({
|
||||||
|
code: item?.outbound?.code || '',
|
||||||
|
displayName:
|
||||||
|
getProxyUrlName(item.link) || item?.outbound?.value?.name || '',
|
||||||
|
latency: item?.outbound?.value?.history?.[0]?.delay || 0,
|
||||||
|
type: item?.outbound?.value?.type || '',
|
||||||
|
selected: selector?.value?.now === item?.outbound?.code,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return {
|
||||||
|
withTagSelect: true,
|
||||||
|
code: selector?.code || section['.name'],
|
||||||
|
displayName: section['.name'],
|
||||||
|
outbounds,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (section.proxy_config_type === 'urltest') {
|
if (section.proxy_config_type === 'urltest') {
|
||||||
const selector = proxies.find(
|
const selector = proxies.find(
|
||||||
(proxy) => proxy.code === `${section['.name']}-out`,
|
(proxy) => proxy.code === `${section['.name']}-out`,
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { getConfigSections } from './getConfigSections';
|
import { getConfigSections } from './getConfigSections';
|
||||||
import { getDashboardSections } from './getDashboardSections';
|
import { getDashboardSections } from './getDashboardSections';
|
||||||
|
import { getClashApiSecret } from './getClashApiSecret';
|
||||||
|
|
||||||
export const CustomPodkopMethods = {
|
export const CustomPodkopMethods = {
|
||||||
getConfigSections,
|
getConfigSections,
|
||||||
getDashboardSections,
|
getDashboardSections,
|
||||||
|
getClashApiSecret,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,15 +29,15 @@ export const PodkopShellMethods = {
|
|||||||
Podkop.AvailableClashAPIMethods.GET_PROXIES,
|
Podkop.AvailableClashAPIMethods.GET_PROXIES,
|
||||||
]),
|
]),
|
||||||
getClashApiProxyLatency: async (tag: string) =>
|
getClashApiProxyLatency: async (tag: string) =>
|
||||||
callBaseMethod<unknown>(Podkop.AvailableMethods.CLASH_API, [
|
callBaseMethod<Podkop.GetClashApiProxyLatency>(
|
||||||
Podkop.AvailableClashAPIMethods.GET_PROXY_LATENCY,
|
Podkop.AvailableMethods.CLASH_API,
|
||||||
tag,
|
[Podkop.AvailableClashAPIMethods.GET_PROXY_LATENCY, tag, '5000'],
|
||||||
]),
|
),
|
||||||
getClashApiGroupLatency: async (tag: string) =>
|
getClashApiGroupLatency: async (tag: string) =>
|
||||||
callBaseMethod<unknown>(Podkop.AvailableMethods.CLASH_API, [
|
callBaseMethod<Podkop.GetClashApiGroupLatency>(
|
||||||
Podkop.AvailableClashAPIMethods.GET_GROUP_LATENCY,
|
Podkop.AvailableMethods.CLASH_API,
|
||||||
tag,
|
[Podkop.AvailableClashAPIMethods.GET_GROUP_LATENCY, tag, '10000'],
|
||||||
]),
|
),
|
||||||
setClashApiGroupProxy: async (group: string, proxy: string) =>
|
setClashApiGroupProxy: async (group: string, proxy: string) =>
|
||||||
callBaseMethod<unknown>(Podkop.AvailableMethods.CLASH_API, [
|
callBaseMethod<unknown>(Podkop.AvailableMethods.CLASH_API, [
|
||||||
Podkop.AvailableClashAPIMethods.SET_GROUP_PROXY,
|
Podkop.AvailableClashAPIMethods.SET_GROUP_PROXY,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { CustomPodkopMethods, PodkopShellMethods } from '../../methods';
|
|||||||
import { logger, socket, store, StoreType } from '../../services';
|
import { logger, socket, store, StoreType } from '../../services';
|
||||||
import { renderSections, renderWidget } from './partials';
|
import { renderSections, renderWidget } from './partials';
|
||||||
import { fetchServicesInfo } from '../../fetchers';
|
import { fetchServicesInfo } from '../../fetchers';
|
||||||
|
import { getClashApiSecret } from '../../methods/custom/getClashApiSecret';
|
||||||
|
|
||||||
// Fetchers
|
// Fetchers
|
||||||
|
|
||||||
@@ -38,8 +39,10 @@ async function fetchDashboardSections() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function connectToClashSockets() {
|
async function connectToClashSockets() {
|
||||||
|
const clashApiSecret = await getClashApiSecret();
|
||||||
|
|
||||||
socket.subscribe(
|
socket.subscribe(
|
||||||
`${getClashWsUrl()}/traffic?token=`,
|
`${getClashWsUrl()}/traffic?token=${clashApiSecret}`,
|
||||||
(msg) => {
|
(msg) => {
|
||||||
const parsedMsg = JSON.parse(msg);
|
const parsedMsg = JSON.parse(msg);
|
||||||
|
|
||||||
@@ -68,7 +71,7 @@ async function connectToClashSockets() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
socket.subscribe(
|
socket.subscribe(
|
||||||
`${getClashWsUrl()}/connections?token=`,
|
`${getClashWsUrl()}/connections?token=${clashApiSecret}`,
|
||||||
(msg) => {
|
(msg) => {
|
||||||
const parsedMsg = JSON.parse(msg);
|
const parsedMsg = JSON.parse(msg);
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export enum DIAGNOSTICS_CHECKS {
|
|||||||
SINGBOX = 'SINGBOX',
|
SINGBOX = 'SINGBOX',
|
||||||
NFT = 'NFT',
|
NFT = 'NFT',
|
||||||
FAKEIP = 'FAKEIP',
|
FAKEIP = 'FAKEIP',
|
||||||
|
OUTBOUNDS = 'OUTBOUNDS',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DIAGNOSTICS_CHECKS_MAP: Record<
|
export const DIAGNOSTICS_CHECKS_MAP: Record<
|
||||||
@@ -26,8 +27,13 @@ export const DIAGNOSTICS_CHECKS_MAP: Record<
|
|||||||
title: getCheckTitle('Nftables'),
|
title: getCheckTitle('Nftables'),
|
||||||
code: DIAGNOSTICS_CHECKS.NFT,
|
code: DIAGNOSTICS_CHECKS.NFT,
|
||||||
},
|
},
|
||||||
[DIAGNOSTICS_CHECKS.FAKEIP]: {
|
[DIAGNOSTICS_CHECKS.OUTBOUNDS]: {
|
||||||
order: 4,
|
order: 4,
|
||||||
|
title: getCheckTitle('Outbounds'),
|
||||||
|
code: DIAGNOSTICS_CHECKS.OUTBOUNDS,
|
||||||
|
},
|
||||||
|
[DIAGNOSTICS_CHECKS.FAKEIP]: {
|
||||||
|
order: 5,
|
||||||
title: getCheckTitle('FakeIP'),
|
title: getCheckTitle('FakeIP'),
|
||||||
code: DIAGNOSTICS_CHECKS.FAKEIP,
|
code: DIAGNOSTICS_CHECKS.FAKEIP,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,132 @@
|
|||||||
|
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||||
|
import { PodkopShellMethods } from '../../../methods';
|
||||||
|
import { updateCheckStore } from './updateCheckStore';
|
||||||
|
import { getMeta } from '../helpers/getMeta';
|
||||||
|
import { getDashboardSections } from '../../../methods/custom/getDashboardSections';
|
||||||
|
import { IDiagnosticsChecksItem } from '../../../services';
|
||||||
|
|
||||||
|
export async function runSectionsCheck() {
|
||||||
|
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS;
|
||||||
|
|
||||||
|
updateCheckStore({
|
||||||
|
order,
|
||||||
|
code,
|
||||||
|
title,
|
||||||
|
description: _('Checking, please wait'),
|
||||||
|
state: 'loading',
|
||||||
|
items: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const sections = await getDashboardSections();
|
||||||
|
|
||||||
|
if (!sections.success) {
|
||||||
|
updateCheckStore({
|
||||||
|
order,
|
||||||
|
code,
|
||||||
|
title,
|
||||||
|
description: _('Cannot receive checks result'),
|
||||||
|
state: 'error',
|
||||||
|
items: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
throw new Error('Sections checks failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
const items = (await Promise.all(
|
||||||
|
sections.data.map(async (section) => {
|
||||||
|
async function getLatency() {
|
||||||
|
if (section.withTagSelect) {
|
||||||
|
const latencyGroup = await PodkopShellMethods.getClashApiGroupLatency(
|
||||||
|
section.code,
|
||||||
|
);
|
||||||
|
|
||||||
|
const selectedOutbound = section.outbounds.find(
|
||||||
|
(item) => item.selected,
|
||||||
|
);
|
||||||
|
|
||||||
|
const isUrlTest = selectedOutbound?.type === 'URLTest';
|
||||||
|
|
||||||
|
const success = latencyGroup.success && !latencyGroup.data.message;
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
if (isUrlTest) {
|
||||||
|
const latency = Object.values(latencyGroup.data)
|
||||||
|
.map((item) => (item ? `${item}ms` : 'n/a'))
|
||||||
|
.join(' / ');
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
latency: `[${_('Fastest')}] ${latency}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedProxyDelay =
|
||||||
|
latencyGroup.data?.[selectedOutbound?.code ?? ''];
|
||||||
|
|
||||||
|
if (selectedProxyDelay) {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
latency: `[${selectedOutbound?.displayName ?? ''}] ${selectedProxyDelay}ms`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
latency: `[${selectedOutbound?.displayName ?? ''}] ${_('Not responding')}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
latency: _('Not responding'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const latencyProxy = await PodkopShellMethods.getClashApiProxyLatency(
|
||||||
|
section.code,
|
||||||
|
);
|
||||||
|
|
||||||
|
const success = latencyProxy.success && !latencyProxy.data.message;
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
latency: `${latencyProxy.data.delay} ms`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
latency: _('Not responding'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const { latency, success } = await getLatency();
|
||||||
|
|
||||||
|
return {
|
||||||
|
state: success ? 'success' : 'error',
|
||||||
|
key: section.displayName,
|
||||||
|
value: latency,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
)) as Array<IDiagnosticsChecksItem>;
|
||||||
|
|
||||||
|
const allGood = items.every((item) => item.state === 'success');
|
||||||
|
|
||||||
|
const atLeastOneGood = items.some((item) => item.state === 'success');
|
||||||
|
|
||||||
|
const { state, description } = getMeta({ atLeastOneGood, allGood });
|
||||||
|
|
||||||
|
updateCheckStore({
|
||||||
|
order,
|
||||||
|
code,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
state,
|
||||||
|
items,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!atLeastOneGood) {
|
||||||
|
throw new Error('Sections checks failed');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -64,7 +64,7 @@ export async function runSingBoxCheck() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
state: data.sing_box_version_ok ? 'success' : 'error',
|
state: data.sing_box_version_ok ? 'success' : 'error',
|
||||||
key: _('Sing-box version >= 1.12.4'),
|
key: _('Sing-box version is compatible (newer than 1.12.4)'),
|
||||||
value: '',
|
value: '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -72,6 +72,14 @@ export const initialDiagnosticStore: Pick<
|
|||||||
items: [],
|
items: [],
|
||||||
state: 'skipped',
|
state: 'skipped',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
code: DIAGNOSTICS_CHECKS.OUTBOUNDS,
|
||||||
|
title: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.title,
|
||||||
|
order: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.order,
|
||||||
|
description: _('Not running'),
|
||||||
|
items: [],
|
||||||
|
state: 'skipped',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
code: DIAGNOSTICS_CHECKS.FAKEIP,
|
code: DIAGNOSTICS_CHECKS.FAKEIP,
|
||||||
title: DIAGNOSTICS_CHECKS_MAP.FAKEIP.title,
|
title: DIAGNOSTICS_CHECKS_MAP.FAKEIP.title,
|
||||||
@@ -112,6 +120,14 @@ export const loadingDiagnosticsChecksStore: Pick<
|
|||||||
items: [],
|
items: [],
|
||||||
state: 'skipped',
|
state: 'skipped',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
code: DIAGNOSTICS_CHECKS.OUTBOUNDS,
|
||||||
|
title: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.title,
|
||||||
|
order: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.order,
|
||||||
|
description: _('Pending'),
|
||||||
|
items: [],
|
||||||
|
state: 'skipped',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
code: DIAGNOSTICS_CHECKS.FAKEIP,
|
code: DIAGNOSTICS_CHECKS.FAKEIP,
|
||||||
title: DIAGNOSTICS_CHECKS_MAP.FAKEIP.title,
|
title: DIAGNOSTICS_CHECKS_MAP.FAKEIP.title,
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import { normalizeCompiledVersion } from '../../../../helpers/normalizeCompiledVersion';
|
||||||
|
import { removeVersionPrefix } from '../../../../helpers/removeVersionPrefix';
|
||||||
|
import type { StoreType } from '../../../services/store.service';
|
||||||
|
import type { IRenderSystemInfoRow } from '../partials';
|
||||||
|
|
||||||
|
function isUnknownVersion(version?: string | null): boolean {
|
||||||
|
return version === 'unknown' || version === _('unknown');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPodkopVersionRow(
|
||||||
|
diagnosticsSystemInfo: StoreType['diagnosticsSystemInfo'],
|
||||||
|
): IRenderSystemInfoRow {
|
||||||
|
const loading = diagnosticsSystemInfo.loading;
|
||||||
|
const unknown = isUnknownVersion(diagnosticsSystemInfo.podkop_version);
|
||||||
|
const hasActualVersion =
|
||||||
|
Boolean(diagnosticsSystemInfo.podkop_latest_version) &&
|
||||||
|
!isUnknownVersion(diagnosticsSystemInfo.podkop_latest_version);
|
||||||
|
const version = normalizeCompiledVersion(
|
||||||
|
diagnosticsSystemInfo.podkop_version,
|
||||||
|
);
|
||||||
|
const isDevVersion = version === 'dev';
|
||||||
|
|
||||||
|
if (loading || unknown || !hasActualVersion || isDevVersion) {
|
||||||
|
return {
|
||||||
|
key: 'Podkop',
|
||||||
|
value: version,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
removeVersionPrefix(version) !==
|
||||||
|
removeVersionPrefix(diagnosticsSystemInfo.podkop_latest_version)
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
key: 'Podkop',
|
||||||
|
value: version,
|
||||||
|
tag: {
|
||||||
|
label: _('Outdated'),
|
||||||
|
kind: 'warning',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
key: 'Podkop',
|
||||||
|
value: version,
|
||||||
|
tag: {
|
||||||
|
label: _('Latest'),
|
||||||
|
kind: 'success',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -6,7 +6,6 @@ import { runFakeIPCheck } from './checks/runFakeIPCheck';
|
|||||||
import { loadingDiagnosticsChecksStore } from './diagnostic.store';
|
import { loadingDiagnosticsChecksStore } from './diagnostic.store';
|
||||||
import { logger, store, StoreType } from '../../services';
|
import { logger, store, StoreType } from '../../services';
|
||||||
import {
|
import {
|
||||||
IRenderSystemInfoRow,
|
|
||||||
renderAvailableActions,
|
renderAvailableActions,
|
||||||
renderCheckSection,
|
renderCheckSection,
|
||||||
renderRunAction,
|
renderRunAction,
|
||||||
@@ -19,6 +18,8 @@ import { renderModal } from '../../../partials';
|
|||||||
import { PODKOP_LUCI_APP_VERSION } from '../../../constants';
|
import { PODKOP_LUCI_APP_VERSION } from '../../../constants';
|
||||||
import { showToast } from '../../../helpers/showToast';
|
import { showToast } from '../../../helpers/showToast';
|
||||||
import { renderWikiDisclaimer } from './partials/renderWikiDisclaimer';
|
import { renderWikiDisclaimer } from './partials/renderWikiDisclaimer';
|
||||||
|
import { runSectionsCheck } from './checks/runSectionsCheck';
|
||||||
|
import { getPodkopVersionRow } from './helpers/getPodkopVersionRow';
|
||||||
|
|
||||||
async function fetchSystemInfo() {
|
async function fetchSystemInfo() {
|
||||||
const systemInfo = await PodkopShellMethods.getSystemInfo();
|
const systemInfo = await PodkopShellMethods.getSystemInfo();
|
||||||
@@ -287,7 +288,10 @@ async function handleShowSingBoxConfig() {
|
|||||||
if (showSingBoxConfig.success) {
|
if (showSingBoxConfig.success) {
|
||||||
ui.showModal(
|
ui.showModal(
|
||||||
_('Show sing-box config'),
|
_('Show sing-box config'),
|
||||||
renderModal(showSingBoxConfig.data as string, 'show_sing_box_config'),
|
renderModal(
|
||||||
|
JSON.stringify(showSingBoxConfig.data, null, 2),
|
||||||
|
'show_sing_box_config',
|
||||||
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
logger.error(
|
logger.error(
|
||||||
@@ -411,53 +415,9 @@ function renderDiagnosticSystemInfoWidget() {
|
|||||||
|
|
||||||
const container = document.getElementById('pdk_diagnostic-page-system-info');
|
const container = document.getElementById('pdk_diagnostic-page-system-info');
|
||||||
|
|
||||||
function getPodkopVersionRow(): IRenderSystemInfoRow {
|
|
||||||
const loading = diagnosticsSystemInfo.loading;
|
|
||||||
const unknown = diagnosticsSystemInfo.podkop_version === _('unknown');
|
|
||||||
const hasActualVersion = Boolean(
|
|
||||||
diagnosticsSystemInfo.podkop_latest_version,
|
|
||||||
);
|
|
||||||
const version = normalizeCompiledVersion(
|
|
||||||
diagnosticsSystemInfo.podkop_version,
|
|
||||||
);
|
|
||||||
const isDevVersion = version === 'dev';
|
|
||||||
|
|
||||||
if (loading || unknown || !hasActualVersion || isDevVersion) {
|
|
||||||
return {
|
|
||||||
key: 'Podkop',
|
|
||||||
value: version,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (version !== `v${diagnosticsSystemInfo.podkop_latest_version}`) {
|
|
||||||
logger.debug(
|
|
||||||
'[DIAGNOSTIC]',
|
|
||||||
'diagnosticsSystemInfo',
|
|
||||||
diagnosticsSystemInfo,
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
key: 'Podkop',
|
|
||||||
value: version,
|
|
||||||
tag: {
|
|
||||||
label: _('Outdated'),
|
|
||||||
kind: 'warning',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
key: 'Podkop',
|
|
||||||
value: version,
|
|
||||||
tag: {
|
|
||||||
label: _('Latest'),
|
|
||||||
kind: 'success',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const renderedSystemInfo = renderSystemInfo({
|
const renderedSystemInfo = renderSystemInfo({
|
||||||
items: [
|
items: [
|
||||||
getPodkopVersionRow(),
|
getPodkopVersionRow(diagnosticsSystemInfo),
|
||||||
{
|
{
|
||||||
key: 'Luci App',
|
key: 'Luci App',
|
||||||
value: normalizeCompiledVersion(PODKOP_LUCI_APP_VERSION),
|
value: normalizeCompiledVersion(PODKOP_LUCI_APP_VERSION),
|
||||||
@@ -518,6 +478,8 @@ async function runChecks() {
|
|||||||
|
|
||||||
await runNftCheck();
|
await runNftCheck();
|
||||||
|
|
||||||
|
await runSectionsCheck();
|
||||||
|
|
||||||
await runFakeIPCheck();
|
await runFakeIPCheck();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('[DIAGNOSTIC]', 'runChecks - e', e);
|
logger.error('[DIAGNOSTIC]', 'runChecks - e', e);
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import { getPodkopVersionRow } from '../helpers/getPodkopVersionRow';
|
||||||
|
import type { StoreType } from '../../../services/store.service';
|
||||||
|
|
||||||
|
function makeDiagnosticsSystemInfo(
|
||||||
|
patch: Partial<StoreType['diagnosticsSystemInfo']> = {},
|
||||||
|
): StoreType['diagnosticsSystemInfo'] {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
podkop_version: '1.2.3',
|
||||||
|
podkop_latest_version: '1.2.3',
|
||||||
|
luci_app_version: '1.0.0',
|
||||||
|
sing_box_version: '1.11.0',
|
||||||
|
openwrt_version: 'OpenWrt 25.12',
|
||||||
|
device_model: 'Test Router',
|
||||||
|
...patch,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('getPodkopVersionRow', () => {
|
||||||
|
it('returns Latest when versions differ only by leading v', () => {
|
||||||
|
const row = getPodkopVersionRow(
|
||||||
|
makeDiagnosticsSystemInfo({
|
||||||
|
podkop_version: 'v1.2.3',
|
||||||
|
podkop_latest_version: '1.2.3',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(row).toEqual({
|
||||||
|
key: 'Podkop',
|
||||||
|
value: 'v1.2.3',
|
||||||
|
tag: {
|
||||||
|
label: 'Latest',
|
||||||
|
kind: 'success',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns Outdated when versions differ', () => {
|
||||||
|
const row = getPodkopVersionRow(
|
||||||
|
makeDiagnosticsSystemInfo({
|
||||||
|
podkop_version: '1.2.2',
|
||||||
|
podkop_latest_version: '1.2.3',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(row).toEqual({
|
||||||
|
key: 'Podkop',
|
||||||
|
value: '1.2.2',
|
||||||
|
tag: {
|
||||||
|
label: 'Outdated',
|
||||||
|
kind: 'warning',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns plain row without tag for dev build', () => {
|
||||||
|
const row = getPodkopVersionRow(
|
||||||
|
makeDiagnosticsSystemInfo({
|
||||||
|
podkop_version: 'COMPILED_VERSION',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(row).toEqual({
|
||||||
|
key: 'Podkop',
|
||||||
|
value: 'dev',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -95,6 +95,12 @@ export namespace Podkop {
|
|||||||
urltest_proxy_links: string[];
|
urltest_proxy_links: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ConfigProxySelectorSection {
|
||||||
|
connection_type: 'proxy';
|
||||||
|
proxy_config_type: 'selector';
|
||||||
|
selector_proxy_links: string[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface ConfigProxyUrlSection {
|
export interface ConfigProxyUrlSection {
|
||||||
connection_type: 'proxy';
|
connection_type: 'proxy';
|
||||||
proxy_config_type: 'url';
|
proxy_config_type: 'url';
|
||||||
@@ -116,16 +122,23 @@ export namespace Podkop {
|
|||||||
connection_type: 'block';
|
connection_type: 'block';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ConfigExclusionSection {
|
||||||
|
connection_type: 'exclusion';
|
||||||
|
}
|
||||||
|
|
||||||
export type ConfigBaseSection =
|
export type ConfigBaseSection =
|
||||||
| ConfigProxyUrlTestSection
|
| ConfigProxyUrlTestSection
|
||||||
|
| ConfigProxySelectorSection
|
||||||
| ConfigProxyUrlSection
|
| ConfigProxyUrlSection
|
||||||
| ConfigProxyOutboundSection
|
| ConfigProxyOutboundSection
|
||||||
| ConfigVpnSection
|
| ConfigVpnSection
|
||||||
| ConfigBlockSection;
|
| ConfigBlockSection
|
||||||
|
| ConfigExclusionSection;
|
||||||
|
|
||||||
export type ConfigSection = ConfigBaseSection & {
|
export type ConfigSection = ConfigBaseSection & {
|
||||||
'.name': string;
|
'.name': string;
|
||||||
'.type': 'settings' | 'section';
|
'.type': 'settings' | 'section';
|
||||||
|
yacd_secret_key?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface MethodSuccessResponse<T> {
|
export interface MethodSuccessResponse<T> {
|
||||||
@@ -196,4 +209,11 @@ export namespace Podkop {
|
|||||||
openwrt_version: string;
|
openwrt_version: string;
|
||||||
device_model: string;
|
device_model: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GetClashApiProxyLatency {
|
||||||
|
delay: number;
|
||||||
|
message?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type GetClashApiGroupLatency = Record<string, number>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import { validateHysteria2Url } from '../validateHysteriaUrl.js';
|
||||||
|
|
||||||
|
const validUrls = [
|
||||||
|
// Basic password-only
|
||||||
|
['password basic', 'hysteria2://pass@example.com:443/#hy2-basic'],
|
||||||
|
|
||||||
|
// insecure=1
|
||||||
|
[
|
||||||
|
'insecure allowed',
|
||||||
|
'hysteria2://pass@example.com:443/?insecure=1#hy2-insecure',
|
||||||
|
],
|
||||||
|
|
||||||
|
// SNI
|
||||||
|
['SNI param', 'hysteria2://pass@example.com:443/?sni=google.com#hy2-sni'],
|
||||||
|
|
||||||
|
// Obfuscation
|
||||||
|
[
|
||||||
|
'Obfs + password',
|
||||||
|
'hysteria2://mypassword@1.1.1.1:8443/?obfs=salamander&obfs-password=abc123#hy2-obfs',
|
||||||
|
],
|
||||||
|
|
||||||
|
// All params
|
||||||
|
[
|
||||||
|
'All options combined',
|
||||||
|
'hysteria2://pw@8.8.8.8:8443/?sni=example.com&obfs=salamander&obfs-password=hello&insecure=1#hy2-full',
|
||||||
|
],
|
||||||
|
|
||||||
|
// Explicit obfs=none (valid)
|
||||||
|
['obfs none = ok', 'hysteria2://pw@example.com:443/?obfs=none#hy2-none'],
|
||||||
|
|
||||||
|
[
|
||||||
|
'port range 5000-6000',
|
||||||
|
'hysteria2://letmein@example.com:123,5000-6000/?insecure=1&obfs=salamander&obfs-password=gawrgura&pinSHA256=deadbeef&sni=real.example.com',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
const invalidUrls = [
|
||||||
|
['No prefix', 'pw@example.com:443'],
|
||||||
|
['Missing password', 'hysteria2://@example.com:443/'],
|
||||||
|
['Missing host', 'hysteria2://pw@:443/'],
|
||||||
|
['Missing port', 'hysteria2://pw@example.com/'],
|
||||||
|
['Non-numeric port', 'hysteria2://pw@example.com:port/'],
|
||||||
|
['Port out of range', 'hysteria2://pw@example.com:99999/'],
|
||||||
|
|
||||||
|
// Obfuscation errors
|
||||||
|
['Unknown obfs type', 'hysteria2://pw@example.com:443/?obfs=weird'],
|
||||||
|
[
|
||||||
|
'obfs without obfs-password',
|
||||||
|
'hysteria2://pw@example.com:443/?obfs=salamander',
|
||||||
|
],
|
||||||
|
|
||||||
|
// insecure only accepts 0/1
|
||||||
|
['invalid insecure', 'hysteria2://pw@example.com:443/?insecure=5'],
|
||||||
|
|
||||||
|
// SNI empty
|
||||||
|
['empty sni', 'hysteria2://pw@example.com:443/?sni='],
|
||||||
|
];
|
||||||
|
|
||||||
|
describe('validateHysteria2Url', () => {
|
||||||
|
describe.each(validUrls)('Valid HY2 URL: %s', (_desc, url) => {
|
||||||
|
it(`returns valid=true for "${url}"`, () => {
|
||||||
|
const res = validateHysteria2Url(url);
|
||||||
|
expect(res.valid).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe.each(invalidUrls)('Invalid HY2 URL: %s', (_desc, url) => {
|
||||||
|
it(`returns valid=false for "${url}"`, () => {
|
||||||
|
const res = validateHysteria2Url(url);
|
||||||
|
expect(res.valid).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('detects invalid port range', () => {
|
||||||
|
const res = validateHysteria2Url('hysteria2://pw@example.com:70000/');
|
||||||
|
expect(res.valid).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -16,6 +16,7 @@ const invalidUrls = [
|
|||||||
['Unsupported protocol (ftp)', 'ftp://example.com'],
|
['Unsupported protocol (ftp)', 'ftp://example.com'],
|
||||||
['Unsupported protocol (ws)', 'ws://example.com'],
|
['Unsupported protocol (ws)', 'ws://example.com'],
|
||||||
['Empty string', ''],
|
['Empty string', ''],
|
||||||
|
['Without tld', 'https://google'],
|
||||||
];
|
];
|
||||||
|
|
||||||
describe('validateUrl', () => {
|
describe('validateUrl', () => {
|
||||||
|
|||||||
124
fe-app-podkop/src/validators/validateHysteriaUrl.ts
Normal file
124
fe-app-podkop/src/validators/validateHysteriaUrl.ts
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
import { ValidationResult } from './types';
|
||||||
|
import { parseQueryString } from '../helpers/parseQueryString';
|
||||||
|
|
||||||
|
export function validateHysteria2Url(url: string): ValidationResult {
|
||||||
|
try {
|
||||||
|
const isHY2 = url.startsWith('hysteria2://');
|
||||||
|
const isHY2Short = url.startsWith('hy2://');
|
||||||
|
|
||||||
|
if (!isHY2 && !isHY2Short)
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _('Invalid HY2 URL: must start with hysteria2:// or hy2://'),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (/\s/.test(url))
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _('Invalid HY2 URL: must not contain spaces'),
|
||||||
|
};
|
||||||
|
|
||||||
|
const prefix = isHY2 ? 'hysteria2://' : 'hy2://';
|
||||||
|
const body = url.slice(prefix.length);
|
||||||
|
|
||||||
|
const [mainPart] = body.split('#');
|
||||||
|
const [authHostPort, queryString] = mainPart.split('?');
|
||||||
|
|
||||||
|
if (!authHostPort)
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _('Invalid HY2 URL: missing credentials/server'),
|
||||||
|
};
|
||||||
|
|
||||||
|
const [passwordPart, hostPortPart] = authHostPort.split('@');
|
||||||
|
|
||||||
|
if (!passwordPart)
|
||||||
|
return { valid: false, message: _('Invalid HY2 URL: missing password') };
|
||||||
|
|
||||||
|
if (!hostPortPart)
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _('Invalid HY2 URL: missing host & port'),
|
||||||
|
};
|
||||||
|
|
||||||
|
const [host, port] = hostPortPart.split(':');
|
||||||
|
|
||||||
|
if (!host)
|
||||||
|
return { valid: false, message: _('Invalid HY2 URL: missing host') };
|
||||||
|
|
||||||
|
if (!port)
|
||||||
|
return { valid: false, message: _('Invalid HY2 URL: missing port') };
|
||||||
|
|
||||||
|
const cleanedPort = port.replace('/', '');
|
||||||
|
const portEntries = cleanedPort.split(',');
|
||||||
|
|
||||||
|
const isValidPortNumber = (value: string) => {
|
||||||
|
if (!/^\d+$/.test(value)) return false;
|
||||||
|
const num = Number(value);
|
||||||
|
return num >= 1 && num <= 65535;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isValidPortEntry = (entry: string) => {
|
||||||
|
if (!entry) return false;
|
||||||
|
if (!entry.includes('-')) return isValidPortNumber(entry);
|
||||||
|
|
||||||
|
const rangeParts = entry.split('-');
|
||||||
|
if (rangeParts.length !== 2) return false;
|
||||||
|
|
||||||
|
const [start, end] = rangeParts;
|
||||||
|
if (!isValidPortNumber(start) || !isValidPortNumber(end)) return false;
|
||||||
|
|
||||||
|
return Number(start) <= Number(end);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!portEntries.every(isValidPortEntry))
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _('Invalid HY2 URL: invalid port number'),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (queryString) {
|
||||||
|
const params = parseQueryString(queryString);
|
||||||
|
const paramsKeys = Object.keys(params);
|
||||||
|
|
||||||
|
if (
|
||||||
|
paramsKeys.includes('insecure') &&
|
||||||
|
!['0', '1'].includes(params.insecure)
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _('Invalid HY2 URL: insecure must be 0 or 1'),
|
||||||
|
};
|
||||||
|
|
||||||
|
const validObfsTypes = ['none', 'salamander'];
|
||||||
|
|
||||||
|
if (paramsKeys.includes('obfs') && !validObfsTypes.includes(params.obfs))
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _('Invalid HY2 URL: unsupported obfs type'),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (
|
||||||
|
paramsKeys.includes('obfs') &&
|
||||||
|
params.obfs !== 'none' &&
|
||||||
|
!params['obfs-password']
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _(
|
||||||
|
'Invalid HY2 URL: obfs-password required when obfs is set',
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (paramsKeys.includes('sni') && !params.sni)
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _('Invalid HY2 URL: sni cannot be empty'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return { valid: true, message: _('Valid') };
|
||||||
|
} catch (_e) {
|
||||||
|
return { valid: false, message: _('Invalid HY2 URL: parsing failed') };
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,18 +1,8 @@
|
|||||||
import { ValidationResult } from './types';
|
import { ValidationResult } from './types';
|
||||||
|
|
||||||
// TODO refactor current validation and add tests
|
|
||||||
export function validateOutboundJson(value: string): ValidationResult {
|
export function validateOutboundJson(value: string): ValidationResult {
|
||||||
try {
|
try {
|
||||||
const parsed = JSON.parse(value);
|
JSON.parse(value);
|
||||||
|
|
||||||
if (!parsed.type || !parsed.server || !parsed.server_port) {
|
|
||||||
return {
|
|
||||||
valid: false,
|
|
||||||
message: _(
|
|
||||||
'Outbound JSON must contain at least "type", "server" and "server_port" fields',
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return { valid: true, message: _('Valid') };
|
return { valid: true, message: _('Valid') };
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { validateShadowsocksUrl } from './validateShadowsocksUrl';
|
|||||||
import { validateVlessUrl } from './validateVlessUrl';
|
import { validateVlessUrl } from './validateVlessUrl';
|
||||||
import { validateTrojanUrl } from './validateTrojanUrl';
|
import { validateTrojanUrl } from './validateTrojanUrl';
|
||||||
import { validateSocksUrl } from './validateSocksUrl';
|
import { validateSocksUrl } from './validateSocksUrl';
|
||||||
|
import { validateHysteria2Url } from './validateHysteriaUrl';
|
||||||
|
|
||||||
// TODO refactor current validation and add tests
|
// TODO refactor current validation and add tests
|
||||||
export function validateProxyUrl(url: string): ValidationResult {
|
export function validateProxyUrl(url: string): ValidationResult {
|
||||||
@@ -24,10 +25,17 @@ export function validateProxyUrl(url: string): ValidationResult {
|
|||||||
return validateSocksUrl(trimmedUrl);
|
return validateSocksUrl(trimmedUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
trimmedUrl.startsWith('hysteria2://') ||
|
||||||
|
trimmedUrl.startsWith('hy2://')
|
||||||
|
) {
|
||||||
|
return validateHysteria2Url(trimmedUrl);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
valid: false,
|
valid: false,
|
||||||
message: _(
|
message: _(
|
||||||
'URL must start with vless://, ss://, trojan://, or socks4/5://',
|
'URL must start with vless://, ss://, trojan://, socks4/5://, or hysteria2://hy2://',
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,19 +2,31 @@ import { ValidationResult } from './types';
|
|||||||
|
|
||||||
export function validateUrl(
|
export function validateUrl(
|
||||||
url: string,
|
url: string,
|
||||||
protocols: string[] = ['http:', 'https:'],
|
protocols = ['http:', 'https:'],
|
||||||
): ValidationResult {
|
): ValidationResult {
|
||||||
try {
|
if (!url.length) {
|
||||||
const parsedUrl = new URL(url);
|
|
||||||
|
|
||||||
if (!protocols.includes(parsedUrl.protocol)) {
|
|
||||||
return {
|
|
||||||
valid: false,
|
|
||||||
message: `${_('URL must use one of the following protocols:')} ${protocols.join(', ')}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return { valid: true, message: _('Valid') };
|
|
||||||
} catch (_e) {
|
|
||||||
return { valid: false, message: _('Invalid URL format') };
|
return { valid: false, message: _('Invalid URL format') };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hasValidProtocol = protocols.some((p) => url.indexOf(p + '//') === 0);
|
||||||
|
|
||||||
|
if (!hasValidProtocol)
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message:
|
||||||
|
_('URL must use one of the following protocols:') +
|
||||||
|
' ' +
|
||||||
|
protocols.join(', '),
|
||||||
|
};
|
||||||
|
|
||||||
|
const regex = new RegExp(
|
||||||
|
`^(?:${protocols.map((p) => p.replace(':', '')).join('|')})://` +
|
||||||
|
`(?:[A-Za-z0-9-]+\\.)+[A-Za-z]{2,}(?::\\d+)?(?:/[^\\s]*)?$`,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (regex.test(url)) {
|
||||||
|
return { valid: true, message: _('Valid') };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { valid: false, message: _('Invalid URL format') };
|
||||||
}
|
}
|
||||||
|
|||||||
20
install.sh
20
install.sh
@@ -109,16 +109,16 @@ main() {
|
|||||||
pkg_list_update || { echo "Packages list update failed"; exit 1; }
|
pkg_list_update || { echo "Packages list update failed"; exit 1; }
|
||||||
|
|
||||||
if [ -f "/etc/init.d/podkop" ]; then
|
if [ -f "/etc/init.d/podkop" ]; then
|
||||||
msg "Podkop is already installed. Upgraded..."
|
msg "Podkop is already installed. Upgrading..."
|
||||||
else
|
else
|
||||||
msg "Installed podkop..."
|
msg "Installing podkop..."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if command -v curl >/dev/null 2>&1; then
|
if command -v curl >/dev/null 2>&1; then
|
||||||
check_response=$(curl -s "https://api.github.com/repos/itdoginfo/podkop/releases/latest")
|
check_response=$(curl -s "https://api.github.com/repos/itdoginfo/podkop/releases/latest")
|
||||||
|
|
||||||
if echo "$check_response" | grep -q 'API rate limit '; then
|
if echo "$check_response" | grep -q 'API rate limit '; then
|
||||||
msg "You've reached rate limit from GitHub. Repeat in five minutes."
|
msg "You've reached the GitHub rate limit. Repeat in five minutes."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -143,7 +143,7 @@ main() {
|
|||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
msg "Download error $filename. Retry..."
|
msg "Download error for $filename. Retrying..."
|
||||||
rm -f "$filepath"
|
rm -f "$filepath"
|
||||||
attempt=$((attempt+1))
|
attempt=$((attempt+1))
|
||||||
done
|
done
|
||||||
@@ -168,7 +168,7 @@ main() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
if [ -n "$file" ]; then
|
if [ -n "$file" ]; then
|
||||||
msg "Installing $file"
|
msg "Installing $file..."
|
||||||
pkg_install "$DOWNLOAD_DIR/$file"
|
pkg_install "$DOWNLOAD_DIR/$file"
|
||||||
sleep 3
|
sleep 3
|
||||||
fi
|
fi
|
||||||
@@ -183,11 +183,11 @@ main() {
|
|||||||
done
|
done
|
||||||
if [ -n "$ru" ]; then
|
if [ -n "$ru" ]; then
|
||||||
if pkg_is_installed luci-i18n-podkop-ru; then
|
if pkg_is_installed luci-i18n-podkop-ru; then
|
||||||
msg "Upgraded ru translation..."
|
msg "Upgrading Russian translation..."
|
||||||
pkg_remove luci-i18n-podkop*
|
pkg_remove luci-i18n-podkop*
|
||||||
pkg_install "$DOWNLOAD_DIR/$ru"
|
pkg_install "$DOWNLOAD_DIR/$ru"
|
||||||
else
|
else
|
||||||
msg "Русский язык интерфейса ставим? y/n (Need a Russian translation?)"
|
msg "Русский язык интерфейса ставим? y/n (Install the Russian interface language?)"
|
||||||
while true; do
|
while true; do
|
||||||
read -r -p '' RUS
|
read -r -p '' RUS
|
||||||
case $RUS in
|
case $RUS in
|
||||||
@@ -236,7 +236,7 @@ check_system() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if ! nslookup google.com >/dev/null 2>&1; then
|
if ! nslookup google.com >/dev/null 2>&1; then
|
||||||
msg "DNS not working"
|
msg "DNS is not working."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -270,7 +270,7 @@ check_system() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if pkg_is_installed https-dns-proxy; then
|
if pkg_is_installed https-dns-proxy; then
|
||||||
msg "Сonflicting package detected: https-dns-proxy. Remove?"
|
msg "Conflicting package detected: https-dns-proxy. Remove?"
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
read -r -p '' DNSPROXY
|
read -r -p '' DNSPROXY
|
||||||
@@ -300,7 +300,7 @@ sing_box() {
|
|||||||
required_version="1.12.4"
|
required_version="1.12.4"
|
||||||
|
|
||||||
if [ "$(printf '%s\n%s\n' "$sing_box_version" "$required_version" | sort -V | head -n 1)" != "$required_version" ]; then
|
if [ "$(printf '%s\n%s\n' "$sing_box_version" "$required_version" | sort -V | head -n 1)" != "$required_version" ]; then
|
||||||
msg "sing-box version $sing_box_version is older than required $required_version"
|
msg "sing-box version $sing_box_version is older than the required version $required_version."
|
||||||
msg "Removing old version..."
|
msg "Removing old version..."
|
||||||
service podkop stop
|
service podkop stop
|
||||||
pkg_remove sing-box
|
pkg_remove sing-box
|
||||||
|
|||||||
@@ -58,18 +58,22 @@ function validateDNS(value) {
|
|||||||
|
|
||||||
// src/validators/validateUrl.ts
|
// src/validators/validateUrl.ts
|
||||||
function validateUrl(url, protocols = ["http:", "https:"]) {
|
function validateUrl(url, protocols = ["http:", "https:"]) {
|
||||||
try {
|
if (!url.length) {
|
||||||
const parsedUrl = new URL(url);
|
|
||||||
if (!protocols.includes(parsedUrl.protocol)) {
|
|
||||||
return {
|
|
||||||
valid: false,
|
|
||||||
message: `${_("URL must use one of the following protocols:")} ${protocols.join(", ")}`
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return { valid: true, message: _("Valid") };
|
|
||||||
} catch (_e) {
|
|
||||||
return { valid: false, message: _("Invalid URL format") };
|
return { valid: false, message: _("Invalid URL format") };
|
||||||
}
|
}
|
||||||
|
const hasValidProtocol = protocols.some((p) => url.indexOf(p + "//") === 0);
|
||||||
|
if (!hasValidProtocol)
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _("URL must use one of the following protocols:") + " " + protocols.join(", ")
|
||||||
|
};
|
||||||
|
const regex = new RegExp(
|
||||||
|
`^(?:${protocols.map((p) => p.replace(":", "")).join("|")})://(?:[A-Za-z0-9-]+\\.)+[A-Za-z]{2,}(?::\\d+)?(?:/[^\\s]*)?$`
|
||||||
|
);
|
||||||
|
if (regex.test(url)) {
|
||||||
|
return { valid: true, message: _("Valid") };
|
||||||
|
}
|
||||||
|
return { valid: false, message: _("Invalid URL format") };
|
||||||
}
|
}
|
||||||
|
|
||||||
// src/validators/validatePath.ts
|
// src/validators/validatePath.ts
|
||||||
@@ -323,15 +327,7 @@ function validateVlessUrl(url) {
|
|||||||
// src/validators/validateOutboundJson.ts
|
// src/validators/validateOutboundJson.ts
|
||||||
function validateOutboundJson(value) {
|
function validateOutboundJson(value) {
|
||||||
try {
|
try {
|
||||||
const parsed = JSON.parse(value);
|
JSON.parse(value);
|
||||||
if (!parsed.type || !parsed.server || !parsed.server_port) {
|
|
||||||
return {
|
|
||||||
valid: false,
|
|
||||||
message: _(
|
|
||||||
'Outbound JSON must contain at least "type", "server" and "server_port" fields'
|
|
||||||
)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return { valid: true, message: _("Valid") };
|
return { valid: true, message: _("Valid") };
|
||||||
} catch {
|
} catch {
|
||||||
return { valid: false, message: _("Invalid JSON format") };
|
return { valid: false, message: _("Invalid JSON format") };
|
||||||
@@ -452,6 +448,97 @@ function validateSocksUrl(url) {
|
|||||||
return { valid: true, message: _("Valid") };
|
return { valid: true, message: _("Valid") };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// src/validators/validateHysteriaUrl.ts
|
||||||
|
function validateHysteria2Url(url) {
|
||||||
|
try {
|
||||||
|
const isHY2 = url.startsWith("hysteria2://");
|
||||||
|
const isHY2Short = url.startsWith("hy2://");
|
||||||
|
if (!isHY2 && !isHY2Short)
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _("Invalid HY2 URL: must start with hysteria2:// or hy2://")
|
||||||
|
};
|
||||||
|
if (/\s/.test(url))
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _("Invalid HY2 URL: must not contain spaces")
|
||||||
|
};
|
||||||
|
const prefix = isHY2 ? "hysteria2://" : "hy2://";
|
||||||
|
const body = url.slice(prefix.length);
|
||||||
|
const [mainPart] = body.split("#");
|
||||||
|
const [authHostPort, queryString] = mainPart.split("?");
|
||||||
|
if (!authHostPort)
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _("Invalid HY2 URL: missing credentials/server")
|
||||||
|
};
|
||||||
|
const [passwordPart, hostPortPart] = authHostPort.split("@");
|
||||||
|
if (!passwordPart)
|
||||||
|
return { valid: false, message: _("Invalid HY2 URL: missing password") };
|
||||||
|
if (!hostPortPart)
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _("Invalid HY2 URL: missing host & port")
|
||||||
|
};
|
||||||
|
const [host, port] = hostPortPart.split(":");
|
||||||
|
if (!host)
|
||||||
|
return { valid: false, message: _("Invalid HY2 URL: missing host") };
|
||||||
|
if (!port)
|
||||||
|
return { valid: false, message: _("Invalid HY2 URL: missing port") };
|
||||||
|
const cleanedPort = port.replace("/", "");
|
||||||
|
const portEntries = cleanedPort.split(",");
|
||||||
|
const isValidPortNumber = (value) => {
|
||||||
|
if (!/^\d+$/.test(value)) return false;
|
||||||
|
const num = Number(value);
|
||||||
|
return num >= 1 && num <= 65535;
|
||||||
|
};
|
||||||
|
const isValidPortEntry = (entry) => {
|
||||||
|
if (!entry) return false;
|
||||||
|
if (!entry.includes("-")) return isValidPortNumber(entry);
|
||||||
|
const rangeParts = entry.split("-");
|
||||||
|
if (rangeParts.length !== 2) return false;
|
||||||
|
const [start, end] = rangeParts;
|
||||||
|
if (!isValidPortNumber(start) || !isValidPortNumber(end)) return false;
|
||||||
|
return Number(start) <= Number(end);
|
||||||
|
};
|
||||||
|
if (!portEntries.every(isValidPortEntry))
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _("Invalid HY2 URL: invalid port number")
|
||||||
|
};
|
||||||
|
if (queryString) {
|
||||||
|
const params = parseQueryString(queryString);
|
||||||
|
const paramsKeys = Object.keys(params);
|
||||||
|
if (paramsKeys.includes("insecure") && !["0", "1"].includes(params.insecure))
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _("Invalid HY2 URL: insecure must be 0 or 1")
|
||||||
|
};
|
||||||
|
const validObfsTypes = ["none", "salamander"];
|
||||||
|
if (paramsKeys.includes("obfs") && !validObfsTypes.includes(params.obfs))
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _("Invalid HY2 URL: unsupported obfs type")
|
||||||
|
};
|
||||||
|
if (paramsKeys.includes("obfs") && params.obfs !== "none" && !params["obfs-password"])
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _(
|
||||||
|
"Invalid HY2 URL: obfs-password required when obfs is set"
|
||||||
|
)
|
||||||
|
};
|
||||||
|
if (paramsKeys.includes("sni") && !params.sni)
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _("Invalid HY2 URL: sni cannot be empty")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return { valid: true, message: _("Valid") };
|
||||||
|
} catch (_e) {
|
||||||
|
return { valid: false, message: _("Invalid HY2 URL: parsing failed") };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// src/validators/validateProxyUrl.ts
|
// src/validators/validateProxyUrl.ts
|
||||||
function validateProxyUrl(url) {
|
function validateProxyUrl(url) {
|
||||||
const trimmedUrl = url.trim();
|
const trimmedUrl = url.trim();
|
||||||
@@ -467,10 +554,13 @@ function validateProxyUrl(url) {
|
|||||||
if (/^socks(4|4a|5):\/\//.test(trimmedUrl)) {
|
if (/^socks(4|4a|5):\/\//.test(trimmedUrl)) {
|
||||||
return validateSocksUrl(trimmedUrl);
|
return validateSocksUrl(trimmedUrl);
|
||||||
}
|
}
|
||||||
|
if (trimmedUrl.startsWith("hysteria2://") || trimmedUrl.startsWith("hy2://")) {
|
||||||
|
return validateHysteria2Url(trimmedUrl);
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
valid: false,
|
valid: false,
|
||||||
message: _(
|
message: _(
|
||||||
"URL must start with vless://, ss://, trojan://, or socks4/5://"
|
"URL must start with vless://, ss://, trojan://, socks4/5://, or hysteria2://hy2://"
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -563,14 +653,14 @@ var PodkopShellMethods = {
|
|||||||
getClashApiProxies: async () => callBaseMethod(Podkop.AvailableMethods.CLASH_API, [
|
getClashApiProxies: async () => callBaseMethod(Podkop.AvailableMethods.CLASH_API, [
|
||||||
Podkop.AvailableClashAPIMethods.GET_PROXIES
|
Podkop.AvailableClashAPIMethods.GET_PROXIES
|
||||||
]),
|
]),
|
||||||
getClashApiProxyLatency: async (tag) => callBaseMethod(Podkop.AvailableMethods.CLASH_API, [
|
getClashApiProxyLatency: async (tag) => callBaseMethod(
|
||||||
Podkop.AvailableClashAPIMethods.GET_PROXY_LATENCY,
|
Podkop.AvailableMethods.CLASH_API,
|
||||||
tag
|
[Podkop.AvailableClashAPIMethods.GET_PROXY_LATENCY, tag, "5000"]
|
||||||
]),
|
),
|
||||||
getClashApiGroupLatency: async (tag) => callBaseMethod(Podkop.AvailableMethods.CLASH_API, [
|
getClashApiGroupLatency: async (tag) => callBaseMethod(
|
||||||
Podkop.AvailableClashAPIMethods.GET_GROUP_LATENCY,
|
Podkop.AvailableMethods.CLASH_API,
|
||||||
tag
|
[Podkop.AvailableClashAPIMethods.GET_GROUP_LATENCY, tag, "10000"]
|
||||||
]),
|
),
|
||||||
setClashApiGroupProxy: async (group, proxy) => callBaseMethod(Podkop.AvailableMethods.CLASH_API, [
|
setClashApiGroupProxy: async (group, proxy) => callBaseMethod(Podkop.AvailableMethods.CLASH_API, [
|
||||||
Podkop.AvailableClashAPIMethods.SET_GROUP_PROXY,
|
Podkop.AvailableClashAPIMethods.SET_GROUP_PROXY,
|
||||||
group,
|
group,
|
||||||
@@ -626,7 +716,7 @@ async function getDashboardSections() {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
const data = configSections.filter(
|
const data = configSections.filter(
|
||||||
(section) => section.connection_type !== "block" && section[".type"] !== "settings"
|
(section) => section.connection_type !== "block" && section.connection_type !== "exclusion" && section[".type"] !== "settings"
|
||||||
).map((section) => {
|
).map((section) => {
|
||||||
if (section.connection_type === "proxy") {
|
if (section.connection_type === "proxy") {
|
||||||
if (section.proxy_config_type === "url") {
|
if (section.proxy_config_type === "url") {
|
||||||
@@ -672,6 +762,30 @@ async function getDashboardSections() {
|
|||||||
]
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (section.proxy_config_type === "selector") {
|
||||||
|
const selector = proxies.find(
|
||||||
|
(proxy) => proxy.code === `${section[".name"]}-out`
|
||||||
|
);
|
||||||
|
const links = section.selector_proxy_links ?? [];
|
||||||
|
const outbounds = links.map((link, index) => ({
|
||||||
|
link,
|
||||||
|
outbound: proxies.find(
|
||||||
|
(item) => item.code === `${section[".name"]}-${index + 1}-out`
|
||||||
|
)
|
||||||
|
})).map((item) => ({
|
||||||
|
code: item?.outbound?.code || "",
|
||||||
|
displayName: getProxyUrlName(item.link) || item?.outbound?.value?.name || "",
|
||||||
|
latency: item?.outbound?.value?.history?.[0]?.delay || 0,
|
||||||
|
type: item?.outbound?.value?.type || "",
|
||||||
|
selected: selector?.value?.now === item?.outbound?.code
|
||||||
|
}));
|
||||||
|
return {
|
||||||
|
withTagSelect: true,
|
||||||
|
code: selector?.code || section[".name"],
|
||||||
|
displayName: section[".name"],
|
||||||
|
outbounds
|
||||||
|
};
|
||||||
|
}
|
||||||
if (section.proxy_config_type === "urltest") {
|
if (section.proxy_config_type === "urltest") {
|
||||||
const selector = proxies.find(
|
const selector = proxies.find(
|
||||||
(proxy) => proxy.code === `${section[".name"]}-out`
|
(proxy) => proxy.code === `${section[".name"]}-out`
|
||||||
@@ -735,10 +849,18 @@ async function getDashboardSections() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// src/podkop/methods/custom/getClashApiSecret.ts
|
||||||
|
async function getClashApiSecret() {
|
||||||
|
const sections = await getConfigSections();
|
||||||
|
const settings = sections.find((section) => section[".type"] === "settings");
|
||||||
|
return settings?.yacd_secret_key || "";
|
||||||
|
}
|
||||||
|
|
||||||
// src/podkop/methods/custom/index.ts
|
// src/podkop/methods/custom/index.ts
|
||||||
var CustomPodkopMethods = {
|
var CustomPodkopMethods = {
|
||||||
getConfigSections,
|
getConfigSections,
|
||||||
getDashboardSections
|
getDashboardSections,
|
||||||
|
getClashApiSecret
|
||||||
};
|
};
|
||||||
|
|
||||||
// src/constants.ts
|
// src/constants.ts
|
||||||
@@ -767,6 +889,7 @@ var ALLOWED_WITH_RUSSIA_INSIDE = [
|
|||||||
"hetzner",
|
"hetzner",
|
||||||
"ovh",
|
"ovh",
|
||||||
"hodca",
|
"hodca",
|
||||||
|
"roblox",
|
||||||
"digitalocean",
|
"digitalocean",
|
||||||
"cloudfront"
|
"cloudfront"
|
||||||
];
|
];
|
||||||
@@ -790,6 +913,7 @@ var DOMAIN_LIST_OPTIONS = {
|
|||||||
google_ai: "Google AI",
|
google_ai: "Google AI",
|
||||||
google_play: "Google Play",
|
google_play: "Google Play",
|
||||||
hodca: "H.O.D.C.A",
|
hodca: "H.O.D.C.A",
|
||||||
|
roblox: "Roblox",
|
||||||
hetzner: "Hetzner ASN",
|
hetzner: "Hetzner ASN",
|
||||||
ovh: "OVH ASN",
|
ovh: "OVH ASN",
|
||||||
digitalocean: "Digital Ocean ASN",
|
digitalocean: "Digital Ocean ASN",
|
||||||
@@ -1004,8 +1128,13 @@ var DIAGNOSTICS_CHECKS_MAP = {
|
|||||||
title: getCheckTitle("Nftables"),
|
title: getCheckTitle("Nftables"),
|
||||||
code: "NFT" /* NFT */
|
code: "NFT" /* NFT */
|
||||||
},
|
},
|
||||||
["FAKEIP" /* FAKEIP */]: {
|
["OUTBOUNDS" /* OUTBOUNDS */]: {
|
||||||
order: 4,
|
order: 4,
|
||||||
|
title: getCheckTitle("Outbounds"),
|
||||||
|
code: "OUTBOUNDS" /* OUTBOUNDS */
|
||||||
|
},
|
||||||
|
["FAKEIP" /* FAKEIP */]: {
|
||||||
|
order: 5,
|
||||||
title: getCheckTitle("FakeIP"),
|
title: getCheckTitle("FakeIP"),
|
||||||
code: "FAKEIP" /* FAKEIP */
|
code: "FAKEIP" /* FAKEIP */
|
||||||
}
|
}
|
||||||
@@ -1074,6 +1203,14 @@ var initialDiagnosticStore = {
|
|||||||
items: [],
|
items: [],
|
||||||
state: "skipped"
|
state: "skipped"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
code: "OUTBOUNDS" /* OUTBOUNDS */,
|
||||||
|
title: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.title,
|
||||||
|
order: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.order,
|
||||||
|
description: _("Not running"),
|
||||||
|
items: [],
|
||||||
|
state: "skipped"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
code: "FAKEIP" /* FAKEIP */,
|
code: "FAKEIP" /* FAKEIP */,
|
||||||
title: DIAGNOSTICS_CHECKS_MAP.FAKEIP.title,
|
title: DIAGNOSTICS_CHECKS_MAP.FAKEIP.title,
|
||||||
@@ -1110,6 +1247,14 @@ var loadingDiagnosticsChecksStore = {
|
|||||||
items: [],
|
items: [],
|
||||||
state: "skipped"
|
state: "skipped"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
code: "OUTBOUNDS" /* OUTBOUNDS */,
|
||||||
|
title: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.title,
|
||||||
|
order: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.order,
|
||||||
|
description: _("Pending"),
|
||||||
|
items: [],
|
||||||
|
state: "skipped"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
code: "FAKEIP" /* FAKEIP */,
|
code: "FAKEIP" /* FAKEIP */,
|
||||||
title: DIAGNOSTICS_CHECKS_MAP.FAKEIP.title,
|
title: DIAGNOSTICS_CHECKS_MAP.FAKEIP.title,
|
||||||
@@ -1859,8 +2004,9 @@ async function fetchDashboardSections() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
async function connectToClashSockets() {
|
async function connectToClashSockets() {
|
||||||
|
const clashApiSecret = await getClashApiSecret();
|
||||||
socket.subscribe(
|
socket.subscribe(
|
||||||
`${getClashWsUrl()}/traffic?token=`,
|
`${getClashWsUrl()}/traffic?token=${clashApiSecret}`,
|
||||||
(msg) => {
|
(msg) => {
|
||||||
const parsedMsg = JSON.parse(msg);
|
const parsedMsg = JSON.parse(msg);
|
||||||
store.set({
|
store.set({
|
||||||
@@ -1887,7 +2033,7 @@ async function connectToClashSockets() {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
socket.subscribe(
|
socket.subscribe(
|
||||||
`${getClashWsUrl()}/connections?token=`,
|
`${getClashWsUrl()}/connections?token=${clashApiSecret}`,
|
||||||
(msg) => {
|
(msg) => {
|
||||||
const parsedMsg = JSON.parse(msg);
|
const parsedMsg = JSON.parse(msg);
|
||||||
store.set({
|
store.set({
|
||||||
@@ -2492,7 +2638,7 @@ async function runSingBoxCheck() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
state: data.sing_box_version_ok ? "success" : "error",
|
state: data.sing_box_version_ok ? "success" : "error",
|
||||||
key: _("Sing-box version >= 1.12.4"),
|
key: _("Sing-box version is compatible (newer than 1.12.4)"),
|
||||||
value: ""
|
value: ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -3685,6 +3831,148 @@ function renderWikiDisclaimer(kind) {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts
|
||||||
|
async function runSectionsCheck() {
|
||||||
|
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS;
|
||||||
|
updateCheckStore({
|
||||||
|
order,
|
||||||
|
code,
|
||||||
|
title,
|
||||||
|
description: _("Checking, please wait"),
|
||||||
|
state: "loading",
|
||||||
|
items: []
|
||||||
|
});
|
||||||
|
const sections = await getDashboardSections();
|
||||||
|
if (!sections.success) {
|
||||||
|
updateCheckStore({
|
||||||
|
order,
|
||||||
|
code,
|
||||||
|
title,
|
||||||
|
description: _("Cannot receive checks result"),
|
||||||
|
state: "error",
|
||||||
|
items: []
|
||||||
|
});
|
||||||
|
throw new Error("Sections checks failed");
|
||||||
|
}
|
||||||
|
const items = await Promise.all(
|
||||||
|
sections.data.map(async (section) => {
|
||||||
|
async function getLatency() {
|
||||||
|
if (section.withTagSelect) {
|
||||||
|
const latencyGroup = await PodkopShellMethods.getClashApiGroupLatency(
|
||||||
|
section.code
|
||||||
|
);
|
||||||
|
const selectedOutbound = section.outbounds.find(
|
||||||
|
(item) => item.selected
|
||||||
|
);
|
||||||
|
const isUrlTest = selectedOutbound?.type === "URLTest";
|
||||||
|
const success3 = latencyGroup.success && !latencyGroup.data.message;
|
||||||
|
if (success3) {
|
||||||
|
if (isUrlTest) {
|
||||||
|
const latency2 = Object.values(latencyGroup.data).map((item) => item ? `${item}ms` : "n/a").join(" / ");
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
latency: `[${_("Fastest")}] ${latency2}`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const selectedProxyDelay = latencyGroup.data?.[selectedOutbound?.code ?? ""];
|
||||||
|
if (selectedProxyDelay) {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
latency: `[${selectedOutbound?.displayName ?? ""}] ${selectedProxyDelay}ms`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
latency: `[${selectedOutbound?.displayName ?? ""}] ${_("Not responding")}`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
latency: _("Not responding")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const latencyProxy = await PodkopShellMethods.getClashApiProxyLatency(
|
||||||
|
section.code
|
||||||
|
);
|
||||||
|
const success2 = latencyProxy.success && !latencyProxy.data.message;
|
||||||
|
if (success2) {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
latency: `${latencyProxy.data.delay} ms`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
latency: _("Not responding")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const { latency, success } = await getLatency();
|
||||||
|
return {
|
||||||
|
state: success ? "success" : "error",
|
||||||
|
key: section.displayName,
|
||||||
|
value: latency
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const allGood = items.every((item) => item.state === "success");
|
||||||
|
const atLeastOneGood = items.some((item) => item.state === "success");
|
||||||
|
const { state, description } = getMeta({ atLeastOneGood, allGood });
|
||||||
|
updateCheckStore({
|
||||||
|
order,
|
||||||
|
code,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
state,
|
||||||
|
items
|
||||||
|
});
|
||||||
|
if (!atLeastOneGood) {
|
||||||
|
throw new Error("Sections checks failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/helpers/removeVersionPrefix.ts
|
||||||
|
function removeVersionPrefix(version) {
|
||||||
|
return version.replace(/^v/, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/podkop/tabs/diagnostic/helpers/getPodkopVersionRow.ts
|
||||||
|
function isUnknownVersion(version) {
|
||||||
|
return version === "unknown" || version === _("unknown");
|
||||||
|
}
|
||||||
|
function getPodkopVersionRow(diagnosticsSystemInfo) {
|
||||||
|
const loading = diagnosticsSystemInfo.loading;
|
||||||
|
const unknown = isUnknownVersion(diagnosticsSystemInfo.podkop_version);
|
||||||
|
const hasActualVersion = Boolean(diagnosticsSystemInfo.podkop_latest_version) && !isUnknownVersion(diagnosticsSystemInfo.podkop_latest_version);
|
||||||
|
const version = normalizeCompiledVersion(
|
||||||
|
diagnosticsSystemInfo.podkop_version
|
||||||
|
);
|
||||||
|
const isDevVersion = version === "dev";
|
||||||
|
if (loading || unknown || !hasActualVersion || isDevVersion) {
|
||||||
|
return {
|
||||||
|
key: "Podkop",
|
||||||
|
value: version
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (removeVersionPrefix(version) !== removeVersionPrefix(diagnosticsSystemInfo.podkop_latest_version)) {
|
||||||
|
return {
|
||||||
|
key: "Podkop",
|
||||||
|
value: version,
|
||||||
|
tag: {
|
||||||
|
label: _("Outdated"),
|
||||||
|
kind: "warning"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
key: "Podkop",
|
||||||
|
value: version,
|
||||||
|
tag: {
|
||||||
|
label: _("Latest"),
|
||||||
|
kind: "success"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// src/podkop/tabs/diagnostic/initController.ts
|
// src/podkop/tabs/diagnostic/initController.ts
|
||||||
async function fetchSystemInfo() {
|
async function fetchSystemInfo() {
|
||||||
const systemInfo = await PodkopShellMethods.getSystemInfo();
|
const systemInfo = await PodkopShellMethods.getSystemInfo();
|
||||||
@@ -3924,7 +4212,10 @@ async function handleShowSingBoxConfig() {
|
|||||||
if (showSingBoxConfig.success) {
|
if (showSingBoxConfig.success) {
|
||||||
ui.showModal(
|
ui.showModal(
|
||||||
_("Show sing-box config"),
|
_("Show sing-box config"),
|
||||||
renderModal(showSingBoxConfig.data, "show_sing_box_config")
|
renderModal(
|
||||||
|
JSON.stringify(showSingBoxConfig.data, null, 2),
|
||||||
|
"show_sing_box_config"
|
||||||
|
)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
logger.error(
|
logger.error(
|
||||||
@@ -4029,49 +4320,9 @@ function renderDiagnosticSystemInfoWidget() {
|
|||||||
logger.debug("[DIAGNOSTIC]", "renderDiagnosticSystemInfoWidget");
|
logger.debug("[DIAGNOSTIC]", "renderDiagnosticSystemInfoWidget");
|
||||||
const diagnosticsSystemInfo = store.get().diagnosticsSystemInfo;
|
const diagnosticsSystemInfo = store.get().diagnosticsSystemInfo;
|
||||||
const container = document.getElementById("pdk_diagnostic-page-system-info");
|
const container = document.getElementById("pdk_diagnostic-page-system-info");
|
||||||
function getPodkopVersionRow() {
|
|
||||||
const loading = diagnosticsSystemInfo.loading;
|
|
||||||
const unknown = diagnosticsSystemInfo.podkop_version === _("unknown");
|
|
||||||
const hasActualVersion = Boolean(
|
|
||||||
diagnosticsSystemInfo.podkop_latest_version
|
|
||||||
);
|
|
||||||
const version = normalizeCompiledVersion(
|
|
||||||
diagnosticsSystemInfo.podkop_version
|
|
||||||
);
|
|
||||||
const isDevVersion = version === "dev";
|
|
||||||
if (loading || unknown || !hasActualVersion || isDevVersion) {
|
|
||||||
return {
|
|
||||||
key: "Podkop",
|
|
||||||
value: version
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (version !== `v${diagnosticsSystemInfo.podkop_latest_version}`) {
|
|
||||||
logger.debug(
|
|
||||||
"[DIAGNOSTIC]",
|
|
||||||
"diagnosticsSystemInfo",
|
|
||||||
diagnosticsSystemInfo
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
key: "Podkop",
|
|
||||||
value: version,
|
|
||||||
tag: {
|
|
||||||
label: _("Outdated"),
|
|
||||||
kind: "warning"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
key: "Podkop",
|
|
||||||
value: version,
|
|
||||||
tag: {
|
|
||||||
label: _("Latest"),
|
|
||||||
kind: "success"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const renderedSystemInfo = renderSystemInfo({
|
const renderedSystemInfo = renderSystemInfo({
|
||||||
items: [
|
items: [
|
||||||
getPodkopVersionRow(),
|
getPodkopVersionRow(diagnosticsSystemInfo),
|
||||||
{
|
{
|
||||||
key: "Luci App",
|
key: "Luci App",
|
||||||
value: normalizeCompiledVersion(PODKOP_LUCI_APP_VERSION)
|
value: normalizeCompiledVersion(PODKOP_LUCI_APP_VERSION)
|
||||||
@@ -4118,6 +4369,7 @@ async function runChecks() {
|
|||||||
await runDnsCheck();
|
await runDnsCheck();
|
||||||
await runSingBoxCheck();
|
await runSingBoxCheck();
|
||||||
await runNftCheck();
|
await runNftCheck();
|
||||||
|
await runSectionsCheck();
|
||||||
await runFakeIPCheck();
|
await runFakeIPCheck();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error("[DIAGNOSTIC]", "runChecks - e", e);
|
logger.error("[DIAGNOSTIC]", "runChecks - e", e);
|
||||||
@@ -4624,6 +4876,10 @@ function insertIf(condition, elements) {
|
|||||||
function insertIfObj(condition, object) {
|
function insertIfObj(condition, object) {
|
||||||
return condition ? object : {};
|
return condition ? object : {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// src/main.ts
|
||||||
|
if (typeof structuredClone !== "function")
|
||||||
|
globalThis.structuredClone = (obj) => JSON.parse(JSON.stringify(obj));
|
||||||
return baseclass.extend({
|
return baseclass.extend({
|
||||||
ALLOWED_WITH_RUSSIA_INSIDE,
|
ALLOWED_WITH_RUSSIA_INSIDE,
|
||||||
BOOTSTRAP_DNS_SERVER_OPTIONS,
|
BOOTSTRAP_DNS_SERVER_OPTIONS,
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ function createSectionContent(section) {
|
|||||||
o.value("proxy", "Proxy");
|
o.value("proxy", "Proxy");
|
||||||
o.value("vpn", "VPN");
|
o.value("vpn", "VPN");
|
||||||
o.value("block", "Block");
|
o.value("block", "Block");
|
||||||
|
o.value("exclusion", "Exclusion");
|
||||||
|
|
||||||
o = section.option(
|
o = section.option(
|
||||||
form.ListValue,
|
form.ListValue,
|
||||||
@@ -23,8 +24,9 @@ function createSectionContent(section) {
|
|||||||
_("Select how to configure the proxy"),
|
_("Select how to configure the proxy"),
|
||||||
);
|
);
|
||||||
o.value("url", _("Connection URL"));
|
o.value("url", _("Connection URL"));
|
||||||
o.value("outbound", _("Outbound Config"));
|
o.value("selector", _("Selector"));
|
||||||
o.value("urltest", _("URLTest"));
|
o.value("urltest", _("URLTest"));
|
||||||
|
o.value("outbound", _("Outbound Config"));
|
||||||
o.default = "url";
|
o.default = "url";
|
||||||
o.depends("connection_type", "proxy");
|
o.depends("connection_type", "proxy");
|
||||||
|
|
||||||
@@ -32,7 +34,7 @@ function createSectionContent(section) {
|
|||||||
form.TextValue,
|
form.TextValue,
|
||||||
"proxy_string",
|
"proxy_string",
|
||||||
_("Proxy Configuration URL"),
|
_("Proxy Configuration URL"),
|
||||||
"",
|
_("vless://, ss://, trojan://, socks4/5://, hy2/hysteria2:// links")
|
||||||
);
|
);
|
||||||
o.depends("proxy_config_type", "url");
|
o.depends("proxy_config_type", "url");
|
||||||
o.rows = 5;
|
o.rows = 5;
|
||||||
@@ -42,7 +44,6 @@ function createSectionContent(section) {
|
|||||||
o.textarea = true;
|
o.textarea = true;
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
o.sectionDescriptions = new Map();
|
o.sectionDescriptions = new Map();
|
||||||
o.placeholder = "vless://uuid@server:port?type=tcp&security=tls#main";
|
|
||||||
o.validate = function (section_id, value) {
|
o.validate = function (section_id, value) {
|
||||||
// Optional
|
// Optional
|
||||||
if (!value || value.length === 0) {
|
if (!value || value.length === 0) {
|
||||||
@@ -83,11 +84,11 @@ function createSectionContent(section) {
|
|||||||
|
|
||||||
o = section.option(
|
o = section.option(
|
||||||
form.DynamicList,
|
form.DynamicList,
|
||||||
"urltest_proxy_links",
|
"selector_proxy_links",
|
||||||
_("URLTest Proxy Links"),
|
_("Selector Proxy Links"),
|
||||||
|
_("vless://, ss://, trojan://, socks4/5://, hy2/hysteria2:// links")
|
||||||
);
|
);
|
||||||
o.depends("proxy_config_type", "urltest");
|
o.depends("proxy_config_type", "selector");
|
||||||
o.placeholder = "vless://, ss://, trojan://, socks4/5:// links";
|
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
o.validate = function (section_id, value) {
|
o.validate = function (section_id, value) {
|
||||||
// Optional
|
// Optional
|
||||||
@@ -104,6 +105,93 @@ function createSectionContent(section) {
|
|||||||
return validation.message;
|
return validation.message;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
o = section.option(
|
||||||
|
form.DynamicList,
|
||||||
|
"urltest_proxy_links",
|
||||||
|
_("URLTest Proxy Links"),
|
||||||
|
_("vless://, ss://, trojan://, socks4/5://, hy2/hysteria2:// links")
|
||||||
|
);
|
||||||
|
o.depends("proxy_config_type", "urltest");
|
||||||
|
o.rmempty = false;
|
||||||
|
o.validate = function (section_id, value) {
|
||||||
|
// Optional
|
||||||
|
if (!value || value.length === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const validation = main.validateProxyUrl(value);
|
||||||
|
|
||||||
|
if (validation.valid) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return validation.message;
|
||||||
|
};
|
||||||
|
|
||||||
|
o = section.option(
|
||||||
|
form.ListValue,
|
||||||
|
"urltest_check_interval",
|
||||||
|
_("URLTest Check Interval"),
|
||||||
|
_("The interval between connectivity tests")
|
||||||
|
);
|
||||||
|
o.value("30s", _("Every 30 seconds"));
|
||||||
|
o.value("1m", _("Every 1 minute"));
|
||||||
|
o.value("3m", _("Every 3 minutes"));
|
||||||
|
o.value("5m", _("Every 5 minutes"));
|
||||||
|
o.default = "3m";
|
||||||
|
o.depends("proxy_config_type", "urltest");
|
||||||
|
|
||||||
|
o = section.option(
|
||||||
|
form.Value,
|
||||||
|
"urltest_tolerance",
|
||||||
|
_("URLTest Tolerance"),
|
||||||
|
_("The maximum difference in response times (ms) allowed when comparing servers")
|
||||||
|
);
|
||||||
|
o.default = "50";
|
||||||
|
o.rmempty = false;
|
||||||
|
o.depends("proxy_config_type", "urltest");
|
||||||
|
o.validate = function (section_id, value) {
|
||||||
|
if (!value || value.length === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsed = parseFloat(value);
|
||||||
|
|
||||||
|
if (/^[0-9]+$/.test(value) && !isNaN(parsed) && isFinite(parsed) && parsed >= 50 && parsed <= 1000) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _('Must be a number in the range of 50 - 1000');
|
||||||
|
};
|
||||||
|
|
||||||
|
o = section.option(
|
||||||
|
form.Value,
|
||||||
|
"urltest_testing_url",
|
||||||
|
_("URLTest Testing URL"),
|
||||||
|
_("The URL used to test server connectivity")
|
||||||
|
);
|
||||||
|
o.value("https://www.gstatic.com/generate_204", "https://www.gstatic.com/generate_204 (Google)");
|
||||||
|
o.value("https://cp.cloudflare.com/generate_204", "https://cp.cloudflare.com/generate_204 (Cloudflare)");
|
||||||
|
o.value("https://captive.apple.com", "https://captive.apple.com (Apple)");
|
||||||
|
o.value("https://connectivity-check.ubuntu.com", "https://connectivity-check.ubuntu.com (Ubuntu)")
|
||||||
|
o.default = "https://www.gstatic.com/generate_204";
|
||||||
|
o.rmempty = false;
|
||||||
|
o.depends("proxy_config_type", "urltest");
|
||||||
|
|
||||||
|
o.validate = function (section_id, value) {
|
||||||
|
if (!value || value.length === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const validation = main.validateUrl(value);
|
||||||
|
|
||||||
|
if (validation.valid) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return validation.message;
|
||||||
|
};
|
||||||
|
|
||||||
o = section.option(
|
o = section.option(
|
||||||
form.Flag,
|
form.Flag,
|
||||||
"enable_udp_over_tcp",
|
"enable_udp_over_tcp",
|
||||||
@@ -381,7 +469,7 @@ function createSectionContent(section) {
|
|||||||
);
|
);
|
||||||
o.value("disabled", _("Disabled"));
|
o.value("disabled", _("Disabled"));
|
||||||
o.value("dynamic", _("Dynamic List"));
|
o.value("dynamic", _("Dynamic List"));
|
||||||
o.value("text", _("Text List (comma/space/newline separated)"));
|
o.value("text", _("Text List"));
|
||||||
o.default = "disabled";
|
o.default = "disabled";
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
|
|
||||||
@@ -554,6 +642,8 @@ function createSectionContent(section) {
|
|||||||
);
|
);
|
||||||
o.placeholder = "192.168.1.2 or 192.168.1.0/24";
|
o.placeholder = "192.168.1.2 or 192.168.1.0/24";
|
||||||
o.rmempty = true;
|
o.rmempty = true;
|
||||||
|
o.depends("connection_type", "proxy");
|
||||||
|
o.depends("connection_type", "vpn");
|
||||||
o.validate = function (section_id, value) {
|
o.validate = function (section_id, value) {
|
||||||
// Optional
|
// Optional
|
||||||
if (!value || value.length === 0) {
|
if (!value || value.length === 0) {
|
||||||
@@ -579,6 +669,8 @@ function createSectionContent(section) {
|
|||||||
);
|
);
|
||||||
o.default = "0";
|
o.default = "0";
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
|
o.depends("connection_type", "proxy");
|
||||||
|
o.depends("connection_type", "vpn");
|
||||||
|
|
||||||
o = section.option(
|
o = section.option(
|
||||||
form.Value,
|
form.Value,
|
||||||
@@ -591,6 +683,17 @@ function createSectionContent(section) {
|
|||||||
);
|
);
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
o.depends("mixed_proxy_enabled", "1");
|
o.depends("mixed_proxy_enabled", "1");
|
||||||
|
|
||||||
|
o = section.option(
|
||||||
|
form.Flag,
|
||||||
|
"resolve_real_ip_for_routing",
|
||||||
|
_("Resolve real IP for routing"),
|
||||||
|
_("Enable DNS resolve to get real IP when routing"),
|
||||||
|
);
|
||||||
|
o.default = "0";
|
||||||
|
o.rmempty = false;
|
||||||
|
o.depends("connection_type", "proxy");
|
||||||
|
o.depends("connection_type", "vpn");
|
||||||
}
|
}
|
||||||
|
|
||||||
const EntryPoint = {
|
const EntryPoint = {
|
||||||
|
|||||||
@@ -240,6 +240,25 @@ function createSettingsContent(section) {
|
|||||||
o.default = "0";
|
o.default = "0";
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
|
|
||||||
|
o = section.option(
|
||||||
|
form.Flag,
|
||||||
|
"enable_yacd_wan_access",
|
||||||
|
_("Enable YACD WAN Access"),
|
||||||
|
_("Allows access to YACD from the WAN. Make sure to open the appropriate port in your firewall."),
|
||||||
|
);
|
||||||
|
o.depends("enable_yacd", "1");
|
||||||
|
o.default = "0";
|
||||||
|
o.rmempty = false;
|
||||||
|
|
||||||
|
o = section.option(
|
||||||
|
form.Value,
|
||||||
|
"yacd_secret_key",
|
||||||
|
_("YACD Secret Key"),
|
||||||
|
_("Secret key for authenticating remote access to YACD when WAN access is enabled."),
|
||||||
|
);
|
||||||
|
o.depends("enable_yacd_wan_access", "1");
|
||||||
|
o.rmempty = false;
|
||||||
|
|
||||||
o = section.option(
|
o = section.option(
|
||||||
form.Flag,
|
form.Flag,
|
||||||
"disable_quic",
|
"disable_quic",
|
||||||
@@ -267,7 +286,7 @@ function createSettingsContent(section) {
|
|||||||
form.Flag,
|
form.Flag,
|
||||||
"download_lists_via_proxy",
|
"download_lists_via_proxy",
|
||||||
_("Download Lists via Proxy/VPN"),
|
_("Download Lists via Proxy/VPN"),
|
||||||
_("Downloading all lists via main Proxy/VPN"),
|
_("Downloading all lists via specific Proxy/VPN"),
|
||||||
);
|
);
|
||||||
o.default = "0";
|
o.default = "0";
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
@@ -292,7 +311,7 @@ function createSettingsContent(section) {
|
|||||||
|
|
||||||
for (const secName in sections) {
|
for (const secName in sections) {
|
||||||
const sec = sections[secName];
|
const sec = sections[secName];
|
||||||
if (sec[".type"] === "section") {
|
if (sec[".type"] === "section" && sec['connection_type'] !== 'block' && sec['connection_type'] !== 'exclusion') {
|
||||||
this.keylist.push(secName);
|
this.keylist.push(secName);
|
||||||
this.vallist.push(secName);
|
this.vallist.push(secName);
|
||||||
}
|
}
|
||||||
@@ -359,6 +378,24 @@ function createSettingsContent(section) {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
o = section.option(
|
||||||
|
form.ListValue,
|
||||||
|
"log_level",
|
||||||
|
_("Log Level"),
|
||||||
|
_(
|
||||||
|
"Select the log level for sing-box",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
o.value("trace", "Trace");
|
||||||
|
o.value("debug", "Debug");
|
||||||
|
o.value("info", "Info");
|
||||||
|
o.value("warn", "Warn");
|
||||||
|
o.value("error", "Error");
|
||||||
|
o.value("fatal", "Fatal");
|
||||||
|
o.value("panic", "Panic");
|
||||||
|
o.default = "warn";
|
||||||
|
o.rmempty = false;
|
||||||
|
|
||||||
o = section.option(
|
o = section.option(
|
||||||
form.Flag,
|
form.Flag,
|
||||||
"exclude_ntp",
|
"exclude_ntp",
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
# RU translations for PODKOP package.
|
# RU translations for PODKOP package.
|
||||||
# Copyright (C) 2025 THE PODKOP'S COPYRIGHT HOLDER
|
# Copyright (C) 2026 THE PODKOP'S COPYRIGHT HOLDER
|
||||||
# This file is distributed under the same license as the PODKOP package.
|
# This file is distributed under the same license as the PODKOP package.
|
||||||
# divocat, 2025.
|
# divocatt, 2026.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PODKOP\n"
|
"Project-Id-Version: PODKOP\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-10-23 20:43+0300\n"
|
"POT-Creation-Date: 2026-05-29 16:40+0300\n"
|
||||||
"PO-Revision-Date: 2025-10-23 20:43+0300\n"
|
"PO-Revision-Date: 2026-05-29 16:40+0300\n"
|
||||||
"Last-Translator: divocat\n"
|
"Last-Translator: divocatt\n"
|
||||||
"Language-Team: none\n"
|
"Language-Team: none\n"
|
||||||
"Language: ru\n"
|
"Language: ru\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@@ -35,6 +35,9 @@ msgstr "Активные соединения"
|
|||||||
msgid "Additional marking rules found"
|
msgid "Additional marking rules found"
|
||||||
msgstr "Найдены дополнительные правила маркировки"
|
msgstr "Найдены дополнительные правила маркировки"
|
||||||
|
|
||||||
|
msgid "Allows access to YACD from the WAN. Make sure to open the appropriate port in your firewall."
|
||||||
|
msgstr "Обеспечивает доступ к YACD из WAN. Убедитесь, что в брандмауэре открыт соответствующий порт."
|
||||||
|
|
||||||
msgid "Applicable for SOCKS and Shadowsocks proxy"
|
msgid "Applicable for SOCKS and Shadowsocks proxy"
|
||||||
msgstr "Применимо для SOCKS и Shadowsocks прокси"
|
msgstr "Применимо для SOCKS и Shadowsocks прокси"
|
||||||
|
|
||||||
@@ -182,9 +185,6 @@ msgstr "Скачивать списки через Proxy/VPN"
|
|||||||
msgid "Download Lists via specific proxy section"
|
msgid "Download Lists via specific proxy section"
|
||||||
msgstr "Скачивать списки через выбранную секцию"
|
msgstr "Скачивать списки через выбранную секцию"
|
||||||
|
|
||||||
msgid "Downloading all lists via main Proxy/VPN"
|
|
||||||
msgstr "Загрузка всех списков через основной прокси/VPN"
|
|
||||||
|
|
||||||
msgid "Downloading all lists via specific Proxy/VPN"
|
msgid "Downloading all lists via specific Proxy/VPN"
|
||||||
msgstr "Загрузка всех списков через указанный прокси/VPN"
|
msgstr "Загрузка всех списков через указанный прокси/VPN"
|
||||||
|
|
||||||
@@ -197,6 +197,9 @@ msgstr "Включить автостарт"
|
|||||||
msgid "Enable built-in DNS resolver for domains handled by this section"
|
msgid "Enable built-in DNS resolver for domains handled by this section"
|
||||||
msgstr "Включить встроенный DNS-резолвер для доменов, обрабатываемых в этом разделе"
|
msgstr "Включить встроенный DNS-резолвер для доменов, обрабатываемых в этом разделе"
|
||||||
|
|
||||||
|
msgid "Enable DNS resolve to get real IP when routing"
|
||||||
|
msgstr "Разрешать домены в реальные IP-адреса перед маршрутизацией в outbound"
|
||||||
|
|
||||||
msgid "Enable Mixed Proxy"
|
msgid "Enable Mixed Proxy"
|
||||||
msgstr "Включить смешанный прокси"
|
msgstr "Включить смешанный прокси"
|
||||||
|
|
||||||
@@ -209,6 +212,9 @@ msgstr "Включить смешанный прокси-сервер, разр
|
|||||||
msgid "Enable YACD"
|
msgid "Enable YACD"
|
||||||
msgstr "Включить YACD"
|
msgstr "Включить YACD"
|
||||||
|
|
||||||
|
msgid "Enable YACD WAN Access"
|
||||||
|
msgstr "Включить доступ YACD WAN"
|
||||||
|
|
||||||
msgid "Enter complete outbound configuration in JSON format"
|
msgid "Enter complete outbound configuration in JSON format"
|
||||||
msgstr "Введите полную конфигурацию исходящего соединения в формате JSON"
|
msgstr "Введите полную конфигурацию исходящего соединения в формате JSON"
|
||||||
|
|
||||||
@@ -221,6 +227,18 @@ msgstr "Введите доменные имена без протоколов,
|
|||||||
msgid "Enter subnets in CIDR notation (e.g. 103.21.244.0/22) or single IP addresses"
|
msgid "Enter subnets in CIDR notation (e.g. 103.21.244.0/22) or single IP addresses"
|
||||||
msgstr "Введите подсети в нотации CIDR (например, 103.21.244.0/22) или отдельные IP-адреса"
|
msgstr "Введите подсети в нотации CIDR (например, 103.21.244.0/22) или отдельные IP-адреса"
|
||||||
|
|
||||||
|
msgid "Every 1 minute"
|
||||||
|
msgstr "Каждую минуту"
|
||||||
|
|
||||||
|
msgid "Every 3 minutes"
|
||||||
|
msgstr "Каждые 3 минуты"
|
||||||
|
|
||||||
|
msgid "Every 30 seconds"
|
||||||
|
msgstr "Каждые 30 секунд"
|
||||||
|
|
||||||
|
msgid "Every 5 minutes"
|
||||||
|
msgstr "Каждые 5 минут"
|
||||||
|
|
||||||
msgid "Exclude NTP"
|
msgid "Exclude NTP"
|
||||||
msgstr "Исключить NTP"
|
msgstr "Исключить NTP"
|
||||||
|
|
||||||
@@ -266,6 +284,45 @@ msgstr "Неверный домен"
|
|||||||
msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y"
|
msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y"
|
||||||
msgstr "Неверный формат. Используйте X.X.X.X или X.X.X.X/Y"
|
msgstr "Неверный формат. Используйте X.X.X.X или X.X.X.X/Y"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: insecure must be 0 or 1"
|
||||||
|
msgstr "Неверный URL Hysteria2: параметр insecure должен быть 0 или 1"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: invalid port number"
|
||||||
|
msgstr "Неверный URL Hysteria2: неверный номер порта"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: missing credentials/server"
|
||||||
|
msgstr "Неверный URL Hysteria2: отсутствуют учетные данные/сервер"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: missing host"
|
||||||
|
msgstr "Неверный URL Hysteria2: отсутствует хост"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: missing host & port"
|
||||||
|
msgstr "Неверный URL Hysteria2: отсутствуют хост и порт"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: missing password"
|
||||||
|
msgstr "Неверный URL Hysteria2: отсутствует пароль"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: missing port"
|
||||||
|
msgstr "Неверный URL Hysteria2: отсутствует порт"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: must not contain spaces"
|
||||||
|
msgstr "Неверный URL Hysteria2: не должен содержать пробелов"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: must start with hysteria2:// or hy2://"
|
||||||
|
msgstr "Неверный URL Hysteria2: должен начинаться с hysteria2:// или hy2://"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: obfs-password required when obfs is set"
|
||||||
|
msgstr "Неверный URL Hysteria2: требуется obfs-password, когда установлен obfs"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: parsing failed"
|
||||||
|
msgstr "Неверный URL Hysteria2: ошибка разбора"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: sni cannot be empty"
|
||||||
|
msgstr "Неверный URL Hysteria2: sni не может быть пустым"
|
||||||
|
|
||||||
|
msgid "Invalid HY2 URL: unsupported obfs type"
|
||||||
|
msgstr "Неверный URL Hysteria2: неподдерживаемый тип obfs"
|
||||||
|
|
||||||
msgid "Invalid IP address"
|
msgid "Invalid IP address"
|
||||||
msgstr "Неверный IP-адрес"
|
msgstr "Неверный IP-адрес"
|
||||||
|
|
||||||
@@ -365,6 +422,9 @@ msgstr "Локальные списки доменов"
|
|||||||
msgid "Local Subnet Lists"
|
msgid "Local Subnet Lists"
|
||||||
msgstr "Локальные списки подсетей"
|
msgstr "Локальные списки подсетей"
|
||||||
|
|
||||||
|
msgid "Log Level"
|
||||||
|
msgstr "Уровень логов"
|
||||||
|
|
||||||
msgid "Main DNS"
|
msgid "Main DNS"
|
||||||
msgstr "Основной DNS"
|
msgstr "Основной DNS"
|
||||||
|
|
||||||
@@ -377,6 +437,9 @@ msgstr "Порт смешанного прокси"
|
|||||||
msgid "Monitored Interfaces"
|
msgid "Monitored Interfaces"
|
||||||
msgstr "Наблюдаемые интерфейсы"
|
msgstr "Наблюдаемые интерфейсы"
|
||||||
|
|
||||||
|
msgid "Must be a number in the range of 50 - 1000"
|
||||||
|
msgstr "Должно быть числом от 50 до 1000"
|
||||||
|
|
||||||
msgid "Network Interface"
|
msgid "Network Interface"
|
||||||
msgstr "Сетевой интерфейс"
|
msgstr "Сетевой интерфейс"
|
||||||
|
|
||||||
@@ -386,6 +449,9 @@ msgstr "Другие правила маркировки не найдены"
|
|||||||
msgid "Not implement yet"
|
msgid "Not implement yet"
|
||||||
msgstr "Ещё не реализовано"
|
msgstr "Ещё не реализовано"
|
||||||
|
|
||||||
|
msgid "Not responding"
|
||||||
|
msgstr "Не отвечает"
|
||||||
|
|
||||||
msgid "Not running"
|
msgid "Not running"
|
||||||
msgstr "Не запущено"
|
msgstr "Не запущено"
|
||||||
|
|
||||||
@@ -398,9 +464,6 @@ msgstr "Конфигурация Outbound"
|
|||||||
msgid "Outbound Configuration"
|
msgid "Outbound Configuration"
|
||||||
msgstr "Конфигурация исходящего соединения"
|
msgstr "Конфигурация исходящего соединения"
|
||||||
|
|
||||||
msgid "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields"
|
|
||||||
msgstr "JSON должен содержать поля \"type\", \"server\" и \"server_port\""
|
|
||||||
|
|
||||||
msgid "Outdated"
|
msgid "Outdated"
|
||||||
msgstr "Устаревшая"
|
msgstr "Устаревшая"
|
||||||
|
|
||||||
@@ -449,6 +512,9 @@ msgstr "Внешние списки доменов"
|
|||||||
msgid "Remote Subnet Lists"
|
msgid "Remote Subnet Lists"
|
||||||
msgstr "Внешние списки подсетей"
|
msgstr "Внешние списки подсетей"
|
||||||
|
|
||||||
|
msgid "Resolve real IP for routing"
|
||||||
|
msgstr "Разрешение реальных IP-адресов"
|
||||||
|
|
||||||
msgid "Restart podkop"
|
msgid "Restart podkop"
|
||||||
msgstr "Перезапустить Podkop"
|
msgstr "Перезапустить Podkop"
|
||||||
|
|
||||||
@@ -485,6 +551,9 @@ msgstr "Запустить диагностику"
|
|||||||
msgid "Russia inside restrictions"
|
msgid "Russia inside restrictions"
|
||||||
msgstr "Ограничения Russia inside"
|
msgstr "Ограничения Russia inside"
|
||||||
|
|
||||||
|
msgid "Secret key for authenticating remote access to YACD when WAN access is enabled."
|
||||||
|
msgstr "Секретный ключ для аутентификации удаленного доступа к YACD при включенном доступе через WAN."
|
||||||
|
|
||||||
msgid "Sections"
|
msgid "Sections"
|
||||||
msgstr "Секции"
|
msgstr "Секции"
|
||||||
|
|
||||||
@@ -524,6 +593,9 @@ msgstr "Выберите тип списка для добавления пол
|
|||||||
msgid "Select the list type for adding custom subnets"
|
msgid "Select the list type for adding custom subnets"
|
||||||
msgstr "Выберите тип списка для добавления пользовательских подсетей"
|
msgstr "Выберите тип списка для добавления пользовательских подсетей"
|
||||||
|
|
||||||
|
msgid "Select the log level for sing-box"
|
||||||
|
msgstr "Выберите уровень логов для sing-box"
|
||||||
|
|
||||||
msgid "Select the network interface from which the traffic will originate"
|
msgid "Select the network interface from which the traffic will originate"
|
||||||
msgstr "Выберите сетевой интерфейс, с которого будет исходить трафик"
|
msgstr "Выберите сетевой интерфейс, с которого будет исходить трафик"
|
||||||
|
|
||||||
@@ -533,6 +605,12 @@ msgstr "Выберите сетевой интерфейс, на который
|
|||||||
msgid "Select the WAN interfaces to be monitored"
|
msgid "Select the WAN interfaces to be monitored"
|
||||||
msgstr "Выберите WAN интерфейсы для мониторинга"
|
msgstr "Выберите WAN интерфейсы для мониторинга"
|
||||||
|
|
||||||
|
msgid "Selector"
|
||||||
|
msgstr "Selector"
|
||||||
|
|
||||||
|
msgid "Selector Proxy Links"
|
||||||
|
msgstr "Ссылки прокси для Selector"
|
||||||
|
|
||||||
msgid "Services info"
|
msgid "Services info"
|
||||||
msgstr "Информация о сервисах"
|
msgstr "Информация о сервисах"
|
||||||
|
|
||||||
@@ -560,8 +638,8 @@ msgstr "Процесс sing-box запущен"
|
|||||||
msgid "Sing-box service exist"
|
msgid "Sing-box service exist"
|
||||||
msgstr "Сервис sing-box существует"
|
msgstr "Сервис sing-box существует"
|
||||||
|
|
||||||
msgid "Sing-box version >= 1.12.4"
|
msgid "Sing-box version is compatible (newer than 1.12.4)"
|
||||||
msgstr "Версия sing-box >= 1.12.4"
|
msgstr "Версия Sing-box совместима (новее 1.12.4)"
|
||||||
|
|
||||||
msgid "Source Network Interface"
|
msgid "Source Network Interface"
|
||||||
msgstr "Сетевой интерфейс источника"
|
msgstr "Сетевой интерфейс источника"
|
||||||
@@ -605,12 +683,18 @@ msgstr "Тестирование задержки"
|
|||||||
msgid "Text List"
|
msgid "Text List"
|
||||||
msgstr "Текстовый список"
|
msgstr "Текстовый список"
|
||||||
|
|
||||||
msgid "Text List (comma/space/newline separated)"
|
|
||||||
msgstr "Текстовый список (через запятую, пробел или новую строку)"
|
|
||||||
|
|
||||||
msgid "The DNS server used to look up the IP address of an upstream DNS server"
|
msgid "The DNS server used to look up the IP address of an upstream DNS server"
|
||||||
msgstr "DNS-сервер, используемый для поиска IP-адреса вышестоящего DNS-сервера"
|
msgstr "DNS-сервер, используемый для поиска IP-адреса вышестоящего DNS-сервера"
|
||||||
|
|
||||||
|
msgid "The interval between connectivity tests"
|
||||||
|
msgstr "Интервал между тестами подключения"
|
||||||
|
|
||||||
|
msgid "The maximum difference in response times (ms) allowed when comparing servers"
|
||||||
|
msgstr "Максимально допустимая разница во времени отклика (мс) при сравнении серверов"
|
||||||
|
|
||||||
|
msgid "The URL used to test server connectivity"
|
||||||
|
msgstr "URL-адрес, используемый для проверки подключения к серверу"
|
||||||
|
|
||||||
msgid "Time in seconds for DNS record caching (default: 60)"
|
msgid "Time in seconds for DNS record caching (default: 60)"
|
||||||
msgstr "Время в секундах для кэширования DNS записей (по умолчанию: 60)"
|
msgstr "Время в секундах для кэширования DNS записей (по умолчанию: 60)"
|
||||||
|
|
||||||
@@ -644,8 +728,8 @@ msgstr "Неизвестная ошибка"
|
|||||||
msgid "Uplink"
|
msgid "Uplink"
|
||||||
msgstr "Исходящий"
|
msgstr "Исходящий"
|
||||||
|
|
||||||
msgid "URL must start with vless://, ss://, trojan://, or socks4/5://"
|
msgid "URL must start with vless://, ss://, trojan://, socks4/5://, or hysteria2://hy2://"
|
||||||
msgstr "URL должен начинаться с vless://, ss://, trojan:// или socks4/5://"
|
msgstr "URL должен начинаться с vless://, ss://, trojan://, socks4/5:// или hysteria2:// hy2://"
|
||||||
|
|
||||||
msgid "URL must use one of the following protocols:"
|
msgid "URL must use one of the following protocols:"
|
||||||
msgstr "URL должен использовать один из следующих протоколов:"
|
msgstr "URL должен использовать один из следующих протоколов:"
|
||||||
@@ -653,9 +737,18 @@ msgstr "URL должен использовать один из следующи
|
|||||||
msgid "URLTest"
|
msgid "URLTest"
|
||||||
msgstr "URLTest"
|
msgstr "URLTest"
|
||||||
|
|
||||||
|
msgid "URLTest Check Interval"
|
||||||
|
msgstr "Интервал проверки URLTest"
|
||||||
|
|
||||||
msgid "URLTest Proxy Links"
|
msgid "URLTest Proxy Links"
|
||||||
msgstr "Ссылки прокси для URLTest"
|
msgstr "Ссылки прокси для URLTest"
|
||||||
|
|
||||||
|
msgid "URLTest Testing URL"
|
||||||
|
msgstr "URLTest ссылка для проверки"
|
||||||
|
|
||||||
|
msgid "URLTest Tolerance"
|
||||||
|
msgstr "URLTest допустимое отклонение"
|
||||||
|
|
||||||
msgid "User Domain List Type"
|
msgid "User Domain List Type"
|
||||||
msgstr "Тип пользовательского списка доменов"
|
msgstr "Тип пользовательского списка доменов"
|
||||||
|
|
||||||
@@ -686,11 +779,17 @@ msgstr "Посмотреть логи"
|
|||||||
msgid "Visit Wiki"
|
msgid "Visit Wiki"
|
||||||
msgstr "Перейти в wiki"
|
msgstr "Перейти в wiki"
|
||||||
|
|
||||||
|
msgid "vless://, ss://, trojan://, socks4/5://, hy2/hysteria2:// links"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Warning: %s cannot be used together with %s. Previous selections have been removed."
|
msgid "Warning: %s cannot be used together with %s. Previous selections have been removed."
|
||||||
msgstr "Предупреждение: %s нельзя использовать вместе с %s. Предыдущие варианты были удалены."
|
msgstr "Предупреждение: %s нельзя использовать вместе с %s. Предыдущие варианты были удалены."
|
||||||
|
|
||||||
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
|
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 и будет удален из выбранных."
|
msgstr "Предупреждение: Russia inside может быть использован только с %s. %s уже есть в Russia inside и будет удален из выбранных."
|
||||||
|
|
||||||
|
msgid "YACD Secret Key"
|
||||||
|
msgstr "Секретный ключ YACD"
|
||||||
|
|
||||||
msgid "You can select Output Network Interface, by default autodetect"
|
msgid "You can select Output Network Interface, by default autodetect"
|
||||||
msgstr "Вы можете выбрать выходной сетевой интерфейс, по умолчанию он определяется автоматически."
|
msgstr "Вы можете выбрать выходной сетевой интерфейс, по умолчанию он определяется автоматически."
|
||||||
|
|||||||
@@ -1,38 +1,38 @@
|
|||||||
# SOME DESCRIPTIVE TITLE.
|
# SOME DESCRIPTIVE TITLE.
|
||||||
# Copyright (C) 2025 THE PACKAGE'S COPYRIGHT HOLDER
|
# Copyright (C) 2026 THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
# This file is distributed under the same license as the PODKOP package.
|
# This file is distributed under the same license as the PODKOP package.
|
||||||
# divocat <divocatt@gmail.com>, 2025.
|
# divocatt <210179590+divocatt@users.noreply.github.com>, 2026.
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PODKOP\n"
|
"Project-Id-Version: PODKOP\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-10-23 17:43+0300\n"
|
"POT-Creation-Date: 2026-05-29 13:40+0300\n"
|
||||||
"PO-Revision-Date: 2025-10-23 17:43+0300\n"
|
"PO-Revision-Date: 2026-05-29 13:40+0300\n"
|
||||||
"Last-Translator: divocat <divocatt@gmail.com>\n"
|
"Last-Translator: divocatt <210179590+divocatt@users.noreply.github.com>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
"Language: \n"
|
"Language: \n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:342
|
#: src/podkop/tabs/dashboard/initController.ts:345
|
||||||
msgid "✔ Enabled"
|
msgid "✔ Enabled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:353
|
#: src/podkop/tabs/dashboard/initController.ts:356
|
||||||
msgid "✔ Running"
|
msgid "✔ Running"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:343
|
#: src/podkop/tabs/dashboard/initController.ts:346
|
||||||
msgid "✘ Disabled"
|
msgid "✘ Disabled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:354
|
#: src/podkop/tabs/dashboard/initController.ts:357
|
||||||
msgid "✘ Stopped"
|
msgid "✘ Stopped"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:304
|
#: src/podkop/tabs/dashboard/initController.ts:307
|
||||||
msgid "Active Connections"
|
msgid "Active Connections"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -40,15 +40,19 @@ msgstr ""
|
|||||||
msgid "Additional marking rules found"
|
msgid "Additional marking rules found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:111
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:247
|
||||||
|
msgid "Allows access to YACD from the WAN. Make sure to open the appropriate port in your firewall."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:199
|
||||||
msgid "Applicable for SOCKS and Shadowsocks proxy"
|
msgid "Applicable for SOCKS and Shadowsocks proxy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:356
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:444
|
||||||
msgid "At least one valid domain must be specified. Comments-only content is not allowed."
|
msgid "At least one valid domain must be specified. Comments-only content is not allowed."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:437
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:525
|
||||||
msgid "At least one valid subnet or IP must be specified. Comments-only content is not allowed."
|
msgid "At least one valid subnet or IP must be specified. Comments-only content is not allowed."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -72,16 +76,17 @@ msgstr ""
|
|||||||
msgid "Browser is using FakeIP correctly"
|
msgid "Browser is using FakeIP correctly"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:329
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:348
|
||||||
msgid "Cache File Path"
|
msgid "Cache File Path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:343
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:362
|
||||||
msgid "Cache file path cannot be empty"
|
msgid "Cache file path cannot be empty"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:27
|
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:27
|
||||||
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:28
|
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:28
|
||||||
|
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:27
|
||||||
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:25
|
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:25
|
||||||
msgid "Cannot receive checks result"
|
msgid "Cannot receive checks result"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -89,6 +94,7 @@ msgstr ""
|
|||||||
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:15
|
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:15
|
||||||
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:15
|
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:15
|
||||||
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:13
|
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:13
|
||||||
|
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:15
|
||||||
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:13
|
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:13
|
||||||
msgid "Checking, please wait"
|
msgid "Checking, please wait"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -113,11 +119,11 @@ msgstr ""
|
|||||||
msgid "Close"
|
msgid "Close"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:211
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:299
|
||||||
msgid "Community Lists"
|
msgid "Community Lists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:316
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:335
|
||||||
msgid "Config File Path"
|
msgid "Config File Path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -125,7 +131,7 @@ msgstr ""
|
|||||||
msgid "Configuration for Podkop service"
|
msgid "Configuration for Podkop service"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:22
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:23
|
||||||
msgid "Configuration Type"
|
msgid "Configuration Type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -133,7 +139,7 @@ msgstr ""
|
|||||||
msgid "Connection Type"
|
msgid "Connection Type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:25
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:26
|
||||||
msgid "Connection URL"
|
msgid "Connection URL"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -173,16 +179,16 @@ msgstr ""
|
|||||||
msgid "Disable autostart"
|
msgid "Disable autostart"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:246
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:265
|
||||||
msgid "Disable QUIC"
|
msgid "Disable QUIC"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:247
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:266
|
||||||
msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming"
|
msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:302
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:390
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:382
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:470
|
||||||
msgid "Disabled"
|
msgid "Disabled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -190,17 +196,17 @@ msgstr ""
|
|||||||
msgid "DNS on router"
|
msgid "DNS on router"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:179
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:267
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:15
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:15
|
||||||
msgid "DNS over HTTPS (DoH)"
|
msgid "DNS over HTTPS (DoH)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:180
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:268
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:16
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:16
|
||||||
msgid "DNS over TLS (DoT)"
|
msgid "DNS over TLS (DoT)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:176
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:264
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:12
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:12
|
||||||
msgid "DNS Protocol Type"
|
msgid "DNS Protocol Type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -209,7 +215,7 @@ msgstr ""
|
|||||||
msgid "DNS Rewrite TTL"
|
msgid "DNS Rewrite TTL"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:189
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:277
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:24
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:24
|
||||||
msgid "DNS Server"
|
msgid "DNS Server"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -222,16 +228,16 @@ msgstr ""
|
|||||||
msgid "Do not panic, everything can be fixed, just..."
|
msgid "Do not panic, everything can be fixed, just..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:166
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:254
|
||||||
msgid "Domain Resolver"
|
msgid "Domain Resolver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:307
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:326
|
||||||
msgid "Dont Touch My DHCP!"
|
msgid "Dont Touch My DHCP!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:238
|
#: src/podkop/tabs/dashboard/initController.ts:241
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:272
|
#: src/podkop/tabs/dashboard/initController.ts:275
|
||||||
msgid "Downlink"
|
msgid "Downlink"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -239,24 +245,21 @@ msgstr ""
|
|||||||
msgid "Download"
|
msgid "Download"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:269
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:288
|
||||||
msgid "Download Lists via Proxy/VPN"
|
msgid "Download Lists via Proxy/VPN"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:278
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:297
|
||||||
msgid "Download Lists via specific proxy section"
|
msgid "Download Lists via specific proxy section"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:270
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:289
|
||||||
msgid "Downloading all lists via main Proxy/VPN"
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:298
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:279
|
|
||||||
msgid "Downloading all lists via specific Proxy/VPN"
|
msgid "Downloading all lists via specific Proxy/VPN"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:303
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:391
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:383
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:471
|
||||||
msgid "Dynamic List"
|
msgid "Dynamic List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -264,11 +267,15 @@ msgstr ""
|
|||||||
msgid "Enable autostart"
|
msgid "Enable autostart"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:167
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:255
|
||||||
msgid "Enable built-in DNS resolver for domains handled by this section"
|
msgid "Enable built-in DNS resolver for domains handled by this section"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:575
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:691
|
||||||
|
msgid "Enable DNS resolve to get real IP when routing"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:665
|
||||||
msgid "Enable Mixed Proxy"
|
msgid "Enable Mixed Proxy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -276,7 +283,7 @@ msgstr ""
|
|||||||
msgid "Enable Output Network Interface"
|
msgid "Enable Output Network Interface"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:576
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:666
|
||||||
msgid "Enable the mixed proxy, allowing this section to route traffic through both HTTP and SOCKS proxies"
|
msgid "Enable the mixed proxy, allowing this section to route traffic through both HTTP and SOCKS proxies"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -284,27 +291,47 @@ msgstr ""
|
|||||||
msgid "Enable YACD"
|
msgid "Enable YACD"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:65
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:246
|
||||||
|
msgid "Enable YACD WAN Access"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:66
|
||||||
msgid "Enter complete outbound configuration in JSON format"
|
msgid "Enter complete outbound configuration in JSON format"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:338
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:426
|
||||||
msgid "Enter domain names separated by commas, spaces, or newlines. You can add comments using //"
|
msgid "Enter domain names separated by commas, spaces, or newlines. You can add comments using //"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:312
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:400
|
||||||
msgid "Enter domain names without protocols, e.g. example.com or sub.example.com"
|
msgid "Enter domain names without protocols, e.g. example.com or sub.example.com"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:392
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:480
|
||||||
msgid "Enter subnets in CIDR notation (e.g. 103.21.244.0/22) or single IP addresses"
|
msgid "Enter subnets in CIDR notation (e.g. 103.21.244.0/22) or single IP addresses"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:365
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:138
|
||||||
|
msgid "Every 1 minute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:139
|
||||||
|
msgid "Every 3 minutes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:137
|
||||||
|
msgid "Every 30 seconds"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:140
|
||||||
|
msgid "Every 5 minutes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:402
|
||||||
msgid "Exclude NTP"
|
msgid "Exclude NTP"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:366
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:403
|
||||||
msgid "Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN"
|
msgid "Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -312,20 +339,21 @@ msgstr ""
|
|||||||
msgid "Failed to copy!"
|
msgid "Failed to copy!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:226
|
#: src/podkop/tabs/diagnostic/initController.ts:227
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:230
|
#: src/podkop/tabs/diagnostic/initController.ts:231
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:260
|
#: src/podkop/tabs/diagnostic/initController.ts:261
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:264
|
#: src/podkop/tabs/diagnostic/initController.ts:265
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:298
|
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:302
|
#: src/podkop/tabs/diagnostic/initController.ts:302
|
||||||
|
#: src/podkop/tabs/diagnostic/initController.ts:306
|
||||||
msgid "Failed to execute!"
|
msgid "Failed to execute!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/methods/custom/getDashboardSections.ts:117
|
#: src/podkop/methods/custom/getDashboardSections.ts:148
|
||||||
|
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:59
|
||||||
msgid "Fastest"
|
msgid "Fastest"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:550
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:638
|
||||||
msgid "Fully Routed IPs"
|
msgid "Fully Routed IPs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -333,7 +361,7 @@ msgstr ""
|
|||||||
msgid "Get global check"
|
msgid "Get global check"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:221
|
#: src/podkop/tabs/diagnostic/initController.ts:222
|
||||||
msgid "Global check"
|
msgid "Global check"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -366,11 +394,63 @@ msgstr ""
|
|||||||
msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y"
|
msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:90
|
||||||
|
msgid "Invalid HY2 URL: insecure must be 0 or 1"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:77
|
||||||
|
msgid "Invalid HY2 URL: invalid port number"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:30
|
||||||
|
msgid "Invalid HY2 URL: missing credentials/server"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:47
|
||||||
|
msgid "Invalid HY2 URL: missing host"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:41
|
||||||
|
msgid "Invalid HY2 URL: missing host & port"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:36
|
||||||
|
msgid "Invalid HY2 URL: missing password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:50
|
||||||
|
msgid "Invalid HY2 URL: missing port"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:18
|
||||||
|
msgid "Invalid HY2 URL: must not contain spaces"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:12
|
||||||
|
msgid "Invalid HY2 URL: must start with hysteria2:// or hy2://"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:108
|
||||||
|
msgid "Invalid HY2 URL: obfs-password required when obfs is set"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:122
|
||||||
|
msgid "Invalid HY2 URL: parsing failed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:116
|
||||||
|
msgid "Invalid HY2 URL: sni cannot be empty"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:98
|
||||||
|
msgid "Invalid HY2 URL: unsupported obfs type"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/validators/validateIp.ts:11
|
#: src/validators/validateIp.ts:11
|
||||||
msgid "Invalid IP address"
|
msgid "Invalid IP address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/validators/validateOutboundJson.ts:19
|
#: src/validators/validateOutboundJson.ts:9
|
||||||
msgid "Invalid JSON format"
|
msgid "Invalid JSON format"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -466,7 +546,8 @@ msgstr ""
|
|||||||
msgid "Invalid Trojan URL: parsing failed"
|
msgid "Invalid Trojan URL: parsing failed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/validators/validateUrl.ts:18
|
#: src/validators/validateUrl.ts:8
|
||||||
|
#: src/validators/validateUrl.ts:31
|
||||||
msgid "Invalid URL format"
|
msgid "Invalid URL format"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -482,31 +563,35 @@ msgstr ""
|
|||||||
msgid "Issues detected"
|
msgid "Issues detected"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:452
|
#: src/podkop/tabs/diagnostic/helpers/getPodkopVersionRow.ts:48
|
||||||
msgid "Latest"
|
msgid "Latest"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:257
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:276
|
||||||
msgid "List Update Frequency"
|
msgid "List Update Frequency"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:458
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:546
|
||||||
msgid "Local Domain Lists"
|
msgid "Local Domain Lists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:481
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:569
|
||||||
msgid "Local Subnet Lists"
|
msgid "Local Subnet Lists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:384
|
||||||
|
msgid "Log Level"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:72
|
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:72
|
||||||
msgid "Main DNS"
|
msgid "Main DNS"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:308
|
#: src/podkop/tabs/dashboard/initController.ts:311
|
||||||
msgid "Memory Usage"
|
msgid "Memory Usage"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:586
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:678
|
||||||
msgid "Mixed Proxy Port"
|
msgid "Mixed Proxy Port"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -514,7 +599,11 @@ msgstr ""
|
|||||||
msgid "Monitored Interfaces"
|
msgid "Monitored Interfaces"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:120
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:164
|
||||||
|
msgid "Must be a number in the range of 50 - 1000"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:208
|
||||||
msgid "Network Interface"
|
msgid "Network Interface"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -526,10 +615,17 @@ msgstr ""
|
|||||||
msgid "Not implement yet"
|
msgid "Not implement yet"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:75
|
||||||
|
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:81
|
||||||
|
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:100
|
||||||
|
msgid "Not responding"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:55
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:55
|
||||||
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:63
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:63
|
||||||
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:71
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:71
|
||||||
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:79
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:79
|
||||||
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:87
|
||||||
msgid "Not running"
|
msgid "Not running"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -537,19 +633,15 @@ msgstr ""
|
|||||||
msgid "Operation timed out"
|
msgid "Operation timed out"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:26
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:29
|
||||||
msgid "Outbound Config"
|
msgid "Outbound Config"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:64
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:65
|
||||||
msgid "Outbound Configuration"
|
msgid "Outbound Configuration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/validators/validateOutboundJson.ts:11
|
#: src/podkop/tabs/diagnostic/helpers/getPodkopVersionRow.ts:38
|
||||||
msgid "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:442
|
|
||||||
msgid "Outdated"
|
msgid "Outdated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -561,26 +653,27 @@ msgstr ""
|
|||||||
msgid "Path cannot be empty"
|
msgid "Path cannot be empty"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:347
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:366
|
||||||
msgid "Path must be absolute (start with /)"
|
msgid "Path must be absolute (start with /)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:356
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:375
|
||||||
msgid "Path must contain at least one directory (like /tmp/cache.db)"
|
msgid "Path must contain at least one directory (like /tmp/cache.db)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:351
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:370
|
||||||
msgid "Path must end with cache.db"
|
msgid "Path must end with cache.db"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:95
|
|
||||||
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:103
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:103
|
||||||
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:111
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:111
|
||||||
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:119
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:119
|
||||||
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:127
|
||||||
|
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:135
|
||||||
msgid "Pending"
|
msgid "Pending"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:340
|
#: src/podkop/tabs/dashboard/initController.ts:343
|
||||||
msgid "Podkop"
|
msgid "Podkop"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -588,11 +681,11 @@ msgstr ""
|
|||||||
msgid "Podkop Settings"
|
msgid "Podkop Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:308
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:327
|
||||||
msgid "Podkop will not modify your DHCP configuration"
|
msgid "Podkop will not modify your DHCP configuration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:34
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:36
|
||||||
msgid "Proxy Configuration URL"
|
msgid "Proxy Configuration URL"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -604,18 +697,22 @@ msgstr ""
|
|||||||
msgid "Proxy traffic is routed via FakeIP"
|
msgid "Proxy traffic is routed via FakeIP"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:245
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:333
|
||||||
msgid "Regional options cannot be used together"
|
msgid "Regional options cannot be used together"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:504
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:592
|
||||||
msgid "Remote Domain Lists"
|
msgid "Remote Domain Lists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:527
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:615
|
||||||
msgid "Remote Subnet Lists"
|
msgid "Remote Subnet Lists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:690
|
||||||
|
msgid "Resolve real IP for routing"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:49
|
#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:49
|
||||||
msgid "Restart podkop"
|
msgid "Restart podkop"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -628,7 +725,7 @@ msgstr ""
|
|||||||
msgid "Router DNS is routed through sing-box"
|
msgid "Router DNS is routed through sing-box"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:376
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:413
|
||||||
msgid "Routing Excluded IPs"
|
msgid "Routing Excluded IPs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -660,15 +757,19 @@ msgstr ""
|
|||||||
msgid "Run Diagnostic"
|
msgid "Run Diagnostic"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:264
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:352
|
||||||
msgid "Russia inside restrictions"
|
msgid "Russia inside restrictions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:257
|
||||||
|
msgid "Secret key for authenticating remote access to YACD when WAN access is enabled."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:36
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:36
|
||||||
msgid "Sections"
|
msgid "Sections"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:212
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:300
|
||||||
msgid "Select a predefined list for routing"
|
msgid "Select a predefined list for routing"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -680,43 +781,47 @@ msgstr ""
|
|||||||
msgid "Select DNS protocol to use"
|
msgid "Select DNS protocol to use"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:258
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:277
|
||||||
msgid "Select how often the domain or subnet lists are updated automatically"
|
msgid "Select how often the domain or subnet lists are updated automatically"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:23
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:24
|
||||||
msgid "Select how to configure the proxy"
|
msgid "Select how to configure the proxy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:121
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:209
|
||||||
msgid "Select network interface for VPN connection"
|
msgid "Select network interface for VPN connection"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:190
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:278
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:25
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:25
|
||||||
msgid "Select or enter DNS server address"
|
msgid "Select or enter DNS server address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:330
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:349
|
||||||
msgid "Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing"
|
msgid "Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:317
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:336
|
||||||
msgid "Select path for sing-box config file. Change this ONLY if you know what you are doing"
|
msgid "Select path for sing-box config file. Change this ONLY if you know what you are doing"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:177
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:265
|
||||||
msgid "Select the DNS protocol type for the domain resolver"
|
msgid "Select the DNS protocol type for the domain resolver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:300
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:388
|
||||||
msgid "Select the list type for adding custom domains"
|
msgid "Select the list type for adding custom domains"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:380
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:468
|
||||||
msgid "Select the list type for adding custom subnets"
|
msgid "Select the list type for adding custom subnets"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:385
|
||||||
|
msgid "Select the log level for sing-box"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:90
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:90
|
||||||
msgid "Select the network interface from which the traffic will originate"
|
msgid "Select the network interface from which the traffic will originate"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -729,7 +834,15 @@ msgstr ""
|
|||||||
msgid "Select the WAN interfaces to be monitored"
|
msgid "Select the WAN interfaces to be monitored"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:337
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:27
|
||||||
|
msgid "Selector"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:88
|
||||||
|
msgid "Selector Proxy Links"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/podkop/tabs/dashboard/initController.ts:340
|
||||||
msgid "Services info"
|
msgid "Services info"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -737,12 +850,12 @@ msgstr ""
|
|||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:289
|
#: src/podkop/tabs/diagnostic/initController.ts:290
|
||||||
#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:116
|
#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:116
|
||||||
msgid "Show sing-box config"
|
msgid "Show sing-box config"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:351
|
#: src/podkop/tabs/dashboard/initController.ts:354
|
||||||
msgid "Sing-box"
|
msgid "Sing-box"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -767,31 +880,31 @@ msgid "Sing-box service exist"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:67
|
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:67
|
||||||
msgid "Sing-box version >= 1.12.4"
|
msgid "Sing-box version is compatible (newer than 1.12.4)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:89
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:89
|
||||||
msgid "Source Network Interface"
|
msgid "Source Network Interface"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:377
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:414
|
||||||
msgid "Specify a local IP address to be excluded from routing"
|
msgid "Specify a local IP address to be excluded from routing"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:551
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:639
|
||||||
msgid "Specify local IP addresses or subnets whose traffic will always be routed through the configured route"
|
msgid "Specify local IP addresses or subnets whose traffic will always be routed through the configured route"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:505
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:593
|
||||||
msgid "Specify remote URLs to download and use domain lists"
|
msgid "Specify remote URLs to download and use domain lists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:528
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:616
|
||||||
msgid "Specify remote URLs to download and use subnet lists"
|
msgid "Specify remote URLs to download and use subnet lists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:459
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:547
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:482
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:570
|
||||||
msgid "Specify the path to the list file located on the router filesystem"
|
msgid "Specify the path to the list file located on the router filesystem"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -807,7 +920,7 @@ msgstr ""
|
|||||||
msgid "Successfully copied!"
|
msgid "Successfully copied!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:301
|
#: src/podkop/tabs/dashboard/initController.ts:304
|
||||||
msgid "System info"
|
msgid "System info"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -823,27 +936,36 @@ msgstr ""
|
|||||||
msgid "Test latency"
|
msgid "Test latency"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:304
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:392
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:472
|
||||||
msgid "Text List"
|
msgid "Text List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:384
|
|
||||||
msgid "Text List (comma/space/newline separated)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:46
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:46
|
||||||
msgid "The DNS server used to look up the IP address of an upstream DNS server"
|
msgid "The DNS server used to look up the IP address of an upstream DNS server"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:135
|
||||||
|
msgid "The interval between connectivity tests"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:148
|
||||||
|
msgid "The maximum difference in response times (ms) allowed when comparing servers"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:171
|
||||||
|
msgid "The URL used to test server connectivity"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:69
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:69
|
||||||
msgid "Time in seconds for DNS record caching (default: 60)"
|
msgid "Time in seconds for DNS record caching (default: 60)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:235
|
#: src/podkop/tabs/dashboard/initController.ts:238
|
||||||
msgid "Traffic"
|
msgid "Traffic"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:265
|
#: src/podkop/tabs/dashboard/initController.ts:268
|
||||||
msgid "Traffic Total"
|
msgid "Traffic Total"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -859,22 +981,22 @@ msgstr ""
|
|||||||
msgid "TTL value cannot be empty"
|
msgid "TTL value cannot be empty"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:181
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:269
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:17
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:17
|
||||||
msgid "UDP (Unprotected DNS)"
|
msgid "UDP (Unprotected DNS)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:110
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:198
|
||||||
msgid "UDP over TCP"
|
msgid "UDP over TCP"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:37
|
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:38
|
#: src/podkop/tabs/diagnostic/initController.ts:38
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:39
|
#: src/podkop/tabs/diagnostic/initController.ts:39
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:40
|
#: src/podkop/tabs/diagnostic/initController.ts:40
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:41
|
#: src/podkop/tabs/diagnostic/initController.ts:41
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:42
|
#: src/podkop/tabs/diagnostic/initController.ts:42
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:416
|
#: src/podkop/tabs/diagnostic/initController.ts:43
|
||||||
|
#: src/podkop/tabs/diagnostic/helpers/getPodkopVersionRow.ts:7
|
||||||
msgid "unknown"
|
msgid "unknown"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -882,48 +1004,60 @@ msgstr ""
|
|||||||
msgid "Unknown error"
|
msgid "Unknown error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:237
|
#: src/podkop/tabs/dashboard/initController.ts:240
|
||||||
#: src/podkop/tabs/dashboard/initController.ts:268
|
#: src/podkop/tabs/dashboard/initController.ts:271
|
||||||
msgid "Uplink"
|
msgid "Uplink"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/validators/validateProxyUrl.ts:29
|
#: src/validators/validateProxyUrl.ts:37
|
||||||
msgid "URL must start with vless://, ss://, trojan://, or socks4/5://"
|
msgid "URL must start with vless://, ss://, trojan://, socks4/5://, or hysteria2://hy2://"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/validators/validateUrl.ts:13
|
#: src/validators/validateUrl.ts:17
|
||||||
msgid "URL must use one of the following protocols:"
|
msgid "URL must use one of the following protocols:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:27
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:28
|
||||||
msgid "URLTest"
|
msgid "URLTest"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:87
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:134
|
||||||
|
msgid "URLTest Check Interval"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:111
|
||||||
msgid "URLTest Proxy Links"
|
msgid "URLTest Proxy Links"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:299
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:170
|
||||||
|
msgid "URLTest Testing URL"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:147
|
||||||
|
msgid "URLTest Tolerance"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:387
|
||||||
msgid "User Domain List Type"
|
msgid "User Domain List Type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:311
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:399
|
||||||
msgid "User Domains"
|
msgid "User Domains"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:337
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:425
|
||||||
msgid "User Domains List"
|
msgid "User Domains List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:379
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:467
|
||||||
msgid "User Subnet List Type"
|
msgid "User Subnet List Type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:391
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:479
|
||||||
msgid "User Subnets"
|
msgid "User Subnets"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:417
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:505
|
||||||
msgid "User Subnets List"
|
msgid "User Subnets List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -931,24 +1065,25 @@ msgstr ""
|
|||||||
#: src/validators/validateDns.ts:18
|
#: src/validators/validateDns.ts:18
|
||||||
#: src/validators/validateDomain.ts:13
|
#: src/validators/validateDomain.ts:13
|
||||||
#: src/validators/validateDomain.ts:30
|
#: src/validators/validateDomain.ts:30
|
||||||
|
#: src/validators/validateHysteriaUrl.ts:120
|
||||||
#: src/validators/validateIp.ts:8
|
#: src/validators/validateIp.ts:8
|
||||||
#: src/validators/validateOutboundJson.ts:17
|
#: src/validators/validateOutboundJson.ts:7
|
||||||
#: src/validators/validatePath.ts:16
|
#: src/validators/validatePath.ts:16
|
||||||
#: src/validators/validateShadowsocksUrl.ts:95
|
#: src/validators/validateShadowsocksUrl.ts:95
|
||||||
#: src/validators/validateSocksUrl.ts:80
|
#: src/validators/validateSocksUrl.ts:80
|
||||||
#: src/validators/validateSubnet.ts:38
|
#: src/validators/validateSubnet.ts:38
|
||||||
#: src/validators/validateTrojanUrl.ts:59
|
#: src/validators/validateTrojanUrl.ts:59
|
||||||
#: src/validators/validateUrl.ts:16
|
#: src/validators/validateUrl.ts:28
|
||||||
#: src/validators/validateVlessUrl.ts:108
|
#: src/validators/validateVlessUrl.ts:108
|
||||||
msgid "Valid"
|
msgid "Valid"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:370
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:458
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:449
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:537
|
||||||
msgid "Validation errors:"
|
msgid "Validation errors:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/podkop/tabs/diagnostic/initController.ts:255
|
#: src/podkop/tabs/diagnostic/initController.ts:256
|
||||||
#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:107
|
#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:107
|
||||||
msgid "View logs"
|
msgid "View logs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -957,14 +1092,24 @@ msgstr ""
|
|||||||
msgid "Visit Wiki"
|
msgid "Visit Wiki"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:247
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:37
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:89
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:112
|
||||||
|
msgid "vless://, ss://, trojan://, socks4/5://, hy2/hysteria2:// links"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:335
|
||||||
msgid "Warning: %s cannot be used together with %s. Previous selections have been removed."
|
msgid "Warning: %s cannot be used together with %s. Previous selections have been removed."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:266
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:354
|
||||||
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
|
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:256
|
||||||
|
msgid "YACD Secret Key"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:127
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:127
|
||||||
msgid "You can select Output Network Interface, by default autodetect"
|
msgid "You can select Output Network Interface, by default autodetect"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
config settings 'settings'
|
config settings 'settings'
|
||||||
option dns_type 'udp'
|
option dns_type 'udp'
|
||||||
option dns_server '8.8.8.8'
|
option dns_server '77.88.8.8'
|
||||||
option bootstrap_dns_server '77.88.8.8'
|
option bootstrap_dns_server '77.88.8.8'
|
||||||
option dns_rewrite_ttl '60'
|
option dns_rewrite_ttl '60'
|
||||||
list source_network_interfaces 'br-lan'
|
list source_network_interfaces 'br-lan'
|
||||||
@@ -16,6 +16,7 @@ config settings 'settings'
|
|||||||
option dont_touch_dhcp '0'
|
option dont_touch_dhcp '0'
|
||||||
option config_path '/etc/sing-box/config.json'
|
option config_path '/etc/sing-box/config.json'
|
||||||
option cache_path '/tmp/sing-box/cache.db'
|
option cache_path '/tmp/sing-box/cache.db'
|
||||||
|
option log_level 'warn'
|
||||||
option exclude_ntp '0'
|
option exclude_ntp '0'
|
||||||
option shutdown_correctly '0'
|
option shutdown_correctly '0'
|
||||||
#list routing_excluded_ips '192.168.1.3'
|
#list routing_excluded_ips '192.168.1.3'
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,7 @@ TMP_RULESET_FOLDER="$TMP_SING_BOX_FOLDER/rulesets"
|
|||||||
CLOUDFLARE_OCTETS="8.47 162.159 188.114" # Endpoints https://github.com/ampetelin/warp-endpoint-checker
|
CLOUDFLARE_OCTETS="8.47 162.159 188.114" # Endpoints https://github.com/ampetelin/warp-endpoint-checker
|
||||||
JQ_REQUIRED_VERSION="1.7.1"
|
JQ_REQUIRED_VERSION="1.7.1"
|
||||||
COREUTILS_BASE64_REQUIRED_VERSION="9.7"
|
COREUTILS_BASE64_REQUIRED_VERSION="9.7"
|
||||||
|
RT_TABLE_NAME="podkop"
|
||||||
|
|
||||||
## nft
|
## nft
|
||||||
NFT_TABLE_NAME="PodkopTable"
|
NFT_TABLE_NAME="PodkopTable"
|
||||||
@@ -19,11 +20,11 @@ NFT_LOCALV4_SET_NAME="localv4"
|
|||||||
NFT_COMMON_SET_NAME="podkop_subnets"
|
NFT_COMMON_SET_NAME="podkop_subnets"
|
||||||
NFT_DISCORD_SET_NAME="podkop_discord_subnets"
|
NFT_DISCORD_SET_NAME="podkop_discord_subnets"
|
||||||
NFT_INTERFACE_SET_NAME="interfaces"
|
NFT_INTERFACE_SET_NAME="interfaces"
|
||||||
|
NFT_FAKEIP_MARK="0x00100000"
|
||||||
|
NFT_OUTBOUND_MARK="0x00200000"
|
||||||
|
|
||||||
## sing-box
|
## sing-box
|
||||||
SB_REQUIRED_VERSION="1.12.0"
|
SB_REQUIRED_VERSION="1.12.0"
|
||||||
# Log
|
|
||||||
SB_DEFAULT_LOG_LEVEL="warn"
|
|
||||||
# DNS
|
# DNS
|
||||||
SB_DNS_SERVER_TAG="dns-server"
|
SB_DNS_SERVER_TAG="dns-server"
|
||||||
SB_FAKEIP_DNS_SERVER_TAG="fakeip-server"
|
SB_FAKEIP_DNS_SERVER_TAG="fakeip-server"
|
||||||
@@ -38,7 +39,6 @@ SB_TPROXY_INBOUND_PORT=1602
|
|||||||
SB_DNS_INBOUND_TAG="dns-in"
|
SB_DNS_INBOUND_TAG="dns-in"
|
||||||
SB_DNS_INBOUND_ADDRESS="127.0.0.42"
|
SB_DNS_INBOUND_ADDRESS="127.0.0.42"
|
||||||
SB_DNS_INBOUND_PORT=53
|
SB_DNS_INBOUND_PORT=53
|
||||||
SB_MIXED_INBOUND_ADDRESS="0.0.0.0" # TODO(ampetelin): maybe to determine address?
|
|
||||||
SB_SERVICE_MIXED_INBOUND_TAG="service-mixed-in"
|
SB_SERVICE_MIXED_INBOUND_TAG="service-mixed-in"
|
||||||
SB_SERVICE_MIXED_INBOUND_ADDRESS="127.0.0.1"
|
SB_SERVICE_MIXED_INBOUND_ADDRESS="127.0.0.1"
|
||||||
SB_SERVICE_MIXED_INBOUND_PORT=4534
|
SB_SERVICE_MIXED_INBOUND_PORT=4534
|
||||||
@@ -46,23 +46,21 @@ SB_SERVICE_MIXED_INBOUND_PORT=4534
|
|||||||
SB_DIRECT_OUTBOUND_TAG="direct-out"
|
SB_DIRECT_OUTBOUND_TAG="direct-out"
|
||||||
# Route
|
# Route
|
||||||
SB_REJECT_RULE_TAG="reject-rule-tag"
|
SB_REJECT_RULE_TAG="reject-rule-tag"
|
||||||
|
SB_EXCLUSION_RULE_TAG="exclusion-rule-tag"
|
||||||
# Experimental
|
# Experimental
|
||||||
SB_CLASH_API_CONTROLLER="0.0.0.0:9090"
|
SB_CLASH_API_CONTROLLER_PORT=9090
|
||||||
|
|
||||||
## Lists
|
## Lists
|
||||||
GITHUB_RAW_URL="https://raw.githubusercontent.com/itdoginfo/allow-domains/main"
|
GITHUB_RAW_URL="https://raw.githubusercontent.com/itdoginfo/allow-domains/main"
|
||||||
SRS_MAIN_URL="https://github.com/itdoginfo/allow-domains/releases/latest/download"
|
SRS_MAIN_URL="https://github.com/itdoginfo/allow-domains/releases/latest/download"
|
||||||
DOMAINS_RU_INSIDE="${GITHUB_RAW_URL}/Russia/inside-dnsmasq-nfset.lst"
|
|
||||||
DOMAINS_RU_OUTSIDE="${GITHUB_RAW_URL}/Russia/outside-dnsmasq-nfset.lst"
|
|
||||||
DOMAINS_UA="${GITHUB_RAW_URL}/Ukraine/inside-dnsmasq-nfset.lst"
|
|
||||||
DOMAINS_YOUTUBE="${GITHUB_RAW_URL}/Services/youtube.lst"
|
|
||||||
SUBNETS_TWITTER="${GITHUB_RAW_URL}/Subnets/IPv4/twitter.lst"
|
SUBNETS_TWITTER="${GITHUB_RAW_URL}/Subnets/IPv4/twitter.lst"
|
||||||
SUBNETS_META="${GITHUB_RAW_URL}/Subnets/IPv4/meta.lst"
|
SUBNETS_META="${GITHUB_RAW_URL}/Subnets/IPv4/meta.lst"
|
||||||
SUBNETS_DISCORD="${GITHUB_RAW_URL}/Subnets/IPv4/discord.lst"
|
SUBNETS_DISCORD="${GITHUB_RAW_URL}/Subnets/IPv4/discord.lst"
|
||||||
|
SUBNETS_ROBLOX="${GITHUB_RAW_URL}/Subnets/IPv4/roblox.lst"
|
||||||
SUBNETS_TELERAM="${GITHUB_RAW_URL}/Subnets/IPv4/telegram.lst"
|
SUBNETS_TELERAM="${GITHUB_RAW_URL}/Subnets/IPv4/telegram.lst"
|
||||||
SUBNETS_CLOUDFLARE="${GITHUB_RAW_URL}/Subnets/IPv4/cloudflare.lst"
|
SUBNETS_CLOUDFLARE="${GITHUB_RAW_URL}/Subnets/IPv4/cloudflare.lst"
|
||||||
SUBNETS_HETZNER="${GITHUB_RAW_URL}/Subnets/IPv4/hetzner.lst"
|
SUBNETS_HETZNER="${GITHUB_RAW_URL}/Subnets/IPv4/hetzner.lst"
|
||||||
SUBNETS_OVH="${GITHUB_RAW_URL}/Subnets/IPv4/ovh.lst"
|
SUBNETS_OVH="${GITHUB_RAW_URL}/Subnets/IPv4/ovh.lst"
|
||||||
SUBNETS_DIGITALOCEAN="${GITHUB_RAW_URL}/Subnets/IPv4/digitalocean.lst"
|
SUBNETS_DIGITALOCEAN="${GITHUB_RAW_URL}/Subnets/IPv4/digitalocean.lst"
|
||||||
SUBNETS_CLOUDFRONT="${GITHUB_RAW_URL}/Subnets/IPv4/cloudfront.lst"
|
SUBNETS_CLOUDFRONT="${GITHUB_RAW_URL}/Subnets/IPv4/cloudfront.lst"
|
||||||
COMMUNITY_SERVICES="russia_inside russia_outside ukraine_inside geoblock block porn news anime youtube hdrezka tiktok google_ai google_play hodca discord meta twitter cloudflare cloudfront digitalocean hetzner ovh telegram"
|
COMMUNITY_SERVICES="russia_inside russia_outside ukraine_inside geoblock block porn news anime youtube hdrezka tiktok google_ai google_play hodca discord meta twitter cloudflare cloudfront digitalocean hetzner ovh telegram roblox"
|
||||||
@@ -105,37 +105,6 @@ get_domain_resolver_tag() {
|
|||||||
echo "$section-$postfix"
|
echo "$section-$postfix"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Constructs and returns a ruleset tag using section, name, optional type, and a fixed postfix
|
|
||||||
get_ruleset_tag() {
|
|
||||||
local section="$1"
|
|
||||||
local name="$2"
|
|
||||||
local type="$3"
|
|
||||||
local postfix="ruleset"
|
|
||||||
|
|
||||||
if [ -n "$type" ]; then
|
|
||||||
echo "$section-$name-$type-$postfix"
|
|
||||||
else
|
|
||||||
echo "$section-$name-$postfix"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Determines the ruleset format based on the file extension (json → source, srs → binary)
|
|
||||||
get_ruleset_format_by_file_extension() {
|
|
||||||
local file_extension="$1"
|
|
||||||
|
|
||||||
local format
|
|
||||||
case "$file_extension" in
|
|
||||||
json) format="source" ;;
|
|
||||||
srs) format="binary" ;;
|
|
||||||
*)
|
|
||||||
log "Unsupported file extension: .$file_extension" "error"
|
|
||||||
return 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo "$format"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Converts a comma-separated string into a JSON array string
|
# Converts a comma-separated string into a JSON array string
|
||||||
comma_string_to_json_array() {
|
comma_string_to_json_array() {
|
||||||
local input="$1"
|
local input="$1"
|
||||||
@@ -156,6 +125,12 @@ url_decode() {
|
|||||||
printf '%b' "$(echo "$encoded" | sed 's/+/ /g; s/%/\\x/g')"
|
printf '%b' "$(echo "$encoded" | sed 's/+/ /g; s/%/\\x/g')"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Returns the scheme (protocol) part of a URL
|
||||||
|
url_get_scheme() {
|
||||||
|
local url="$1"
|
||||||
|
echo "${url%%://*}"
|
||||||
|
}
|
||||||
|
|
||||||
# Extracts the userinfo (username[:password]) part from a URL
|
# Extracts the userinfo (username[:password]) part from a URL
|
||||||
url_get_userinfo() {
|
url_get_userinfo() {
|
||||||
local url="$1"
|
local url="$1"
|
||||||
@@ -165,13 +140,23 @@ url_get_userinfo() {
|
|||||||
# Extracts the host part from a URL
|
# Extracts the host part from a URL
|
||||||
url_get_host() {
|
url_get_host() {
|
||||||
local url="$1"
|
local url="$1"
|
||||||
echo "$url" | sed -n -e 's#^[^:/?]*://##' -e 's#^[^/]*@##' -e 's#\([:/].*\|$\)##p'
|
|
||||||
|
url="${url#*://}"
|
||||||
|
url="${url#*@}"
|
||||||
|
url="${url%%[/?#]*}"
|
||||||
|
|
||||||
|
echo "${url%%:*}"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Extracts the port number from a URL
|
# Extracts the port number from a URL
|
||||||
url_get_port() {
|
url_get_port() {
|
||||||
local url="$1"
|
local url="$1"
|
||||||
echo "$url" | sed -n -e 's#^[^:/?]*://##' -e 's#^[^/]*@##' -e 's#^[^/]*:\([0-9][0-9]*\).*#\1#p'
|
|
||||||
|
url="${url#*://}"
|
||||||
|
url="${url#*@}"
|
||||||
|
url="${url%%[/?#]*}"
|
||||||
|
|
||||||
|
[[ "$url" == *:* ]] && echo "${url#*:}" || echo ""
|
||||||
}
|
}
|
||||||
|
|
||||||
# Extracts the path from a URL (without query or fragment; returns "/" if empty)
|
# Extracts the path from a URL (without query or fragment; returns "/" if empty)
|
||||||
@@ -268,25 +253,6 @@ migration_rename_config_key() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Download URL content directly
|
|
||||||
download_to_stream() {
|
|
||||||
local url="$1"
|
|
||||||
local http_proxy_address="$2"
|
|
||||||
local retries="${3:-3}"
|
|
||||||
local wait="${4:-2}"
|
|
||||||
|
|
||||||
for attempt in $(seq 1 "$retries"); do
|
|
||||||
if [ -n "$http_proxy_address" ]; then
|
|
||||||
http_proxy="http://$http_proxy_address" https_proxy="http://$http_proxy_address" wget -qO- "$url" | sed 's/\r$//' && break
|
|
||||||
else
|
|
||||||
wget -qO- "$url" | sed 's/\r$//' && break
|
|
||||||
fi
|
|
||||||
|
|
||||||
log "Attempt $attempt/$retries to download $url failed" "warn"
|
|
||||||
sleep "$wait"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# Download URL to file
|
# Download URL to file
|
||||||
download_to_file() {
|
download_to_file() {
|
||||||
local url="$1"
|
local url="$1"
|
||||||
@@ -305,29 +271,17 @@ download_to_file() {
|
|||||||
log "Attempt $attempt/$retries to download $url failed" "warn"
|
log "Attempt $attempt/$retries to download $url failed" "warn"
|
||||||
sleep "$wait"
|
sleep "$wait"
|
||||||
done
|
done
|
||||||
|
|
||||||
if grep -q $'\r' "$filepath"; then
|
|
||||||
log "Downloaded file has Windows line endings (CRLF). Converting to Unix (LF)"
|
|
||||||
sed -i 's/\r$//' "$filepath"
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Decompiles a sing-box SRS binary file into a JSON ruleset file
|
# Converts Windows-style line endings (CRLF) to Unix-style (LF)
|
||||||
decompile_srs_file() {
|
convert_crlf_to_lf() {
|
||||||
local binary_filepath="$1"
|
local filepath="$1"
|
||||||
local output_filepath="$2"
|
|
||||||
|
|
||||||
log "Decompiling $binary_filepath to $output_filepath" "debug"
|
if grep -q $'\r' "$filepath"; then
|
||||||
|
log "File '$filepath' contains CRLF line endings. Converting to LF..." "debug"
|
||||||
if ! file_exists "$binary_filepath"; then
|
local tmpfile
|
||||||
log "File $binary_filepath not found" "error"
|
tmpfile=$(mktemp)
|
||||||
return 1
|
tr -d '\r' < "$filepath" > "$tmpfile" && mv "$tmpfile" "$filepath" || rm -f "$tmpfile"
|
||||||
fi
|
|
||||||
|
|
||||||
sing-box rule-set decompile "$binary_filepath" -o "$output_filepath"
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
log "Decompilation command failed for $binary_filepath" "error"
|
|
||||||
return 1
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,4 +353,4 @@ parse_domain_or_subnet_file_to_comma_string() {
|
|||||||
done < "$filepath"
|
done < "$filepath"
|
||||||
|
|
||||||
echo "$result"
|
echo "$result"
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,9 @@ nolog() {
|
|||||||
local timestamp
|
local timestamp
|
||||||
timestamp=$(date +"%Y-%m-%d %H:%M:%S")
|
timestamp=$(date +"%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
echo -e "${COLOR_CYAN}[$timestamp]${COLOR_RESET} ${COLOR_GREEN}$message${COLOR_RESET}"
|
if [ -t 1 ]; then
|
||||||
|
echo -e "${COLOR_CYAN}[$timestamp]${COLOR_RESET} ${COLOR_GREEN}$message${COLOR_RESET}"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
echolog() {
|
echolog() {
|
||||||
|
|||||||
@@ -27,4 +27,44 @@ nft_add_set_elements() {
|
|||||||
local elements="$3"
|
local elements="$3"
|
||||||
|
|
||||||
nft add element inet "$table" "$set" "{ $elements }"
|
nft add element inet "$table" "$set" "{ $elements }"
|
||||||
|
}
|
||||||
|
|
||||||
|
nft_add_set_elements_from_file_chunked() {
|
||||||
|
local filepath="$1"
|
||||||
|
local nft_table_name="$2"
|
||||||
|
local nft_set_name="$3"
|
||||||
|
local chunk_size="${4:-5000}"
|
||||||
|
|
||||||
|
local array count
|
||||||
|
count=0
|
||||||
|
while IFS= read -r line; do
|
||||||
|
line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||||
|
|
||||||
|
[ -z "$line" ] && continue
|
||||||
|
|
||||||
|
if ! is_ipv4 "$line" && ! is_ipv4_cidr "$line"; then
|
||||||
|
log "'$line' is not IPv4 or IPv4 CIDR" "debug"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$array" ]; then
|
||||||
|
array="$line"
|
||||||
|
else
|
||||||
|
array="$array,$line"
|
||||||
|
fi
|
||||||
|
|
||||||
|
count=$((count + 1))
|
||||||
|
|
||||||
|
if [ "$count" = "$chunk_size" ]; then
|
||||||
|
log "Adding $count elements to nft set $nft_set_name" "debug"
|
||||||
|
nft_add_set_elements "$nft_table_name" "$nft_set_name" "$array"
|
||||||
|
array=""
|
||||||
|
count=0
|
||||||
|
fi
|
||||||
|
done < "$filepath"
|
||||||
|
|
||||||
|
if [ -n "$array" ]; then
|
||||||
|
log "Adding $count elements to nft set $nft_set_name" "debug"
|
||||||
|
nft_add_set_elements "$nft_table_name" "$nft_set_name" "$array"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
180
podkop/files/usr/lib/rulesets.sh
Normal file
180
podkop/files/usr/lib/rulesets.sh
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
# Constructs and returns a ruleset tag using section, name, optional type, and a fixed postfix
|
||||||
|
get_ruleset_tag() {
|
||||||
|
local section="$1"
|
||||||
|
local name="$2"
|
||||||
|
local type="$3"
|
||||||
|
local postfix="ruleset"
|
||||||
|
|
||||||
|
if [ -n "$type" ]; then
|
||||||
|
echo "$section-$name-$type-$postfix"
|
||||||
|
else
|
||||||
|
echo "$section-$name-$postfix"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Creates a new ruleset JSON file if it doesn't already exist
|
||||||
|
create_source_rule_set() {
|
||||||
|
local ruleset_filepath="$1"
|
||||||
|
|
||||||
|
if file_exists "$ruleset_filepath"; then
|
||||||
|
return 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
jq -n '{version: 3, rules: []}' > "$ruleset_filepath"
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Patch a source ruleset JSON file for sing-box by appending a new ruleset object containing the provided key
|
||||||
|
# and value.
|
||||||
|
# Arguments:
|
||||||
|
# filepath: path to the JSON file to patch
|
||||||
|
# key: the ruleset key to insert (e.g., "ip_cidr")
|
||||||
|
# value: a JSON array of values to assign to the key
|
||||||
|
# Example:
|
||||||
|
# patch_source_ruleset_rules "/tmp/sing-box/ruleset.json" "ip_cidr" '["1.1.1.1","2.2.2.2"]'
|
||||||
|
#######################################
|
||||||
|
patch_source_ruleset_rules() {
|
||||||
|
local filepath="$1"
|
||||||
|
local key="$2"
|
||||||
|
local value="$3"
|
||||||
|
|
||||||
|
local tmpfile=$(mktemp)
|
||||||
|
|
||||||
|
jq --arg key "$key" --argjson value "$value" \
|
||||||
|
'( .rules | map(has($key)) | index(true) ) as $idx |
|
||||||
|
if $idx != null then
|
||||||
|
.rules[$idx][$key] = (.rules[$idx][$key] + $value | unique)
|
||||||
|
else
|
||||||
|
.rules += [{ ($key): $value }]
|
||||||
|
end' "$filepath" > "$tmpfile"
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
rm -f "$tmpfile"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mv "$tmpfile" "$filepath"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Imports a plain domain list into a ruleset in chunks, validating domains and appending them as domain_suffix rules
|
||||||
|
import_plain_domain_list_to_local_source_ruleset_chunked() {
|
||||||
|
local plain_list_filepath="$1"
|
||||||
|
local ruleset_filepath="$2"
|
||||||
|
local chunk_size="${3:-5000}"
|
||||||
|
|
||||||
|
local array count json_array
|
||||||
|
count=0
|
||||||
|
while IFS= read -r line; do
|
||||||
|
line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||||
|
|
||||||
|
[ -z "$line" ] && continue
|
||||||
|
|
||||||
|
if ! is_domain_suffix "$line"; then
|
||||||
|
log "'$line' is not a valid domain" "debug"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$array" ]; then
|
||||||
|
array="$line"
|
||||||
|
else
|
||||||
|
array="$array,$line"
|
||||||
|
fi
|
||||||
|
|
||||||
|
count=$((count + 1))
|
||||||
|
|
||||||
|
if [ "$count" = "$chunk_size" ]; then
|
||||||
|
log "Adding $count elements to rule set at $ruleset_filepath" "debug"
|
||||||
|
json_array="$(comma_string_to_json_array "$array")"
|
||||||
|
patch_source_ruleset_rules "$ruleset_filepath" "domain_suffix" "$json_array"
|
||||||
|
array=""
|
||||||
|
count=0
|
||||||
|
fi
|
||||||
|
done < "$plain_list_filepath"
|
||||||
|
|
||||||
|
if [ -n "$array" ]; then
|
||||||
|
log "Adding $count elements to rule set at $ruleset_filepath" "debug"
|
||||||
|
json_array="$(comma_string_to_json_array "$array")"
|
||||||
|
patch_source_ruleset_rules "$ruleset_filepath" "domain_suffix" "$json_array"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Imports a plain IPv4/CIDR list into a ruleset in chunks, validating entries and appending them as ip_cidr rules
|
||||||
|
import_plain_subnet_list_to_local_source_ruleset_chunked() {
|
||||||
|
local plain_list_filepath="$1"
|
||||||
|
local ruleset_filepath="$2"
|
||||||
|
local chunk_size="${3:-5000}"
|
||||||
|
|
||||||
|
local array count json_array
|
||||||
|
count=0
|
||||||
|
while IFS= read -r line; do
|
||||||
|
line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||||
|
|
||||||
|
[ -z "$line" ] && continue
|
||||||
|
|
||||||
|
if ! is_ipv4 "$line" && ! is_ipv4_cidr "$line"; then
|
||||||
|
log "'$line' is not IPv4 or IPv4 CIDR" "debug"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$array" ]; then
|
||||||
|
array="$line"
|
||||||
|
else
|
||||||
|
array="$array,$line"
|
||||||
|
fi
|
||||||
|
|
||||||
|
count=$((count + 1))
|
||||||
|
|
||||||
|
if [ "$count" = "$chunk_size" ]; then
|
||||||
|
log "Adding $count elements to ruleset at $ruleset_filepath" "debug"
|
||||||
|
json_array="$(comma_string_to_json_array "$array")"
|
||||||
|
patch_source_ruleset_rules "$ruleset_filepath" "ip_cidr" "$json_array"
|
||||||
|
array=""
|
||||||
|
count=0
|
||||||
|
fi
|
||||||
|
done < "$plain_list_filepath"
|
||||||
|
|
||||||
|
if [ -n "$array" ]; then
|
||||||
|
log "Adding $count elements to ruleset at $ruleset_filepath" "debug"
|
||||||
|
json_array="$(comma_string_to_json_array "$array")"
|
||||||
|
patch_source_ruleset_rules "$ruleset_filepath" "ip_cidr" "$json_array"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Determines the ruleset format based on the file extension (json → source, srs → binary)
|
||||||
|
get_ruleset_format_by_file_extension() {
|
||||||
|
local file_extension="$1"
|
||||||
|
|
||||||
|
local format
|
||||||
|
case "$file_extension" in
|
||||||
|
json) format="source" ;;
|
||||||
|
srs) format="binary" ;;
|
||||||
|
*)
|
||||||
|
log "Unsupported file extension: .$file_extension" "error"
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "$format"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Decompiles a sing-box SRS binary file into a JSON ruleset file
|
||||||
|
decompile_binary_ruleset() {
|
||||||
|
local binary_filepath="$1"
|
||||||
|
local output_filepath="$2"
|
||||||
|
|
||||||
|
log "Decompiling $binary_filepath to $output_filepath" "debug"
|
||||||
|
sing-box rule-set decompile "$binary_filepath" -o "$output_filepath"
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
log "Decompilation command failed for $binary_filepath" "error"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Extracts all ip_cidr entries from a JSON ruleset file and writes them to an output file.
|
||||||
|
extract_ip_cidr_from_json_ruleset_to_file() {
|
||||||
|
local json_file="$1"
|
||||||
|
local output_file="$2"
|
||||||
|
|
||||||
|
log "Extracting ip_cidr entries from $json_file to $output_file" "debug"
|
||||||
|
jq -r '.rules[].ip_cidr[]' "$json_file" > "$output_file"
|
||||||
|
}
|
||||||
@@ -64,7 +64,8 @@ sing_box_cf_add_proxy_outbound() {
|
|||||||
url=$(url_decode "$url")
|
url=$(url_decode "$url")
|
||||||
url=$(url_strip_fragment "$url")
|
url=$(url_strip_fragment "$url")
|
||||||
|
|
||||||
local scheme="${url%%://*}"
|
local scheme
|
||||||
|
scheme="$(url_get_scheme "$url")"
|
||||||
case "$scheme" in
|
case "$scheme" in
|
||||||
socks4 | socks4a | socks5)
|
socks4 | socks4a | socks5)
|
||||||
local tag host port version userinfo username password udp_over_tcp
|
local tag host port version userinfo username password udp_over_tcp
|
||||||
@@ -146,6 +147,21 @@ sing_box_cf_add_proxy_outbound() {
|
|||||||
config=$(_add_outbound_security "$config" "$tag" "$url")
|
config=$(_add_outbound_security "$config" "$tag" "$url")
|
||||||
config=$(_add_outbound_transport "$config" "$tag" "$url")
|
config=$(_add_outbound_transport "$config" "$tag" "$url")
|
||||||
;;
|
;;
|
||||||
|
hysteria2 | hy2)
|
||||||
|
local tag host port password obfuscator_type obfuscator_password upload_mbps download_mbps
|
||||||
|
tag=$(get_outbound_tag_by_section "$section")
|
||||||
|
host=$(url_get_host "$url")
|
||||||
|
port="$(url_get_port "$url")"
|
||||||
|
password=$(url_get_userinfo "$url")
|
||||||
|
obfuscator_type=$(url_get_query_param "$url" "obfs")
|
||||||
|
obfuscator_password=$(url_get_query_param "$url" "obfs-password")
|
||||||
|
upload_mbps=$(url_get_query_param "$url" "upmbps")
|
||||||
|
download_mbps=$(url_get_query_param "$url" "downmbps")
|
||||||
|
|
||||||
|
config=$(sing_box_cm_add_hysteria2_outbound "$config" "$tag" "$host" "$port" "$password" "$obfuscator_type" \
|
||||||
|
"$obfuscator_password" "$upload_mbps" "$download_mbps")
|
||||||
|
config=$(_add_outbound_security "$config" "$tag" "$url")
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
log "Unsupported proxy $scheme type. Aborted." "fatal"
|
log "Unsupported proxy $scheme type. Aborted." "fatal"
|
||||||
exit 1
|
exit 1
|
||||||
@@ -160,18 +176,30 @@ _add_outbound_security() {
|
|||||||
local outbound_tag="$2"
|
local outbound_tag="$2"
|
||||||
local url="$3"
|
local url="$3"
|
||||||
|
|
||||||
local security
|
local security scheme
|
||||||
security=$(url_get_query_param "$url" "security")
|
security=$(url_get_query_param "$url" "security")
|
||||||
|
scheme="$(url_get_scheme "$url")"
|
||||||
|
|
||||||
|
if [ -z "$security" ]; then
|
||||||
|
if [ "$scheme" = "hysteria2" ] || [ "$scheme" = "hy2" ]; then
|
||||||
|
security="tls"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
case "$security" in
|
case "$security" in
|
||||||
tls | reality)
|
tls | reality)
|
||||||
local sni insecure alpn fingerprint public_key short_id
|
local sni insecure alpn fingerprint public_key short_id
|
||||||
sni=$(url_get_query_param "$url" "sni")
|
sni=$(url_get_query_param "$url" "sni")
|
||||||
insecure=$(url_get_query_param "$url" "allowInsecure")
|
insecure=$(_get_insecure_query_param_from_url "$url")
|
||||||
alpn=$(comma_string_to_json_array "$(url_get_query_param "$url" "alpn")")
|
alpn=$(comma_string_to_json_array "$(url_get_query_param "$url" "alpn")")
|
||||||
fingerprint=$(url_get_query_param "$url" "fp")
|
fingerprint=$(url_get_query_param "$url" "fp")
|
||||||
public_key=$(url_get_query_param "$url" "pbk")
|
public_key=$(url_get_query_param "$url" "pbk")
|
||||||
short_id=$(url_get_query_param "$url" "sid")
|
short_id=$(url_get_query_param "$url" "sid")
|
||||||
|
|
||||||
|
if [ "$scheme" = "hysteria2" ] || [ "$scheme" = "hy2" ]; then
|
||||||
|
fingerprint=""
|
||||||
|
fi
|
||||||
|
|
||||||
config=$(
|
config=$(
|
||||||
sing_box_cm_set_tls_for_outbound \
|
sing_box_cm_set_tls_for_outbound \
|
||||||
"$config" \
|
"$config" \
|
||||||
@@ -193,6 +221,18 @@ _add_outbound_security() {
|
|||||||
echo "$config"
|
echo "$config"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_get_insecure_query_param_from_url() {
|
||||||
|
local url="$1"
|
||||||
|
|
||||||
|
local insecure
|
||||||
|
insecure=$(url_get_query_param "$url" "allowInsecure")
|
||||||
|
if [ -z "$insecure" ]; then
|
||||||
|
insecure=$(url_get_query_param "$url" "insecure")
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$insecure"
|
||||||
|
}
|
||||||
|
|
||||||
_add_outbound_transport() {
|
_add_outbound_transport() {
|
||||||
local config="$1"
|
local config="$1"
|
||||||
local outbound_tag="$2"
|
local outbound_tag="$2"
|
||||||
@@ -214,7 +254,12 @@ _add_outbound_transport() {
|
|||||||
;;
|
;;
|
||||||
grpc)
|
grpc)
|
||||||
# TODO(ampetelin): Add handling of optional gRPC parameters; example links are needed.
|
# TODO(ampetelin): Add handling of optional gRPC parameters; example links are needed.
|
||||||
config=$(sing_box_cm_set_grpc_transport_for_outbound "$config" "$outbound_tag")
|
local grpc_service_name
|
||||||
|
grpc_service_name=$(url_get_query_param "$url" "serviceName")
|
||||||
|
|
||||||
|
config=$(
|
||||||
|
sing_box_cm_set_grpc_transport_for_outbound "$config" "$outbound_tag" "$grpc_service_name"
|
||||||
|
)
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
log "Unknown transport '$transport' detected." "error"
|
log "Unknown transport '$transport' detected." "error"
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ SERVICE_TAG="__service_tag"
|
|||||||
#######################################
|
#######################################
|
||||||
# Configure the logging section of a sing-box JSON configuration.
|
# Configure the logging section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string, JSON configuration
|
||||||
# disabled: boolean, true to disable logging
|
# disabled: boolean, true to disable logging
|
||||||
# level: string, e.g., "info", "debug", "warn"
|
# level: string, log level. One of: trace debug info warn error fatal panic.
|
||||||
# timestamp: boolean, true to include timestamps
|
# timestamp: boolean, true to include timestamps
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
@@ -50,7 +50,7 @@ sing_box_cm_configure_log() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Configure the DNS section of a sing-box JSON configuration.
|
# Configure the DNS section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# final: string, default dns server tag
|
# final: string, default dns server tag
|
||||||
# strategy: string, default domain strategy for resolving the domain names
|
# strategy: string, default domain strategy for resolving the domain names
|
||||||
# independent_cache: boolean, whether to use an independent DNS cache
|
# independent_cache: boolean, whether to use an independent DNS cache
|
||||||
@@ -82,12 +82,12 @@ sing_box_cm_configure_dns() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a UDP DNS server to the DNS section of a sing-box JSON configuration.
|
# Add a UDP DNS server to the DNS section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the DNS server
|
# tag: string, identifier for the DNS server
|
||||||
# server_address: string, IP address or hostname of the DNS server
|
# server_address: string, IP address or hostname of the DNS server
|
||||||
# server_port: string or number, port of the DNS server
|
# server_port: string or integer, port of the DNS server
|
||||||
# domain_resolver: string, domain resolver to use for resolving domain names
|
# domain_resolver: string, domain resolver to use for resolving domain names (optional)
|
||||||
# detour: string, tag of the upstream outbound
|
# detour: string, tag of the upstream outbound (optional)
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -122,12 +122,12 @@ sing_box_cm_add_udp_dns_server() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a TLS DNS server to the DNS section of a sing-box JSON configuration.
|
# Add a TLS DNS server to the DNS section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the DNS server
|
# tag: string, identifier for the DNS server
|
||||||
# server_address: string, IP address or hostname of the DNS server
|
# server_address: string, IP address or hostname of the DNS server
|
||||||
# server_port: string or number, port of the DNS server
|
# server_port: string or integer, port of the DNS server
|
||||||
# domain_resolver: string, domain resolver to use for resolving domain names
|
# domain_resolver: string, domain resolver to use for resolving domain names (optional)
|
||||||
# detour: string, tag of the upstream outbound
|
# detour: string, tag of the upstream outbound (optional)
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -162,14 +162,14 @@ sing_box_cm_add_tls_dns_server() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add an HTTPS DNS server to the DNS section of a sing-box JSON configuration.
|
# Add an HTTPS DNS server to the DNS section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the DNS server
|
# tag: string, identifier for the DNS server
|
||||||
# server_address: string, IP address or hostname of the DNS server
|
# server_address: string, IP address or hostname of the DNS server
|
||||||
# server_port: string or number, port of the DNS server
|
# server_port: string or integer, port of the DNS server
|
||||||
# path: string, optional URL path for HTTPS DNS requests
|
# path: string, URL path for HTTPS DNS requests (optional)
|
||||||
# headers: string, optional additional headers for HTTPS DNS requests
|
# headers: string, additional headers for HTTPS DNS requests (optional)
|
||||||
# domain_resolver: string, domain resolver to use for resolving domain names
|
# domain_resolver: string, domain resolver to use for resolving domain names (optional)
|
||||||
# detour: string, tag of the upstream outbound
|
# detour: string, tag of the upstream outbound (optional)
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -210,7 +210,7 @@ sing_box_cm_add_https_dns_server() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a FakeIP DNS server to the DNS section of a sing-box JSON configuration.
|
# Add a FakeIP DNS server to the DNS section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the DNS server
|
# tag: string, identifier for the DNS server
|
||||||
# inet4_range: string, IPv4 range used for fake IP mapping
|
# inet4_range: string, IPv4 range used for fake IP mapping
|
||||||
# Outputs:
|
# Outputs:
|
||||||
@@ -236,7 +236,7 @@ sing_box_cm_add_fakeip_dns_server() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a DNS routing rule to the DNS section of a sing-box JSON configuration.
|
# Add a DNS routing rule to the DNS section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# server: string, target DNS server for the rule
|
# server: string, target DNS server for the rule
|
||||||
# tag: string, identifier for the route rule
|
# tag: string, identifier for the route rule
|
||||||
# Outputs:
|
# Outputs:
|
||||||
@@ -263,10 +263,10 @@ sing_box_cm_add_dns_route_rule() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Patch a DNS routing rule in the DNS section of a sing-box JSON configuration.
|
# Patch a DNS routing rule in the DNS section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier of the rule to patch
|
# tag: string, identifier of the rule to patch
|
||||||
# key: string, the key in the rule to update or add
|
# key: string, the key in the rule to update or add
|
||||||
# value: JSON value to assign to the key
|
# value: string, JSON value to assign to the key
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -304,9 +304,9 @@ sing_box_cm_patch_dns_route_rule() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a DNS reject rule to the DNS section of a sing-box JSON configuration.
|
# Add a DNS reject rule to the DNS section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# key: string, the key to set for the reject rule
|
# key: string, the key to set for the reject rule
|
||||||
# value: JSON value to assign to the key
|
# value: string, JSON value to assign to the key
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -331,10 +331,10 @@ sing_box_cm_add_dns_reject_rule() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a TProxy inbound to the inbounds section of a sing-box JSON configuration.
|
# Add a TProxy inbound to the inbounds section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the inbound
|
# tag: string, identifier for the inbound
|
||||||
# listen_address: string, IP address to listen on
|
# listen_address: string, IP address to listen on
|
||||||
# listen_port: number, port to listen on
|
# listen_port: integer, port to listen on
|
||||||
# tcp_fast_open: boolean, enable or disable TCP Fast Open
|
# tcp_fast_open: boolean, enable or disable TCP Fast Open
|
||||||
# udp_fragment: boolean, enable or disable UDP fragmentation
|
# udp_fragment: boolean, enable or disable UDP fragmentation
|
||||||
# Outputs:
|
# Outputs:
|
||||||
@@ -369,10 +369,10 @@ sing_box_cm_add_tproxy_inbound() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a Direct inbound to the inbounds section of a sing-box JSON configuration.
|
# Add a Direct inbound to the inbounds section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the inbound
|
# tag: string, identifier for the inbound
|
||||||
# listen_address: string, IP address to listen on
|
# listen_address: string, IP address to listen on
|
||||||
# listen_port: number, port to listen on
|
# listen_port: integer, port to listen on
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -399,10 +399,10 @@ sing_box_cm_add_direct_inbound() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a Mixed inbound to the inbounds section of a sing-box JSON configuration.
|
# Add a Mixed inbound to the inbounds section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the inbound
|
# tag: string, identifier for the inbound
|
||||||
# listen_address: string, IP address to listen on
|
# listen_address: string, IP address to listen on
|
||||||
# listen_port: number, port to listen on
|
# listen_port: integer, port to listen on
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -429,7 +429,7 @@ sing_box_cm_add_mixed_inbound() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a Direct outbound to the outbounds section of a sing-box JSON configuration.
|
# Add a Direct outbound to the outbounds section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the outbound
|
# tag: string, identifier for the outbound
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
@@ -451,15 +451,15 @@ sing_box_cm_add_direct_outbound() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a SOCKS outbound to the outbounds section of a sing-box JSON configuration.
|
# Add a SOCKS outbound to the outbounds section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the outbound
|
# tag: string, identifier for the outbound
|
||||||
# server_address: string, IP address or hostname of the SOCKS server
|
# server_address: string, IP address or hostname of the SOCKS server
|
||||||
# server_port: number, port of the SOCKS server
|
# server_port: integer, port of the SOCKS server
|
||||||
# version: string, optional SOCKS version
|
# version: string, SOCKS version (optional)
|
||||||
# username: string, optional username for authentication
|
# username: string, username for authentication (optional)
|
||||||
# password: string, optional password for authentication
|
# password: string, password for authentication (optional)
|
||||||
# network: string, optional network type (e.g., "tcp")
|
# network: string, network type (e.g., "tcp") (optional)
|
||||||
# udp_over_tcp: number, optional version for UDP over TCP
|
# udp_over_tcp: integer, version for UDP over TCP (optional)
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -509,16 +509,16 @@ sing_box_cm_add_socks_outbound() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a Shadowsocks outbound to the outbounds section of a sing-box JSON configuration.
|
# Add a Shadowsocks outbound to the outbounds section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the outbound
|
# tag: string, identifier for the outbound
|
||||||
# server_address: string, IP address or hostname of the Shadowsocks server
|
# server_address: string, IP address or hostname of the Shadowsocks server
|
||||||
# server_port: number, port of the Shadowsocks server
|
# server_port: integer, port of the Shadowsocks server
|
||||||
# method: string, encryption method
|
# method: string, encryption method
|
||||||
# password: string, password for encryption
|
# password: string, password for encryption
|
||||||
# network: string, optional network type (e.g., "tcp")
|
# network: string, network type (e.g., "tcp") (optional)
|
||||||
# udp_over_tcp: number, optional version for UDP over TCP
|
# udp_over_tcp: integer, version for UDP over TCP (optional)
|
||||||
# plugin: string, optional plugin name
|
# plugin: string, plugin name (optional)
|
||||||
# plugin_opts: string, optional plugin options
|
# plugin_opts: string, plugin options (optional)
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -573,14 +573,14 @@ sing_box_cm_add_shadowsocks_outbound() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a VLESS outbound to the outbounds section of a sing-box JSON configuration.
|
# Add a VLESS outbound to the outbounds section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the outbound
|
# tag: string, identifier for the outbound
|
||||||
# server_address: string, IP address or hostname of the VLESS server
|
# server_address: string, IP address or hostname of the VLESS server
|
||||||
# server_port: number, port of the VLESS server
|
# server_port: integer, port of the VLESS server
|
||||||
# uuid: string, user UUID
|
# uuid: string, user UUID
|
||||||
# flow: string, optional flow setting
|
# flow: string, flow setting (optional)
|
||||||
# network: string, optional network type (e.g., "tcp")
|
# network: string, network type (e.g., "tcp") (optional)
|
||||||
# packet_encoding: string, optional packet encoding method
|
# packet_encoding: string, packet encoding method (optional)
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -624,12 +624,12 @@ sing_box_cm_add_vless_outbound() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a Trojan outbound to the outbounds section of a sing-box JSON configuration.
|
# Add a Trojan outbound to the outbounds section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: string, JSON configuration
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the outbound
|
# tag: string, identifier for the outbound
|
||||||
# server_address: string, IP address or hostname of the Trojan server
|
# server_address: string, IP address or hostname of the Trojan server
|
||||||
# server_port: number, port of the Trojan server
|
# server_port: integer, port of the Trojan server
|
||||||
# password: string, password for authentication
|
# password: string, password for authentication
|
||||||
# network: string, optional network type (e.g., "tcp")
|
# network: string, network type (e.g., "tcp") (optional)
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -661,15 +661,92 @@ sing_box_cm_add_trojan_outbound() {
|
|||||||
)]'
|
)]'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Add a Hysteria2 outbound to the outbounds section of a sing-box JSON configuration.
|
||||||
|
# Arguments:
|
||||||
|
# config: string (JSON), sing-box configuration to modify
|
||||||
|
# tag: string, identifier for the outbound
|
||||||
|
# server_address: string, IP address or hostname of the Hysteria2 server
|
||||||
|
# server_port: integer, port of the Hysteria2 server
|
||||||
|
# password: string, password for authentication
|
||||||
|
# obfuscator_type: string, obfuscation type (optional)
|
||||||
|
# obfuscator_password: string, obfuscation password (optional)
|
||||||
|
# upload_mbps: integer, upload bandwidth limit in Mbps (optional)
|
||||||
|
# download_mbps: integer, download bandwidth limit in Mbps (optional)
|
||||||
|
# network: string, network type (e.g., "udp") (optional)
|
||||||
|
# Outputs:
|
||||||
|
# Writes updated JSON configuration to stdout
|
||||||
|
# Example:
|
||||||
|
# CONFIG=$(sing_box_cm_add_hysteria2_outbound "$CONFIG" "hysteria2-out" "example.com" 443 "supersecret" \
|
||||||
|
# "salamander" "obfs-pass" "50" "200" "udp")
|
||||||
|
#######################################
|
||||||
|
sing_box_cm_add_hysteria2_outbound() {
|
||||||
|
local config="$1"
|
||||||
|
local tag="$2"
|
||||||
|
local server_address="$3"
|
||||||
|
local server_port="$4"
|
||||||
|
local password="$5"
|
||||||
|
local obfuscator_type="$6"
|
||||||
|
local obfuscator_password="$7"
|
||||||
|
local upload_mbps="$8"
|
||||||
|
local download_mbps="$9"
|
||||||
|
local network="${10}"
|
||||||
|
|
||||||
|
local is_multi_port="false"
|
||||||
|
case "$server_port" in
|
||||||
|
*","*|*"-"*) is_multi_port="true" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "$config" | jq \
|
||||||
|
--arg tag "$tag" \
|
||||||
|
--arg server_address "$server_address" \
|
||||||
|
--arg server_port "$server_port" \
|
||||||
|
--arg password "$password" \
|
||||||
|
--arg obfuscator_type "$obfuscator_type" \
|
||||||
|
--arg obfuscator_password "$obfuscator_password" \
|
||||||
|
--arg upload_mbps "$upload_mbps" \
|
||||||
|
--arg download_mbps "$download_mbps" \
|
||||||
|
--arg network "$network" \
|
||||||
|
--argjson is_multi_port "$is_multi_port" \
|
||||||
|
'
|
||||||
|
def parse_port_entry:
|
||||||
|
if index("-") then split("-") | join(":")
|
||||||
|
else . + ":" + .
|
||||||
|
end;
|
||||||
|
|
||||||
|
.outbounds += [(
|
||||||
|
{
|
||||||
|
type: "hysteria2",
|
||||||
|
tag: $tag,
|
||||||
|
server: $server_address,
|
||||||
|
password: $password
|
||||||
|
}
|
||||||
|
+ (if $is_multi_port then {
|
||||||
|
server_ports: ($server_port | split(",") | map(ltrimstr(" ") | rtrimstr(" ") | parse_port_entry))
|
||||||
|
} else {
|
||||||
|
server_port: ($server_port | tonumber)
|
||||||
|
} end)
|
||||||
|
+ (if $obfuscator_type != "" and $obfuscator_password != "" then {
|
||||||
|
obfs: {
|
||||||
|
type: $obfuscator_type,
|
||||||
|
password: $obfuscator_password
|
||||||
|
}
|
||||||
|
} else {} end)
|
||||||
|
+ (if $upload_mbps != "" then {up_mbps: ($upload_mbps | tonumber)} else {} end)
|
||||||
|
+ (if $download_mbps != "" then {down_mbps: ($download_mbps | tonumber)} else {} end)
|
||||||
|
+ (if $network != "" then {network: $network} else {} end)
|
||||||
|
)]'
|
||||||
|
}
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Set gRPC transport settings for an outbound in a sing-box JSON configuration.
|
# Set gRPC transport settings for an outbound in a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier of the outbound to modify
|
# tag: string, identifier of the outbound to modify
|
||||||
# service_name: string, optional gRPC service name
|
# service_name: string, gRPC service name (optional)
|
||||||
# idle_timeout: string or number, optional idle timeout
|
# idle_timeout: string or integer, idle timeout (optional)
|
||||||
# ping_timeout: string or number, optional ping timeout
|
# ping_timeout: string or integer, ping timeout (optional)
|
||||||
# permit_without_stream: boolean, optional flag for permitting without stream
|
# permit_without_stream: boolean, flag for permitting without stream (optional)
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -709,12 +786,12 @@ sing_box_cm_set_grpc_transport_for_outbound() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Set WebSocket transport settings for an outbound in a sing-box JSON configuration.
|
# Set WebSocket transport settings for an outbound in a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier of the outbound to modify
|
# tag: string, identifier of the outbound to modify
|
||||||
# path: string, WebSocket path
|
# path: string, WebSocket path
|
||||||
# host: string, optional Host header for WebSocket
|
# host: string, Host header for WebSocket (optional)
|
||||||
# max_early_data: number, optional maximum early data
|
# max_early_data: integer, maximum early data (optional)
|
||||||
# early_data_header_name: string, optional header name for early data
|
# early_data_header_name: string, header name for early data (optional)
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -759,14 +836,14 @@ sing_box_cm_set_ws_transport_for_outbound() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Set TLS settings for an outbound in a sing-box JSON configuration.
|
# Set TLS settings for an outbound in a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier of the outbound to modify
|
# tag: string, identifier of the outbound to modify
|
||||||
# server_name: string, optional, used to verify the hostname on the returned certificates
|
# server_name: string, used to verify the hostname on the returned certificates (optional)
|
||||||
# insecure: boolean, accept any server certificate
|
# insecure: boolean, accept any server certificate (optional)
|
||||||
# alpn: JSON value or null, optional supported application level protocols
|
# alpn: string, JSON value, supported application level protocols (optional)
|
||||||
# utls_fingerprint: string, optional uTLS fingerprint
|
# utls_fingerprint: string, uTLS fingerprint (optional)
|
||||||
# reality_public_key: string, optional Reality public key
|
# reality_public_key: string, Reality public key (optional)
|
||||||
# reality_short_id: string, optional Reality short ID
|
# reality_short_id: string, Reality short ID (optional)
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -825,7 +902,7 @@ sing_box_cm_set_tls_for_outbound() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a Direct outbound with a specific network interface to a sing-box JSON configuration.
|
# Add a Direct outbound with a specific network interface to a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the outbound
|
# tag: string, identifier for the outbound
|
||||||
# interface: string, network interface to bind the outbound
|
# interface: string, network interface to bind the outbound
|
||||||
# domain_resolver: string, tag of the domain resolver to be used for this outbound (optional)
|
# domain_resolver: string, tag of the domain resolver to be used for this outbound (optional)
|
||||||
@@ -857,9 +934,9 @@ sing_box_cm_add_interface_outbound() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a raw outbound JSON object to the outbounds section of a sing-box configuration.
|
# Add a raw outbound JSON object to the outbounds section of a sing-box configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the outbound
|
# tag: string, identifier for the outbound
|
||||||
# raw_outbound: JSON object, the raw outbound configuration to add
|
# raw_outbound: string, JSON object, the raw outbound configuration to add
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -881,14 +958,14 @@ sing_box_cm_add_raw_outbound() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a URLTest outbound to the outbounds section of a sing-box JSON configuration.
|
# Add a URLTest outbound to the outbounds section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the URLTest outbound
|
# tag: string, identifier for the URLTest outbound
|
||||||
# outbounds: JSON array of outbound tags to test
|
# outbounds: string, JSON array of outbound tags to test
|
||||||
# url: URL to probe (optional)
|
# url: string, URL to probe (optional)
|
||||||
# interval: test interval (e.g., "10s") (optional)
|
# interval: string, test interval (e.g., "10s") (optional)
|
||||||
# tolerance: max latency difference tolerated (optional)
|
# tolerance: string or integer, max latency difference tolerated (optional)
|
||||||
# idle_timeout: idle timeout duration (optional)
|
# idle_timeout: string or integer, idle timeout duration (optional)
|
||||||
# interrupt_exist_connections: flag to interrupt existing connections ("true"/"false") (optional)
|
# interrupt_exist_connections: boolean, flag to interrupt existing connections ("true"/"false") (optional)
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -929,11 +1006,11 @@ sing_box_cm_add_urltest_outbound() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a Selector outbound to the outbounds section of a sing-box JSON configuration.
|
# Add a Selector outbound to the outbounds section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the Selector outbound
|
# tag: string, identifier for the Selector outbound
|
||||||
# outbounds: JSON array of outbound tags to choose from
|
# outbounds: string (JSON), array of outbound tags to choose from
|
||||||
# default: default outbound tag if none selected (optional)
|
# default: string, default outbound tag if none selected
|
||||||
# interrupt_exist_connections: flag to interrupt existing connections ("true"/"false") (optional)
|
# interrupt_exist_connections: boolean, flag to interrupt existing connections ("true"/"false") (optional)
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -965,11 +1042,11 @@ sing_box_cm_add_selector_outbound() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Configure the route section of a sing-box JSON configuration.
|
# Configure the route section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# final: string, final outbound tag for unmatched traffic
|
# final: string, final outbound tag for unmatched traffic
|
||||||
# auto_detect_interface: boolean, enable or disable automatic interface detection
|
# auto_detect_interface: boolean, enable or disable automatic interface detection
|
||||||
# default_domain_resolver: string, default DNS resolver for domain-based routing
|
# default_domain_resolver: string, default DNS resolver for domain-based routing
|
||||||
# default_interface: string, default network interface to use when auto detection is disabled
|
# default_interface: string, default network interface to use when auto detection is disabled (optional)
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -1001,7 +1078,7 @@ sing_box_cm_configure_route() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a routing rule to the route section of a sing-box JSON configuration.
|
# Add a routing rule to the route section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the route rule
|
# tag: string, identifier for the route rule
|
||||||
# inbound: string, inbound tag to match
|
# inbound: string, inbound tag to match
|
||||||
# outbound: string, outbound tag to route matched traffic to
|
# outbound: string, outbound tag to route matched traffic to
|
||||||
@@ -1029,13 +1106,49 @@ sing_box_cm_add_route_rule() {
|
|||||||
}]'
|
}]'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Insert a resolve rule immediately before a route rule.
|
||||||
|
# Copies rule_set from the target route rule.
|
||||||
|
# Arguments:
|
||||||
|
# config: string (JSON), sing-box configuration to modify
|
||||||
|
# route_rule_tag: string, tag of the route rule to precede
|
||||||
|
# resolve_rule_tag: string, tag for the new resolve rule
|
||||||
|
# server: string, DNS server tag (optional, default: "dns-server")
|
||||||
|
# Outputs:
|
||||||
|
# Updated JSON config to stdout
|
||||||
|
#######################################
|
||||||
|
sing_box_cm_add_resolve_rule() {
|
||||||
|
local config="$1"
|
||||||
|
local route_rule_tag="$2"
|
||||||
|
local resolve_rule_tag="$3"
|
||||||
|
local server="${4:-dns-server}"
|
||||||
|
|
||||||
|
echo "$config" | jq \
|
||||||
|
--arg service_tag "$SERVICE_TAG" \
|
||||||
|
--arg route_tag "$route_rule_tag" \
|
||||||
|
--arg resolve_tag "$resolve_rule_tag" \
|
||||||
|
--arg server "$server" \
|
||||||
|
'.route.rules |= [
|
||||||
|
.[] |
|
||||||
|
if .[$service_tag] == $route_tag then
|
||||||
|
{
|
||||||
|
action: "resolve",
|
||||||
|
rule_set: (.rule_set // []),
|
||||||
|
server: $server,
|
||||||
|
($service_tag): $resolve_tag
|
||||||
|
}, .
|
||||||
|
else .
|
||||||
|
end
|
||||||
|
]'
|
||||||
|
}
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Patch a routing rule in the route section of a sing-box JSON configuration.
|
# Patch a routing rule in the route section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier of the route rule to patch
|
# tag: string, identifier of the route rule to patch
|
||||||
# key: string, the key in the rule to update or add
|
# key: string, the key in the rule to update or add
|
||||||
# value: JSON value to assign to the key
|
# value: string (JSON), value to assign to the key
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -1071,9 +1184,9 @@ sing_box_cm_patch_route_rule() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a reject rule to the route section of a sing-box JSON configuration.
|
# Add a reject rule to the route section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# key: string, the key to set for the reject rule
|
# key: string, the key to set for the reject rule
|
||||||
# value: JSON value to assign to the key
|
# value: string (JSON), value to assign to the key
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -1098,9 +1211,9 @@ sing_box_cm_add_reject_route_rule() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a hijack-dns rule to the route section of a sing-box JSON configuration.
|
# Add a hijack-dns rule to the route section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# key: string, the key to set for the hijack-dns rule
|
# key: string, the key to set for the hijack-dns rule
|
||||||
# value: JSON value to assign to the key
|
# value: string (JSON), value to assign to the key
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -1125,7 +1238,7 @@ sing_box_cm_add_hijack_dns_route_rule() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a route-options rule to the route section of a sing-box JSON configuration.
|
# Add a route-options rule to the route section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the route-options rule
|
# tag: string, identifier for the route-options rule
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
@@ -1148,9 +1261,9 @@ sing_box_cm_add_options_route_rule() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a sniff rule to the route section of a sing-box JSON configuration.
|
# Add a sniff rule to the route section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# key: string, the key to set for the sniff rule
|
# key: string, the key to set for the sniff rule
|
||||||
# value: JSON value to assign to the key
|
# value: string (JSON), value to assign to the key
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -1176,7 +1289,7 @@ sing_box_cm_sniff_route_rule() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add an inline ruleset to the route.rule_set section of a sing-box JSON configuration.
|
# Add an inline ruleset to the route.rule_set section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the inline ruleset
|
# tag: string, identifier for the inline ruleset
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
@@ -1198,10 +1311,10 @@ sing_box_cm_add_inline_ruleset() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add or update a rule in an inline ruleset within the route.rule_set section of a sing-box JSON configuration.
|
# Add or update a rule in an inline ruleset within the route.rule_set section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier of the inline ruleset
|
# tag: string, identifier of the inline ruleset
|
||||||
# key: string, the key in the ruleset to update or add
|
# key: string, the key in the ruleset to update or add
|
||||||
# value: JSON value to assign to the key
|
# value: string (JSON), value to assign to the key
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -1238,7 +1351,7 @@ sing_box_cm_add_inline_ruleset_rule() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a local ruleset to the route.rule_set section of a sing-box JSON configuration.
|
# Add a local ruleset to the route.rule_set section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the local ruleset
|
# tag: string, identifier for the local ruleset
|
||||||
# format: string, format of the local ruleset ("source" or "binary")
|
# format: string, format of the local ruleset ("source" or "binary")
|
||||||
# path: string, file path to the local ruleset
|
# path: string, file path to the local ruleset
|
||||||
@@ -1269,12 +1382,12 @@ sing_box_cm_add_local_ruleset() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Add a remote ruleset to the route.rule_set section of a sing-box JSON configuration.
|
# Add a remote ruleset to the route.rule_set section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# tag: string, identifier for the remote ruleset
|
# tag: string, identifier for the remote ruleset
|
||||||
# format: string, format of the remote ruleset ("source" or "binary")
|
# format: string, format of the remote ruleset ("source" or "binary")
|
||||||
# url: string, URL to download the ruleset from
|
# url: string, URL to download the ruleset from
|
||||||
# download_detour: string, optional detour tag for downloading
|
# download_detour: string, detour tag for downloading (optional)
|
||||||
# update_interval: string, optional update interval for the ruleset
|
# update_interval: string, update interval for the ruleset (optional)
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -1310,7 +1423,7 @@ sing_box_cm_add_remote_ruleset() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Configure the experimental cache_file section of a sing-box JSON configuration.
|
# Configure the experimental cache_file section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# enabled: boolean, enable or disable file caching
|
# enabled: boolean, enable or disable file caching
|
||||||
# path: string, file path for cache storage
|
# path: string, file path for cache storage
|
||||||
# store_fakeip: boolean, whether to store fake IPs in the cache
|
# store_fakeip: boolean, whether to store fake IPs in the cache
|
||||||
@@ -1339,9 +1452,10 @@ sing_box_cm_configure_cache_file() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Configure the experimental clash_api section of a sing-box JSON configuration.
|
# Configure the experimental clash_api section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# external_controller: API listening address; Clash API will be disabled if empty
|
# external_controller: string, API listening address; Clash API will be disabled if empty
|
||||||
# external_ui: Optional path to static web resources to serve at http://{{external-controller}}/ui
|
# external_ui: string, path to static web resources to serve at http://{{external-controller}}/ui (optional)
|
||||||
|
# secret: string, secret for the RESTful API Authenticate by specifying HTTP header (optional)
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -1351,65 +1465,23 @@ sing_box_cm_configure_clash_api() {
|
|||||||
local config="$1"
|
local config="$1"
|
||||||
local external_controller="$2"
|
local external_controller="$2"
|
||||||
local external_ui="$3"
|
local external_ui="$3"
|
||||||
|
local secret="$4"
|
||||||
|
|
||||||
echo "$config" | jq \
|
echo "$config" | jq \
|
||||||
--arg external_controller "$external_controller" \
|
--arg external_controller "$external_controller" \
|
||||||
--arg external_ui "$external_ui" \
|
--arg external_ui "$external_ui" \
|
||||||
|
--arg secret "$secret" \
|
||||||
'.experimental.clash_api = {
|
'.experimental.clash_api = {
|
||||||
external_controller: $external_controller,
|
external_controller: $external_controller,
|
||||||
}
|
}
|
||||||
+ (if $external_ui != "" then { external_ui: $external_ui } else {} end)'
|
+ (if $external_ui != "" then { external_ui: $external_ui } else {} end)
|
||||||
}
|
+ (if $secret != "" then { secret: $secret } else {} end)'
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Create a local source ruleset JSON file for sing-box.
|
|
||||||
# Arguments:
|
|
||||||
# filepath: path to the JSON file to create
|
|
||||||
# Example:
|
|
||||||
# sing_box_cm_create_local_source_ruleset "/tmp/sing-box/ruleset.json"
|
|
||||||
#######################################
|
|
||||||
sing_box_cm_create_local_source_ruleset() {
|
|
||||||
local filepath="$1"
|
|
||||||
|
|
||||||
jq -n '{version: 3, rules: []}' > "$filepath"
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Patch a local source ruleset JSON file for sing-box by adding unique! values to a given key.
|
|
||||||
# Arguments:
|
|
||||||
# filepath: path to the JSON file to patch
|
|
||||||
# key: the ruleset key to update (e.g., "ip_cidr")
|
|
||||||
# value: a JSON array of values to add to the key
|
|
||||||
# Example:
|
|
||||||
# sing_box_cm_patch_local_source_ruleset_rules "/tmp/sing-box/ruleset.json" "ip_cidr" '["1.1.1.1","2.2.2.2"]'
|
|
||||||
#######################################
|
|
||||||
sing_box_cm_patch_local_source_ruleset_rules() {
|
|
||||||
local filepath="$1"
|
|
||||||
local key="$2"
|
|
||||||
local value="$3"
|
|
||||||
|
|
||||||
value=$(_normalize_arg "$value")
|
|
||||||
|
|
||||||
local content
|
|
||||||
content="$(cat "$filepath")"
|
|
||||||
|
|
||||||
echo "$content" | jq \
|
|
||||||
--arg key "$key" \
|
|
||||||
--argjson value "$value" '
|
|
||||||
([.rules[]?[$key][]] | unique) as $existing
|
|
||||||
| ($value - $existing) as $value
|
|
||||||
| if ($value | length) > 0 then
|
|
||||||
.rules += [{($key): $value}]
|
|
||||||
else
|
|
||||||
.
|
|
||||||
end
|
|
||||||
' > "$filepath"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Save a sing-box JSON configuration to a file, removing service-specific tags.
|
# Save a sing-box JSON configuration to a file, removing service-specific tags.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string (JSON), sing-box configuration to modify
|
||||||
# file_path: string, path to save the configuration file
|
# file_path: string, path to save the configuration file
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes the cleaned JSON configuration to the specified file
|
# Writes the cleaned JSON configuration to the specified file
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM openwrt/sdk:x86-64-SNAPSHOT
|
FROM openwrt/sdk:x86_64-v25.12.3
|
||||||
WORKDIR /builder
|
WORKDIR /builder
|
||||||
RUN ./setup.sh \
|
RUN ./setup.sh \
|
||||||
&& ./scripts/feeds update -a \
|
&& ./scripts/feeds update -a \
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM openwrt/sdk:x86_64-v24.10.3
|
FROM openwrt/sdk:x86_64-v24.10.6
|
||||||
WORKDIR /builder
|
WORKDIR /builder
|
||||||
RUN ./scripts/feeds update -a \
|
RUN ./scripts/feeds update -a \
|
||||||
&& ./scripts/feeds install luci-base \
|
&& ./scripts/feeds install luci-base \
|
||||||
|
|||||||
Reference in New Issue
Block a user