feat: content blocking в родительском контроле (блокировка доменов на устройство)
Новые опции config schedule: - blocked_domains: домены для блокировки (full:/keyword:/regex: префиксы) - mode: block (список) | allow (whitelist — всё кроме списка) - dns_level: блокировка на DNS-уровне (NXDOMAIN через dns-block-in) - notify: уведомление в Telegram при попытке доступа Механизм: - sing-box: новый dns-block-in inbound (127.0.0.43:1053) с reject-правилами для заблокированных доменов; source_ip_cidr для IP-устройств; invert для whitelist-режима - nftables: nat chain dns_block — REDIRECT DNS-запросов устройств на dns-block-in; time-based через meta hour для расписаний; MAC-устройства матчатся по ether saddr (DHCP-динамические IP поддерживаются) - route rules reject для always-on расписаний (fallback при обходе DNS) - telegram worker: проверка nft counters каждые 60s, уведомление о заблокированной активности UI (parental.js): - колонка Blocked Sites в таблице - textarea с пресетами: соцсети, видео, игры, взрослый контент, мессенджеры, магазины - mode / dns_level / notify переключатели Валидация: домены, mode, dns_level, notify в validator.uc Тесты: tests/content_blocking.sh (98/98 backend, 522/522 frontend)
This commit is contained in:
@@ -146,7 +146,7 @@
|
|||||||
"call": "Action Mode",
|
"call": "Action Mode",
|
||||||
"key": "Action Mode",
|
"key": "Action Mode",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:348"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:441"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -165,16 +165,16 @@
|
|||||||
"call": "Active (Allowed)",
|
"call": "Active (Allowed)",
|
||||||
"key": "Active (Allowed)",
|
"key": "Active (Allowed)",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:260",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:353",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:280"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:373"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"call": "Active (Blocking)",
|
"call": "Active (Blocking)",
|
||||||
"key": "Active (Blocking)",
|
"key": "Active (Blocking)",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:260",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:353",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:280"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:373"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -335,6 +335,13 @@
|
|||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:2145"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:2145"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"call": "Adult content",
|
||||||
|
"key": "Adult content",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:73"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"call": "Advanced self-healing features. Requires Watchdog to be enabled.",
|
"call": "Advanced self-healing features. Requires Watchdog to be enabled.",
|
||||||
"key": "Advanced self-healing features. Requires Watchdog to be enabled.",
|
"key": "Advanced self-healing features. Requires Watchdog to be enabled.",
|
||||||
@@ -509,8 +516,8 @@
|
|||||||
"call": "All devices",
|
"call": "All devices",
|
||||||
"key": "All devices",
|
"key": "All devices",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:139",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:201",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:159"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:221"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -524,15 +531,15 @@
|
|||||||
"call": "All Internet",
|
"call": "All Internet",
|
||||||
"key": "All Internet",
|
"key": "All Internet",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:169",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:231",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:194"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:256"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"call": "All Internet (Complete internet cutoff)",
|
"call": "All Internet (Complete internet cutoff)",
|
||||||
"key": "All Internet (Complete internet cutoff)",
|
"key": "All Internet (Complete internet cutoff)",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:320"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:413"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -584,15 +591,15 @@
|
|||||||
"call": "Allow / Enable ONLY in scheduled hours (White period)",
|
"call": "Allow / Enable ONLY in scheduled hours (White period)",
|
||||||
"key": "Allow / Enable ONLY in scheduled hours (White period)",
|
"key": "Allow / Enable ONLY in scheduled hours (White period)",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:354"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:447"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"call": "Allow in interval",
|
"call": "Allow in interval",
|
||||||
"key": "Allow in interval",
|
"key": "Allow in interval",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:206",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:268",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:212"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:274"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -602,6 +609,27 @@
|
|||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:8514"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:8514"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"call": "Allow only",
|
||||||
|
"key": "Allow only",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:314"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"call": "Allow only listed sites (Whitelist)",
|
||||||
|
"key": "Allow only listed sites (Whitelist)",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:587"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"call": "Allow only:",
|
||||||
|
"key": "Allow only:",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:330"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"call": "Allowed domain prefixes are full:, keyword:, and regex:",
|
"call": "Allowed domain prefixes are full:, keyword:, and regex:",
|
||||||
"key": "Allowed domain prefixes are full:, keyword:, and regex:",
|
"key": "Allowed domain prefixes are full:, keyword:, and regex:",
|
||||||
@@ -904,7 +932,7 @@
|
|||||||
"call": "Beginning of the schedule interval (e.g. 22:00)",
|
"call": "Beginning of the schedule interval (e.g. 22:00)",
|
||||||
"key": "Beginning of the schedule interval (e.g. 22:00)",
|
"key": "Beginning of the schedule interval (e.g. 22:00)",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:361"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:454"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -922,19 +950,33 @@
|
|||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:9554"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:9554"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"call": "Block",
|
||||||
|
"key": "Block",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:315"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"call": "Block / Disable in scheduled hours (Standard)",
|
"call": "Block / Disable in scheduled hours (Standard)",
|
||||||
"key": "Block / Disable in scheduled hours (Standard)",
|
"key": "Block / Disable in scheduled hours (Standard)",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:353"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:446"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"call": "Block at DNS level",
|
||||||
|
"key": "Block at DNS level",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:593"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"call": "Block in interval",
|
"call": "Block in interval",
|
||||||
"key": "Block in interval",
|
"key": "Block in interval",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:208",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:270",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:212"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:274"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -944,6 +986,41 @@
|
|||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/tachyon.js:467"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/tachyon.js:467"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"call": "Block listed sites (Standard)",
|
||||||
|
"key": "Block listed sites (Standard)",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:586"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"call": "Block:",
|
||||||
|
"key": "Block:",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:330"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"call": "Block: deny the listed sites. Allow only (whitelist): deny everything except the listed sites. Whitelist mode requires DNS-level blocking and applies to the schedule window.",
|
||||||
|
"key": "Block: deny the listed sites. Allow only (whitelist): deny everything except the listed sites. Whitelist mode requires DNS-level blocking and applies to the schedule window.",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:582"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"call": "Blocked Sites",
|
||||||
|
"key": "Blocked Sites",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:303"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"call": "Blocked Sites (Domains)",
|
||||||
|
"key": "Blocked Sites (Domains)",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:492"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"call": "Bootstrap DNS",
|
"call": "Bootstrap DNS",
|
||||||
"key": "Bootstrap DNS",
|
"key": "Bootstrap DNS",
|
||||||
@@ -1361,8 +1438,8 @@
|
|||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8845",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8845",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9323",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9323",
|
||||||
"src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:10",
|
"src/tachyon/tabs/diagnostic/helpers/getMeta.ts:26",
|
||||||
"src/tachyon/tabs/diagnostic/helpers/getMeta.ts:26"
|
"src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:10"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1372,9 +1449,9 @@
|
|||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8834",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8834",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9280",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9280",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9334",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9334",
|
||||||
|
"src/tachyon/tabs/diagnostic/helpers/getMeta.ts:13",
|
||||||
"src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:23",
|
"src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:23",
|
||||||
"src/tachyon/tabs/diagnostic/checks/runFakeIPCheck.ts:43",
|
"src/tachyon/tabs/diagnostic/checks/runFakeIPCheck.ts:43"
|
||||||
"src/tachyon/tabs/diagnostic/helpers/getMeta.ts:13"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1403,7 +1480,7 @@
|
|||||||
"call": "Choose whether to restrict the entire internet or only specific Tachyon routing sections.",
|
"call": "Choose whether to restrict the entire internet or only specific Tachyon routing sections.",
|
||||||
"key": "Choose whether to restrict the entire internet or only specific Tachyon routing sections.",
|
"key": "Choose whether to restrict the entire internet or only specific Tachyon routing sections.",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:316"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:409"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1417,7 +1494,7 @@
|
|||||||
"call": "Choose which routing sections to apply this schedule to.",
|
"call": "Choose which routing sections to apply this schedule to.",
|
||||||
"key": "Choose which routing sections to apply this schedule to.",
|
"key": "Choose which routing sections to apply this schedule to.",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:328"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:421"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1770,6 +1847,13 @@
|
|||||||
"src/tachyon/tabs/diagnostic/checks/runSectionsCheck.ts:174"
|
"src/tachyon/tabs/diagnostic/checks/runSectionsCheck.ts:174"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"call": "Content Mode",
|
||||||
|
"key": "Content Mode",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:581"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"call": "Cookie packet junk size (S3)",
|
"call": "Cookie packet junk size (S3)",
|
||||||
"key": "Cookie packet junk size (S3)",
|
"key": "Cookie packet junk size (S3)",
|
||||||
@@ -1958,7 +2042,7 @@
|
|||||||
"call": "Days of Week",
|
"call": "Days of Week",
|
||||||
"key": "Days of Week",
|
"key": "Days of Week",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:384"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:477"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2055,7 +2139,7 @@
|
|||||||
"call": "Device / IP / MAC",
|
"call": "Device / IP / MAC",
|
||||||
"key": "Device / IP / MAC",
|
"key": "Device / IP / MAC",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:132"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:194"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2187,8 +2271,8 @@
|
|||||||
"call": "Disabled",
|
"call": "Disabled",
|
||||||
"key": "Disabled",
|
"key": "Disabled",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:250",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:343",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:277"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:370"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2532,6 +2616,13 @@
|
|||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:9310"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:9310"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"call": "Domains to block for the selected devices. Leave empty to block all internet. Enter one domain per line, e.g. youtube.com. Use the preset buttons to quickly add common categories.",
|
||||||
|
"key": "Domains to block for the selected devices. Leave empty to block all internet. Enter one domain per line, e.g. youtube.com. Use the preset buttons to quickly add common categories.",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:493"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"call": "Done",
|
"call": "Done",
|
||||||
"key": "Done",
|
"key": "Done",
|
||||||
@@ -2699,7 +2790,7 @@
|
|||||||
"call": "e.g. Kids Phone (Night YouTube)",
|
"call": "e.g. Kids Phone (Night YouTube)",
|
||||||
"key": "e.g. Kids Phone (Night YouTube)",
|
"key": "e.g. Kids Phone (Night YouTube)",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:290"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:383"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2728,7 +2819,7 @@
|
|||||||
"call": "Enable",
|
"call": "Enable",
|
||||||
"key": "Enable",
|
"key": "Enable",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:125",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:187",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:7235",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:7235",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:2618"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:2618"
|
||||||
]
|
]
|
||||||
@@ -2958,14 +3049,14 @@
|
|||||||
"call": "End of the schedule interval (e.g. 08:00). Supports spans crossing midnight.",
|
"call": "End of the schedule interval (e.g. 08:00). Supports spans crossing midnight.",
|
||||||
"key": "End of the schedule interval (e.g. 08:00). Supports spans crossing midnight.",
|
"key": "End of the schedule interval (e.g. 08:00). Supports spans crossing midnight.",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:373"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:466"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"call": "End Time (HH:MM)",
|
"call": "End Time (HH:MM)",
|
||||||
"key": "End Time (HH:MM)",
|
"key": "End Time (HH:MM)",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:372"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:465"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -3070,7 +3161,7 @@
|
|||||||
"call": "Every day",
|
"call": "Every day",
|
||||||
"key": "Every day",
|
"key": "Every day",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:98"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:160"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -3256,12 +3347,12 @@
|
|||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:16728",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:16728",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:16786",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:16786",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:16957",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:16957",
|
||||||
"src/tachyon/methods/shell/index.ts:172",
|
|
||||||
"src/tachyon/methods/shell/index.ts:179",
|
|
||||||
"src/tachyon/tabs/updates/initController.ts:631",
|
"src/tachyon/tabs/updates/initController.ts:631",
|
||||||
"src/tachyon/tabs/updates/initController.ts:632",
|
"src/tachyon/tabs/updates/initController.ts:632",
|
||||||
"src/tachyon/tabs/updates/initController.ts:707",
|
"src/tachyon/tabs/updates/initController.ts:707",
|
||||||
"src/tachyon/tabs/updates/initController.ts:920"
|
"src/tachyon/tabs/updates/initController.ts:920",
|
||||||
|
"src/tachyon/methods/shell/index.ts:172",
|
||||||
|
"src/tachyon/methods/shell/index.ts:179"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -3668,6 +3759,13 @@
|
|||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:1285"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:1285"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"call": "Gaming",
|
||||||
|
"key": "Gaming",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:63"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"call": "Generate a random 16-character hexadecimal HWID",
|
"call": "Generate a random 16-character hexadecimal HWID",
|
||||||
"key": "Generate a random 16-character hexadecimal HWID",
|
"key": "Generate a random 16-character hexadecimal HWID",
|
||||||
@@ -4431,6 +4529,13 @@
|
|||||||
"src/validators/validateDomain.ts:73"
|
"src/validators/validateDomain.ts:73"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"call": "Invalid domain: empty prefix value",
|
||||||
|
"key": "Invalid domain: empty prefix value",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:507"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"call": "Invalid format. Use an IP address or CIDR subnet",
|
"call": "Invalid format. Use an IP address or CIDR subnet",
|
||||||
"key": "Invalid format. Use an IP address or CIDR subnet",
|
"key": "Invalid format. Use an IP address or CIDR subnet",
|
||||||
@@ -4565,7 +4670,7 @@
|
|||||||
"call": "Invalid IP or MAC address. Expected e.g. 192.168.1.150 or AA:BB:CC:DD:EE:FF",
|
"call": "Invalid IP or MAC address. Expected e.g. 192.168.1.150 or AA:BB:CC:DD:EE:FF",
|
||||||
"key": "Invalid IP or MAC address. Expected e.g. 192.168.1.150 or AA:BB:CC:DD:EE:FF",
|
"key": "Invalid IP or MAC address. Expected e.g. 192.168.1.150 or AA:BB:CC:DD:EE:FF",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:120"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:182"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -4771,7 +4876,7 @@
|
|||||||
"call": "Invalid time format. Expected HH:MM (e.g. 22:00)",
|
"call": "Invalid time format. Expected HH:MM (e.g. 22:00)",
|
||||||
"key": "Invalid time format. Expected HH:MM (e.g. 22:00)",
|
"key": "Invalid time format. Expected HH:MM (e.g. 22:00)",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:47"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:109"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -5005,8 +5110,8 @@
|
|||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8840",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8840",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9329",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9329",
|
||||||
"src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:17",
|
"src/tachyon/tabs/diagnostic/helpers/getMeta.ts:20",
|
||||||
"src/tachyon/tabs/diagnostic/helpers/getMeta.ts:20"
|
"src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:17"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -5554,6 +5659,13 @@
|
|||||||
"src/tachyon/tabs/dashboard/initController.ts:1867"
|
"src/tachyon/tabs/dashboard/initController.ts:1867"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"call": "Messengers",
|
||||||
|
"key": "Messengers",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:84"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"call": "Method",
|
"call": "Method",
|
||||||
"key": "Method",
|
"key": "Method",
|
||||||
@@ -5607,7 +5719,7 @@
|
|||||||
"call": "Mode",
|
"call": "Mode",
|
||||||
"key": "Mode",
|
"key": "Mode",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:200"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:262"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -5980,8 +6092,8 @@
|
|||||||
"call": "No sections selected",
|
"call": "No sections selected",
|
||||||
"key": "No sections selected",
|
"key": "No sections selected",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:177",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:239",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:196"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:258"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -6012,6 +6124,8 @@
|
|||||||
"key": "None",
|
"key": "None",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:12555",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:12555",
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:310",
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:329",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:449",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:449",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:2741",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:2741",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:3033",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:3033",
|
||||||
@@ -6130,6 +6244,13 @@
|
|||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:10197"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:10197"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"call": "Notify in Telegram",
|
||||||
|
"key": "Notify in Telegram",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:604"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"call": "Notify on Certificate Warnings",
|
"call": "Notify on Certificate Warnings",
|
||||||
"key": "Notify on Certificate Warnings",
|
"key": "Notify on Certificate Warnings",
|
||||||
@@ -6630,8 +6751,8 @@
|
|||||||
"key": "Pending",
|
"key": "Pending",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:5187",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:5187",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:271",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:364",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:281",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:374",
|
||||||
"src/tachyon/tabs/diagnostic/diagnostic.store.ts:63"
|
"src/tachyon/tabs/diagnostic/diagnostic.store.ts:63"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -7469,6 +7590,13 @@
|
|||||||
"src/tachyon/tabs/monitoring/initController.ts:737"
|
"src/tachyon/tabs/monitoring/initController.ts:737"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"call": "Return NXDOMAIN for blocked domains (recommended). When enabled, blocked domains are not resolved at all. When disabled, only direct connections are rejected.",
|
||||||
|
"key": "Return NXDOMAIN for blocked domains (recommended). When enabled, blocked domains are not resolved at all. When disabled, only direct connections are rejected.",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:594"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"call": "Route",
|
"call": "Route",
|
||||||
"key": "Route",
|
"key": "Route",
|
||||||
@@ -7552,7 +7680,7 @@
|
|||||||
"call": "Rule Name",
|
"call": "Rule Name",
|
||||||
"key": "Rule Name",
|
"key": "Rule Name",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:287"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:380"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -7760,7 +7888,7 @@
|
|||||||
"call": "Schedule",
|
"call": "Schedule",
|
||||||
"key": "Schedule",
|
"key": "Schedule",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:216"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:278"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -7932,7 +8060,7 @@
|
|||||||
"call": "Select active days. If none selected, the rule applies every day.",
|
"call": "Select active days. If none selected, the rule applies every day.",
|
||||||
"key": "Select active days. If none selected, the rule applies every day.",
|
"key": "Select active days. If none selected, the rule applies every day.",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:385"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:478"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -7981,7 +8109,7 @@
|
|||||||
"call": "Select LAN devices to apply this schedule to, or enter IP or MAC addresses manually.",
|
"call": "Select LAN devices to apply this schedule to, or enter IP or MAC addresses manually.",
|
||||||
"key": "Select LAN devices to apply this schedule to, or enter IP or MAC addresses manually.",
|
"key": "Select LAN devices to apply this schedule to, or enter IP or MAC addresses manually.",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:297"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:390"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -8030,7 +8158,7 @@
|
|||||||
"call": "Select Sections",
|
"call": "Select Sections",
|
||||||
"key": "Select Sections",
|
"key": "Select Sections",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:327"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:420"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -8074,7 +8202,7 @@
|
|||||||
"call": "Select whether to disable the target during the schedule or enable it ONLY during the schedule.",
|
"call": "Select whether to disable the target during the schedule or enable it ONLY during the schedule.",
|
||||||
"key": "Select whether to disable the target during the schedule or enable it ONLY during the schedule.",
|
"key": "Select whether to disable the target during the schedule or enable it ONLY during the schedule.",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:349"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:442"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -8138,6 +8266,13 @@
|
|||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:2203"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:2203"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"call": "Send a Telegram notification to admins when a blocked site is accessed. Requires the Telegram bot to be enabled.",
|
||||||
|
"key": "Send a Telegram notification to admins when a blocked site is accessed. Requires the Telegram bot to be enabled.",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:605"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"call": "Send a Telegram notification when a URLTest group switches to a new server.",
|
"call": "Send a Telegram notification when a URLTest group switches to a new server.",
|
||||||
"key": "Send a Telegram notification when a URLTest group switches to a new server.",
|
"key": "Send a Telegram notification when a URLTest group switches to a new server.",
|
||||||
@@ -8309,9 +8444,9 @@
|
|||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:3410",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:3410",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:3429",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:3429",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:12323",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:12323",
|
||||||
|
"src/tachyon/tabs/diagnostic/initController.ts:604",
|
||||||
"src/tachyon/methods/shell/index.ts:422",
|
"src/tachyon/methods/shell/index.ts:422",
|
||||||
"src/tachyon/methods/shell/index.ts:443",
|
"src/tachyon/methods/shell/index.ts:443"
|
||||||
"src/tachyon/tabs/diagnostic/initController.ts:604"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -8376,6 +8511,13 @@
|
|||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:411"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:411"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"call": "Shopping",
|
||||||
|
"key": "Shopping",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:93"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"call": "Show metadata on dashboard",
|
"call": "Show metadata on dashboard",
|
||||||
"key": "Show metadata on dashboard",
|
"key": "Show metadata on dashboard",
|
||||||
@@ -8583,6 +8725,13 @@
|
|||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:8542"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:8542"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"call": "Social media",
|
||||||
|
"key": "Social media",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:43"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"call": "Sort Alphabetically",
|
"call": "Sort Alphabetically",
|
||||||
"key": "Sort Alphabetically",
|
"key": "Sort Alphabetically",
|
||||||
@@ -8633,7 +8782,7 @@
|
|||||||
"call": "Specific Sections (Select sections below)",
|
"call": "Specific Sections (Select sections below)",
|
||||||
"key": "Specific Sections (Select sections below)",
|
"key": "Specific Sections (Select sections below)",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:321"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:414"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -8781,7 +8930,7 @@
|
|||||||
"call": "Start Time (HH:MM)",
|
"call": "Start Time (HH:MM)",
|
||||||
"key": "Start Time (HH:MM)",
|
"key": "Start Time (HH:MM)",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:360"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:453"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -8812,7 +8961,7 @@
|
|||||||
"key": "Status",
|
"key": "Status",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:2424",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:2424",
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:241",
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:334",
|
||||||
"src/tachyon/tabs/dashboard/partials/renderAdvancedSettings.ts:465",
|
"src/tachyon/tabs/dashboard/partials/renderAdvancedSettings.ts:465",
|
||||||
"src/tachyon/tabs/dashboard/partials/renderSections.ts:666"
|
"src/tachyon/tabs/dashboard/partials/renderSections.ts:666"
|
||||||
]
|
]
|
||||||
@@ -9221,21 +9370,21 @@
|
|||||||
"call": "Target",
|
"call": "Target",
|
||||||
"key": "Target",
|
"key": "Target",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:163"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:225"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"call": "Target Devices (IP / MAC)",
|
"call": "Target Devices (IP / MAC)",
|
||||||
"key": "Target Devices (IP / MAC)",
|
"key": "Target Devices (IP / MAC)",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:296"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:389"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"call": "Target Scope",
|
"call": "Target Scope",
|
||||||
"key": "Target Scope",
|
"key": "Target Scope",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:315"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:408"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -9514,7 +9663,7 @@
|
|||||||
"call": "Time is required (e.g. 22:00)",
|
"call": "Time is required (e.g. 22:00)",
|
||||||
"key": "Time is required (e.g. 22:00)",
|
"key": "Time is required (e.g. 22:00)",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:43"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:105"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -10473,6 +10622,13 @@
|
|||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:1986"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:1986"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"call": "Video streaming",
|
||||||
|
"key": "Video streaming",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:53"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"call": "View logs",
|
"call": "View logs",
|
||||||
"key": "View logs",
|
"key": "View logs",
|
||||||
@@ -10609,14 +10765,14 @@
|
|||||||
"call": "Weekdays (Mon-Fri)",
|
"call": "Weekdays (Mon-Fri)",
|
||||||
"key": "Weekdays (Mon-Fri)",
|
"key": "Weekdays (Mon-Fri)",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:106"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:168"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"call": "Weekends (Sat-Sun)",
|
"call": "Weekends (Sat-Sun)",
|
||||||
"key": "Weekends (Sat-Sun)",
|
"key": "Weekends (Sat-Sun)",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:110"
|
"../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:172"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TACHYON\n"
|
"Project-Id-Version: TACHYON\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-08-20 19:26+0300\n"
|
"POT-Creation-Date: 2026-08-21 02:02+0300\n"
|
||||||
"PO-Revision-Date: 2026-08-20 19:26+0300\n"
|
"PO-Revision-Date: 2026-08-21 02:02+0300\n"
|
||||||
"Last-Translator: Dushnilin <dushnilin@gmail.com>\n"
|
"Last-Translator: Dushnilin <dushnilin@gmail.com>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
"Language: \n"
|
"Language: \n"
|
||||||
@@ -105,7 +105,7 @@ msgstr ""
|
|||||||
msgid "Action"
|
msgid "Action"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:348
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:441
|
||||||
msgid "Action Mode"
|
msgid "Action Mode"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -118,13 +118,13 @@ msgstr ""
|
|||||||
msgid "Active"
|
msgid "Active"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:260
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:353
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:280
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:373
|
||||||
msgid "Active (Allowed)"
|
msgid "Active (Allowed)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:260
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:353
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:280
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:373
|
||||||
msgid "Active (Blocking)"
|
msgid "Active (Blocking)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -223,6 +223,10 @@ msgstr ""
|
|||||||
msgid "Administrator Chat IDs"
|
msgid "Administrator Chat IDs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:73
|
||||||
|
msgid "Adult content"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/tachyon/tabs/dashboard/partials/renderAdvancedSettings.ts:595
|
#: src/tachyon/tabs/dashboard/partials/renderAdvancedSettings.ts:595
|
||||||
msgid "Advanced self-healing features. Requires Watchdog to be enabled."
|
msgid "Advanced self-healing features. Requires Watchdog to be enabled."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -327,8 +331,8 @@ msgstr ""
|
|||||||
msgid "All checks passed — Telegram bot should work correctly"
|
msgid "All checks passed — Telegram bot should work correctly"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:139
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:201
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:159
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:221
|
||||||
msgid "All devices"
|
msgid "All devices"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -336,12 +340,12 @@ msgstr ""
|
|||||||
msgid "All except selected"
|
msgid "All except selected"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:169
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:231
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:194
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:256
|
||||||
msgid "All Internet"
|
msgid "All Internet"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:320
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:413
|
||||||
msgid "All Internet (Complete internet cutoff)"
|
msgid "All Internet (Complete internet cutoff)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -372,12 +376,12 @@ msgstr ""
|
|||||||
msgid "All traffic from these IP addresses will be routed through the section unconditionally, ignoring all other conditions."
|
msgid "All traffic from these IP addresses will be routed through the section unconditionally, ignoring all other conditions."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:354
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:447
|
||||||
msgid "Allow / Enable ONLY in scheduled hours (White period)"
|
msgid "Allow / Enable ONLY in scheduled hours (White period)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:206
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:268
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:212
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:274
|
||||||
msgid "Allow in interval"
|
msgid "Allow in interval"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -385,6 +389,18 @@ msgstr ""
|
|||||||
msgid "Allow Insecure TLS"
|
msgid "Allow Insecure TLS"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:314
|
||||||
|
msgid "Allow only"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:587
|
||||||
|
msgid "Allow only listed sites (Whitelist)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:330
|
||||||
|
msgid "Allow only:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:5332
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:5332
|
||||||
msgid "Allowed domain prefixes are full:, keyword:, and regex:"
|
msgid "Allowed domain prefixes are full:, keyword:, and regex:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -563,7 +579,7 @@ msgstr ""
|
|||||||
msgid "Bearer Auth Token"
|
msgid "Bearer Auth Token"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:361
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:454
|
||||||
msgid "Beginning of the schedule interval (e.g. 22:00)"
|
msgid "Beginning of the schedule interval (e.g. 22:00)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -576,12 +592,20 @@ msgstr ""
|
|||||||
msgid "BitTorrent / P2P"
|
msgid "BitTorrent / P2P"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:353
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:315
|
||||||
|
msgid "Block"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:446
|
||||||
msgid "Block / Disable in scheduled hours (Standard)"
|
msgid "Block / Disable in scheduled hours (Standard)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:208
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:593
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:212
|
msgid "Block at DNS level"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:270
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:274
|
||||||
msgid "Block in interval"
|
msgid "Block in interval"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -589,6 +613,26 @@ msgstr ""
|
|||||||
msgid "Block internet access or specific proxy sections for individual devices based on time and days."
|
msgid "Block internet access or specific proxy sections for individual devices based on time and days."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:586
|
||||||
|
msgid "Block listed sites (Standard)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:330
|
||||||
|
msgid "Block:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:582
|
||||||
|
msgid "Block: deny the listed sites. Allow only (whitelist): deny everything except the listed sites. Whitelist mode requires DNS-level blocking and applies to the schedule window."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:303
|
||||||
|
msgid "Blocked Sites"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:492
|
||||||
|
msgid "Blocked Sites (Domains)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8905
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8905
|
||||||
#: src/tachyon/tabs/diagnostic/checks/runDnsCheck.ts:57
|
#: src/tachyon/tabs/diagnostic/checks/runDnsCheck.ts:57
|
||||||
msgid "Bootstrap DNS"
|
msgid "Bootstrap DNS"
|
||||||
@@ -861,17 +905,17 @@ msgstr ""
|
|||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8845
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8845
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9323
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9323
|
||||||
#: src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:10
|
|
||||||
#: src/tachyon/tabs/diagnostic/helpers/getMeta.ts:26
|
#: src/tachyon/tabs/diagnostic/helpers/getMeta.ts:26
|
||||||
|
#: src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:10
|
||||||
msgid "Checks failed"
|
msgid "Checks failed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8834
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8834
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9280
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9280
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9334
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9334
|
||||||
|
#: src/tachyon/tabs/diagnostic/helpers/getMeta.ts:13
|
||||||
#: src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:23
|
#: src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:23
|
||||||
#: src/tachyon/tabs/diagnostic/checks/runFakeIPCheck.ts:43
|
#: src/tachyon/tabs/diagnostic/checks/runFakeIPCheck.ts:43
|
||||||
#: src/tachyon/tabs/diagnostic/helpers/getMeta.ts:13
|
|
||||||
msgid "Checks passed"
|
msgid "Checks passed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -888,7 +932,7 @@ msgstr ""
|
|||||||
msgid "Choose Hosts File..."
|
msgid "Choose Hosts File..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:316
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:409
|
||||||
msgid "Choose whether to restrict the entire internet or only specific Tachyon routing sections."
|
msgid "Choose whether to restrict the entire internet or only specific Tachyon routing sections."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -896,7 +940,7 @@ msgstr ""
|
|||||||
msgid "Choose whether to route traffic to all destinations except selected countries (Exclude) or only to selected countries (Include)."
|
msgid "Choose whether to route traffic to all destinations except selected countries (Exclude) or only to selected countries (Include)."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:328
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:421
|
||||||
msgid "Choose which routing sections to apply this schedule to."
|
msgid "Choose which routing sections to apply this schedule to."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1118,6 +1162,10 @@ msgstr ""
|
|||||||
msgid "Connectivity probe failed"
|
msgid "Connectivity probe failed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:581
|
||||||
|
msgid "Content Mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:3415
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:3415
|
||||||
msgid "Cookie packet junk size (S3)"
|
msgid "Cookie packet junk size (S3)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -1230,7 +1278,7 @@ msgstr ""
|
|||||||
msgid "Dashboard currently unavailable"
|
msgid "Dashboard currently unavailable"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:384
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:477
|
||||||
msgid "Days of Week"
|
msgid "Days of Week"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1288,7 +1336,7 @@ msgstr ""
|
|||||||
msgid "detour must be a non-empty string"
|
msgid "detour must be a non-empty string"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:132
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:194
|
||||||
msgid "Device / IP / MAC"
|
msgid "Device / IP / MAC"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1366,8 +1414,8 @@ msgstr ""
|
|||||||
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-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:250
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:343
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:277
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:370
|
||||||
msgid "Disabled"
|
msgid "Disabled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1577,6 +1625,10 @@ msgstr ""
|
|||||||
msgid "Domains automatically detected by Smart Detect or added via Telegram bot. You can manually edit or remove them here."
|
msgid "Domains automatically detected by Smart Detect or added via Telegram bot. You can manually edit or remove them here."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:493
|
||||||
|
msgid "Domains to block for the selected devices. Leave empty to block all internet. Enter one domain per line, e.g. youtube.com. Use the preset buttons to quickly add common categories."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:8301
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:8301
|
||||||
msgid "Done"
|
msgid "Done"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -1674,7 +1726,7 @@ msgstr ""
|
|||||||
msgid "e.g. google.com, 1.1.1.1, 443"
|
msgid "e.g. google.com, 1.1.1.1, 443"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:290
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:383
|
||||||
msgid "e.g. Kids Phone (Night YouTube)"
|
msgid "e.g. Kids Phone (Night YouTube)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1691,7 +1743,7 @@ msgstr ""
|
|||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:125
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:187
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:7235
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:7235
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:2618
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:2618
|
||||||
msgid "Enable"
|
msgid "Enable"
|
||||||
@@ -1825,11 +1877,11 @@ msgstr ""
|
|||||||
msgid "Enables the background watchdog process to monitor services and auto-recover on failures."
|
msgid "Enables the background watchdog process to monitor services and auto-recover on failures."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:373
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:466
|
||||||
msgid "End of the schedule interval (e.g. 08:00). Supports spans crossing midnight."
|
msgid "End of the schedule interval (e.g. 08:00). Supports spans crossing midnight."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:372
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:465
|
||||||
msgid "End Time (HH:MM)"
|
msgid "End Time (HH:MM)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1895,7 +1947,7 @@ msgstr ""
|
|||||||
msgid "Error updating lists:"
|
msgid "Error updating lists:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:98
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:160
|
||||||
msgid "Every day"
|
msgid "Every day"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -2012,12 +2064,12 @@ msgstr ""
|
|||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:16728
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:16728
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:16786
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:16786
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:16957
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:16957
|
||||||
#: src/tachyon/methods/shell/index.ts:172
|
|
||||||
#: src/tachyon/methods/shell/index.ts:179
|
|
||||||
#: src/tachyon/tabs/updates/initController.ts:631
|
#: src/tachyon/tabs/updates/initController.ts:631
|
||||||
#: src/tachyon/tabs/updates/initController.ts:632
|
#: src/tachyon/tabs/updates/initController.ts:632
|
||||||
#: src/tachyon/tabs/updates/initController.ts:707
|
#: src/tachyon/tabs/updates/initController.ts:707
|
||||||
#: src/tachyon/tabs/updates/initController.ts:920
|
#: src/tachyon/tabs/updates/initController.ts:920
|
||||||
|
#: src/tachyon/methods/shell/index.ts:172
|
||||||
|
#: src/tachyon/methods/shell/index.ts:179
|
||||||
msgid "Failed to execute"
|
msgid "Failed to execute"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -2269,6 +2321,10 @@ msgstr ""
|
|||||||
msgid "Game Console Optimizer (NAT Type 1)"
|
msgid "Game Console Optimizer (NAT Type 1)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:63
|
||||||
|
msgid "Gaming"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:2489
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:2489
|
||||||
msgid "Generate a random 16-character hexadecimal HWID"
|
msgid "Generate a random 16-character hexadecimal HWID"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -2729,6 +2785,10 @@ msgstr ""
|
|||||||
msgid "Invalid domain address"
|
msgid "Invalid domain address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:507
|
||||||
|
msgid "Invalid domain: empty prefix value"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:206
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:206
|
||||||
#: src/validators/validateSubnet.ts:10
|
#: src/validators/validateSubnet.ts:10
|
||||||
msgid "Invalid format. Use an IP address or CIDR subnet"
|
msgid "Invalid format. Use an IP address or CIDR subnet"
|
||||||
@@ -2811,7 +2871,7 @@ msgstr ""
|
|||||||
msgid "Invalid IP address"
|
msgid "Invalid IP address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:120
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:182
|
||||||
msgid "Invalid IP or MAC address. Expected e.g. 192.168.1.150 or AA:BB:CC:DD:EE:FF"
|
msgid "Invalid IP or MAC address. Expected e.g. 192.168.1.150 or AA:BB:CC:DD:EE:FF"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -2939,7 +2999,7 @@ msgstr ""
|
|||||||
msgid "Invalid SOCKS URL: parsing failed"
|
msgid "Invalid SOCKS URL: parsing failed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:47
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:109
|
||||||
msgid "Invalid time format. Expected HH:MM (e.g. 22:00)"
|
msgid "Invalid time format. Expected HH:MM (e.g. 22:00)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -3086,8 +3146,8 @@ msgstr ""
|
|||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8840
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8840
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9329
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9329
|
||||||
#: src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:17
|
|
||||||
#: src/tachyon/tabs/diagnostic/helpers/getMeta.ts:20
|
#: src/tachyon/tabs/diagnostic/helpers/getMeta.ts:20
|
||||||
|
#: src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:17
|
||||||
msgid "Issues detected"
|
msgid "Issues detected"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -3420,6 +3480,10 @@ msgstr ""
|
|||||||
msgid "Memory Usage"
|
msgid "Memory Usage"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:84
|
||||||
|
msgid "Messengers"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:2968
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:2968
|
||||||
msgid "Method"
|
msgid "Method"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -3448,7 +3512,7 @@ msgstr ""
|
|||||||
msgid "Mixed Proxy Username"
|
msgid "Mixed Proxy Username"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:200
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:262
|
||||||
msgid "Mode"
|
msgid "Mode"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -3677,8 +3741,8 @@ msgstr ""
|
|||||||
msgid "No rules use Zapret2"
|
msgid "No rules use Zapret2"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:177
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:239
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:196
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:258
|
||||||
msgid "No sections selected"
|
msgid "No sections selected"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -3697,6 +3761,8 @@ msgid "Nodes"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:12555
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:12555
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:310
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:329
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:449
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:449
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:2741
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:2741
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:3033
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:3033
|
||||||
@@ -3786,6 +3852,10 @@ msgstr ""
|
|||||||
msgid "Not set"
|
msgid "Not set"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:604
|
||||||
|
msgid "Notify in Telegram"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:2241
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:2241
|
||||||
msgid "Notify on Certificate Warnings"
|
msgid "Notify on Certificate Warnings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -4084,8 +4154,8 @@ msgid "PEM-encoded client private key"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:5187
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:5187
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:271
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:364
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:281
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:374
|
||||||
#: src/tachyon/tabs/diagnostic/diagnostic.store.ts:63
|
#: src/tachyon/tabs/diagnostic/diagnostic.store.ts:63
|
||||||
msgid "Pending"
|
msgid "Pending"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -4594,6 +4664,10 @@ msgstr ""
|
|||||||
msgid "Resume updates"
|
msgid "Resume updates"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:594
|
||||||
|
msgid "Return NXDOMAIN for blocked domains (recommended). When enabled, blocked domains are not resolved at all. When disabled, only direct connections are rejected."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:14571
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:14571
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:14619
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:14619
|
||||||
#: src/tachyon/tabs/monitoring/initController.ts:871
|
#: src/tachyon/tabs/monitoring/initController.ts:871
|
||||||
@@ -4643,7 +4717,7 @@ msgstr ""
|
|||||||
msgid "Rule"
|
msgid "Rule"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:287
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:380
|
||||||
msgid "Rule Name"
|
msgid "Rule Name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4773,7 +4847,7 @@ msgstr ""
|
|||||||
msgid "Saving…"
|
msgid "Saving…"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:216
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:278
|
||||||
msgid "Schedule"
|
msgid "Schedule"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4873,7 +4947,7 @@ msgstr ""
|
|||||||
msgid "Select a transit section"
|
msgid "Select a transit section"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:385
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:478
|
||||||
msgid "Select active days. If none selected, the rule applies every day."
|
msgid "Select active days. If none selected, the rule applies every day."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4901,7 +4975,7 @@ msgstr ""
|
|||||||
msgid "Select DNS protocol to use"
|
msgid "Select DNS protocol to use"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:297
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:390
|
||||||
msgid "Select LAN devices to apply this schedule to, or enter IP or MAC addresses manually."
|
msgid "Select LAN devices to apply this schedule to, or enter IP or MAC addresses manually."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4929,7 +5003,7 @@ msgstr ""
|
|||||||
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-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:327
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:420
|
||||||
msgid "Select Sections"
|
msgid "Select Sections"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4955,7 +5029,7 @@ msgstr ""
|
|||||||
msgid "Select the WAN interfaces to be monitored"
|
msgid "Select the WAN interfaces to be monitored"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:349
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:442
|
||||||
msgid "Select whether to disable the target during the schedule or enable it ONLY during the schedule."
|
msgid "Select whether to disable the target during the schedule or enable it ONLY during the schedule."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4996,6 +5070,10 @@ msgstr ""
|
|||||||
msgid "Send a Telegram notification if the Tachyon service is restarted by the watchdog."
|
msgid "Send a Telegram notification if the Tachyon service is restarted by the watchdog."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:605
|
||||||
|
msgid "Send a Telegram notification to admins when a blocked site is accessed. Requires the Telegram bot to be enabled."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:2216
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:2216
|
||||||
msgid "Send a Telegram notification when a URLTest group switches to a new server."
|
msgid "Send a Telegram notification when a URLTest group switches to a new server."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -5100,9 +5178,9 @@ msgstr ""
|
|||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:3410
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:3410
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:3429
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:3429
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:12323
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:12323
|
||||||
|
#: src/tachyon/tabs/diagnostic/initController.ts:604
|
||||||
#: src/tachyon/methods/shell/index.ts:422
|
#: src/tachyon/methods/shell/index.ts:422
|
||||||
#: src/tachyon/methods/shell/index.ts:443
|
#: src/tachyon/methods/shell/index.ts:443
|
||||||
#: src/tachyon/tabs/diagnostic/initController.ts:604
|
|
||||||
msgid "Service action failed"
|
msgid "Service action failed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -5144,6 +5222,10 @@ msgstr ""
|
|||||||
msgid "Settings have been reset to defaults. The page will reload."
|
msgid "Settings have been reset to defaults. The page will reload."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:93
|
||||||
|
msgid "Shopping"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:2529
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:2529
|
||||||
msgid "Show metadata on dashboard"
|
msgid "Show metadata on dashboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -5267,6 +5349,10 @@ msgstr ""
|
|||||||
msgid "Snell Version"
|
msgid "Snell Version"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:43
|
||||||
|
msgid "Social media"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:7810
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:7810
|
||||||
msgid "Sort Alphabetically"
|
msgid "Sort Alphabetically"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -5295,7 +5381,7 @@ msgstr ""
|
|||||||
msgid "Source Network Interface"
|
msgid "Source Network Interface"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:321
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:414
|
||||||
msgid "Specific Sections (Select sections below)"
|
msgid "Specific Sections (Select sections below)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -5386,7 +5472,7 @@ msgstr ""
|
|||||||
msgid "Start Tachyon"
|
msgid "Start Tachyon"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:360
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:453
|
||||||
msgid "Start Time (HH:MM)"
|
msgid "Start Time (HH:MM)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -5405,7 +5491,7 @@ msgid "Starting…"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:2424
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:2424
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:241
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:334
|
||||||
#: src/tachyon/tabs/dashboard/partials/renderAdvancedSettings.ts:465
|
#: src/tachyon/tabs/dashboard/partials/renderAdvancedSettings.ts:465
|
||||||
#: src/tachyon/tabs/dashboard/partials/renderSections.ts:666
|
#: src/tachyon/tabs/dashboard/partials/renderSections.ts:666
|
||||||
msgid "Status"
|
msgid "Status"
|
||||||
@@ -5655,15 +5741,15 @@ msgstr ""
|
|||||||
msgid "Tailscale hostname"
|
msgid "Tailscale hostname"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:163
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:225
|
||||||
msgid "Target"
|
msgid "Target"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:296
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:389
|
||||||
msgid "Target Devices (IP / MAC)"
|
msgid "Target Devices (IP / MAC)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:315
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:408
|
||||||
msgid "Target Scope"
|
msgid "Target Scope"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -5834,7 +5920,7 @@ msgstr ""
|
|||||||
msgid "Time in seconds for DNS record caching (default: 60)"
|
msgid "Time in seconds for DNS record caching (default: 60)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:43
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:105
|
||||||
msgid "Time is required (e.g. 22:00)"
|
msgid "Time is required (e.g. 22:00)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -6446,6 +6532,10 @@ msgstr ""
|
|||||||
msgid "Via country.is"
|
msgid "Via country.is"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:53
|
||||||
|
msgid "Video streaming"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:10216
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:10216
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:12485
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:12485
|
||||||
#: src/tachyon/tabs/diagnostic/initController.ts:820
|
#: src/tachyon/tabs/diagnostic/initController.ts:820
|
||||||
@@ -6524,11 +6614,11 @@ msgstr ""
|
|||||||
msgid "Wednesday"
|
msgid "Wednesday"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:106
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:168
|
||||||
msgid "Weekdays (Mon-Fri)"
|
msgid "Weekdays (Mon-Fri)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:110
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:172
|
||||||
msgid "Weekends (Sat-Sun)"
|
msgid "Weekends (Sat-Sun)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TACHYON\n"
|
"Project-Id-Version: TACHYON\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-08-20 22:26+0300\n"
|
"POT-Creation-Date: 2026-08-21 05:02+0300\n"
|
||||||
"PO-Revision-Date: 2026-08-20 22:26+0300\n"
|
"PO-Revision-Date: 2026-08-21 05:02+0300\n"
|
||||||
"Last-Translator: Dushnilin\n"
|
"Last-Translator: Dushnilin\n"
|
||||||
"Language-Team: none\n"
|
"Language-Team: none\n"
|
||||||
"Language: ru\n"
|
"Language: ru\n"
|
||||||
@@ -146,6 +146,9 @@ msgstr "Адрес"
|
|||||||
msgid "Administrator Chat IDs"
|
msgid "Administrator Chat IDs"
|
||||||
msgstr "Chat ID администраторов"
|
msgstr "Chat ID администраторов"
|
||||||
|
|
||||||
|
msgid "Adult content"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Advanced self-healing features. Requires Watchdog to be enabled."
|
msgid "Advanced self-healing features. Requires Watchdog to be enabled."
|
||||||
msgstr "Расширенные функции самовосстановления. Требуется включённый Watchdog."
|
msgstr "Расширенные функции самовосстановления. Требуется включённый Watchdog."
|
||||||
|
|
||||||
@@ -251,6 +254,15 @@ msgstr "Разрешено в интервале"
|
|||||||
msgid "Allow Insecure TLS"
|
msgid "Allow Insecure TLS"
|
||||||
msgstr "Разрешить небезопасный TLS"
|
msgstr "Разрешить небезопасный TLS"
|
||||||
|
|
||||||
|
msgid "Allow only"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Allow only listed sites (Whitelist)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Allow only:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Allowed domain prefixes are full:, keyword:, and regex:"
|
msgid "Allowed domain prefixes are full:, keyword:, and regex:"
|
||||||
msgstr "Допустимые префиксы доменов: full:, keyword:, и regex:"
|
msgstr "Допустимые префиксы доменов: full:, keyword:, и regex:"
|
||||||
|
|
||||||
@@ -380,15 +392,36 @@ msgstr "Беларусь (by)"
|
|||||||
msgid "BitTorrent / P2P"
|
msgid "BitTorrent / P2P"
|
||||||
msgstr "BitTorrent / P2P"
|
msgstr "BitTorrent / P2P"
|
||||||
|
|
||||||
|
msgid "Block"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Block / Disable in scheduled hours (Standard)"
|
msgid "Block / Disable in scheduled hours (Standard)"
|
||||||
msgstr "Блокировать / Отключать в указанные часы (Стандарт)"
|
msgstr "Блокировать / Отключать в указанные часы (Стандарт)"
|
||||||
|
|
||||||
|
msgid "Block at DNS level"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Block in interval"
|
msgid "Block in interval"
|
||||||
msgstr "Блокируется в интервале"
|
msgstr "Блокируется в интервале"
|
||||||
|
|
||||||
msgid "Block internet access or specific proxy sections for individual devices based on time and days."
|
msgid "Block internet access or specific proxy sections for individual devices based on time and days."
|
||||||
msgstr "Блокировка доступа в интернет или определенных секций маршрутизации для отдельных устройств по времени и дням недели."
|
msgstr "Блокировка доступа в интернет или определенных секций маршрутизации для отдельных устройств по времени и дням недели."
|
||||||
|
|
||||||
|
msgid "Block listed sites (Standard)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Block:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Block: deny the listed sites. Allow only (whitelist): deny everything except the listed sites. Whitelist mode requires DNS-level blocking and applies to the schedule window."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Blocked Sites"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Blocked Sites (Domains)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Bootstrap DNS"
|
msgid "Bootstrap DNS"
|
||||||
msgstr "Bootstrap DNS"
|
msgstr "Bootstrap DNS"
|
||||||
|
|
||||||
@@ -686,6 +719,9 @@ msgstr "Подключения недоступны"
|
|||||||
msgid "Connectivity probe failed"
|
msgid "Connectivity probe failed"
|
||||||
msgstr "Проверка соединения не прошла"
|
msgstr "Проверка соединения не прошла"
|
||||||
|
|
||||||
|
msgid "Content Mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Cookie packet junk size (S3)"
|
msgid "Cookie packet junk size (S3)"
|
||||||
msgstr "Размер мусора в пакете cookie (S3)"
|
msgstr "Размер мусора в пакете cookie (S3)"
|
||||||
|
|
||||||
@@ -989,6 +1025,9 @@ msgstr "Домены"
|
|||||||
msgid "Domains automatically detected by Smart Detect or added via Telegram bot. You can manually edit or remove them here."
|
msgid "Domains automatically detected by Smart Detect or added via Telegram bot. You can manually edit or remove them here."
|
||||||
msgstr "Домены, автоматически определённые Smart Detect или добавленные через Telegram-бота. Вы можете вручную отредактировать или удалить их здесь."
|
msgstr "Домены, автоматически определённые Smart Detect или добавленные через Telegram-бота. Вы можете вручную отредактировать или удалить их здесь."
|
||||||
|
|
||||||
|
msgid "Domains to block for the selected devices. Leave empty to block all internet. Enter one domain per line, e.g. youtube.com. Use the preset buttons to quickly add common categories."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Done"
|
msgid "Done"
|
||||||
msgstr "Готово"
|
msgstr "Готово"
|
||||||
|
|
||||||
@@ -1433,6 +1472,9 @@ msgstr "IP игровых консолей"
|
|||||||
msgid "Game Console Optimizer (NAT Type 1)"
|
msgid "Game Console Optimizer (NAT Type 1)"
|
||||||
msgstr "Оптимизатор игровых консолей (NAT Type 1)"
|
msgstr "Оптимизатор игровых консолей (NAT Type 1)"
|
||||||
|
|
||||||
|
msgid "Gaming"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Generate a random 16-character hexadecimal HWID"
|
msgid "Generate a random 16-character hexadecimal HWID"
|
||||||
msgstr "Сгенерировать случайный 16-символьный шестнадцатеричный HWID"
|
msgstr "Сгенерировать случайный 16-символьный шестнадцатеричный HWID"
|
||||||
|
|
||||||
@@ -1736,6 +1778,9 @@ msgstr "Неверный порт DNS-сервера"
|
|||||||
msgid "Invalid domain address"
|
msgid "Invalid domain address"
|
||||||
msgstr "Неверный домен"
|
msgstr "Неверный домен"
|
||||||
|
|
||||||
|
msgid "Invalid domain: empty prefix value"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Invalid format. Use an IP address or CIDR subnet"
|
msgid "Invalid format. Use an IP address or CIDR subnet"
|
||||||
msgstr "Неверный формат. Используйте IP-адрес или подсеть CIDR"
|
msgstr "Неверный формат. Используйте IP-адрес или подсеть CIDR"
|
||||||
|
|
||||||
@@ -2168,6 +2213,9 @@ msgstr "Максимальное время ожидания разрешени
|
|||||||
msgid "Memory Usage"
|
msgid "Memory Usage"
|
||||||
msgstr "Использование памяти"
|
msgstr "Использование памяти"
|
||||||
|
|
||||||
|
msgid "Messengers"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Method"
|
msgid "Method"
|
||||||
msgstr "Метод"
|
msgstr "Метод"
|
||||||
|
|
||||||
@@ -2378,6 +2426,9 @@ msgstr "Не запущено"
|
|||||||
msgid "Not set"
|
msgid "Not set"
|
||||||
msgstr "Не задано"
|
msgstr "Не задано"
|
||||||
|
|
||||||
|
msgid "Notify in Telegram"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Notify on Certificate Warnings"
|
msgid "Notify on Certificate Warnings"
|
||||||
msgstr "Уведомлять о предупреждениях сертификатов"
|
msgstr "Уведомлять о предупреждениях сертификатов"
|
||||||
|
|
||||||
@@ -2909,6 +2960,9 @@ msgstr "Восстановление прямого интернета (оста
|
|||||||
msgid "Resume updates"
|
msgid "Resume updates"
|
||||||
msgstr "Продолжить обновление"
|
msgstr "Продолжить обновление"
|
||||||
|
|
||||||
|
msgid "Return NXDOMAIN for blocked domains (recommended). When enabled, blocked domains are not resolved at all. When disabled, only direct connections are rejected."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Route"
|
msgid "Route"
|
||||||
msgstr "Маршрут"
|
msgstr "Маршрут"
|
||||||
|
|
||||||
@@ -3176,6 +3230,9 @@ msgstr "Отправлять уведомление в Telegram, если SSL/TL
|
|||||||
msgid "Send a Telegram notification if the Tachyon service is restarted by the watchdog."
|
msgid "Send a Telegram notification if the Tachyon service is restarted by the watchdog."
|
||||||
msgstr "Отправлять уведомление в Telegram, если сервис Tachyon перезапущен watchdog."
|
msgstr "Отправлять уведомление в Telegram, если сервис Tachyon перезапущен watchdog."
|
||||||
|
|
||||||
|
msgid "Send a Telegram notification to admins when a blocked site is accessed. Requires the Telegram bot to be enabled."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Send a Telegram notification when a URLTest group switches to a new server."
|
msgid "Send a Telegram notification when a URLTest group switches to a new server."
|
||||||
msgstr "Отправлять уведомление в Telegram при переключении группы URLTest на новый сервер."
|
msgstr "Отправлять уведомление в Telegram при переключении группы URLTest на новый сервер."
|
||||||
|
|
||||||
@@ -3266,6 +3323,9 @@ msgstr "Настройки"
|
|||||||
msgid "Settings have been reset to defaults. The page will reload."
|
msgid "Settings have been reset to defaults. The page will reload."
|
||||||
msgstr "Настройки сброшены к значениям по умолчанию. Страница будет перезагружена."
|
msgstr "Настройки сброшены к значениям по умолчанию. Страница будет перезагружена."
|
||||||
|
|
||||||
|
msgid "Shopping"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Show metadata on dashboard"
|
msgid "Show metadata on dashboard"
|
||||||
msgstr "Показывать метаданные на дашборде"
|
msgstr "Показывать метаданные на дашборде"
|
||||||
|
|
||||||
@@ -3350,6 +3410,9 @@ msgstr "Снапшот восстановлен. Сервис перезапус
|
|||||||
msgid "Snell Version"
|
msgid "Snell Version"
|
||||||
msgstr "Версия Snell"
|
msgstr "Версия Snell"
|
||||||
|
|
||||||
|
msgid "Social media"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Sort Alphabetically"
|
msgid "Sort Alphabetically"
|
||||||
msgstr "Сортировать по алфавиту"
|
msgstr "Сортировать по алфавиту"
|
||||||
|
|
||||||
@@ -4061,6 +4124,9 @@ msgstr "Проверка готовности роутера и служб..."
|
|||||||
msgid "Via country.is"
|
msgid "Via country.is"
|
||||||
msgstr "Через country.is"
|
msgstr "Через country.is"
|
||||||
|
|
||||||
|
msgid "Video streaming"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "View logs"
|
msgid "View logs"
|
||||||
msgstr "Посмотреть логи"
|
msgstr "Посмотреть логи"
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,68 @@ const DAY_INDEX_MAP = {
|
|||||||
6: "saturday",
|
6: "saturday",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const DOMAIN_PRESETS = {
|
||||||
|
social: {
|
||||||
|
label: _("Social media"),
|
||||||
|
icon: "📱",
|
||||||
|
domains: [
|
||||||
|
"facebook.com", "instagram.com", "tiktok.com", "twitter.com", "x.com",
|
||||||
|
"vk.com", "snapchat.com", "reddit.com", "discord.com", "discord.gg",
|
||||||
|
"twitch.tv", "pinterest.com", "telegram.org", "t.me", "whatsapp.com",
|
||||||
|
"signal.org", "wechat.com", "youtube.com", "tumblr.com",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
video: {
|
||||||
|
label: _("Video streaming"),
|
||||||
|
icon: "🎬",
|
||||||
|
domains: [
|
||||||
|
"youtube.com", "youtu.be", "googlevideo.com", "ytimg.com",
|
||||||
|
"netflix.com", "primevideo.com", "hulu.com", "disneyplus.com",
|
||||||
|
"hbomax.com", "okko.tv", "ivi.ru", "kinopoisk.ru",
|
||||||
|
"twitch.tv", "vimeo.com", "dailymotion.com", "rutube.ru",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
gaming: {
|
||||||
|
label: _("Gaming"),
|
||||||
|
icon: "🎮",
|
||||||
|
domains: [
|
||||||
|
"steampowered.com", "steamcommunity.com", "epicgames.com",
|
||||||
|
"roblox.com", "fortnite.com", "xbox.com", "playstation.com",
|
||||||
|
"battle.net", "ea.com", "ubisoft.com", "riotgames.com",
|
||||||
|
"minecraft.net", "origin.com", "discord.com", "discord.gg",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
adult: {
|
||||||
|
label: _("Adult content"),
|
||||||
|
icon: "🔞",
|
||||||
|
domains: [
|
||||||
|
"pornhub.com", "xvideos.com", "xhamster.com", "xnxx.com",
|
||||||
|
"onlyfans.com", "stripchat.com", "chaturbate.com",
|
||||||
|
"youporn.com", "redtube.com", "tubegalore.com",
|
||||||
|
"porntrex.com", "pornhd.com", "nudevista.com",
|
||||||
|
"porn.com", "spankbang.com", "eporner.com",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
messengers: {
|
||||||
|
label: _("Messengers"),
|
||||||
|
icon: "💬",
|
||||||
|
domains: [
|
||||||
|
"telegram.org", "t.me", "whatsapp.com", "wa.me", "viber.com",
|
||||||
|
"signal.org", "wechat.com", "qq.com", "icq.com", "discord.com",
|
||||||
|
"discord.gg", "skype.com", "zoom.us", "slack.com", "teams.microsoft.com",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
shopping: {
|
||||||
|
label: _("Shopping"),
|
||||||
|
icon: "🛒",
|
||||||
|
domains: [
|
||||||
|
"amazon.com", "ebay.com", "aliexpress.com", "ozon.ru",
|
||||||
|
"wildberries.ru", "wb.ru", "yandex.market", "market.yandex.ru",
|
||||||
|
"avito.ru", "lamoda.ru", "shein.com", "temu.com", "wish.com",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
function validateTime(sectionId, value) {
|
function validateTime(sectionId, value) {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return _("Time is required (e.g. 22:00)");
|
return _("Time is required (e.g. 22:00)");
|
||||||
@@ -237,6 +299,37 @@ function createParentalContent(section) {
|
|||||||
return `${s} - ${e}, ${days}`;
|
return `${s} - ${e}, ${days}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Blocked sites column in table
|
||||||
|
o = section.option(form.DummyValue, "_sites_display", _("Blocked Sites"));
|
||||||
|
o.rawhtml = true;
|
||||||
|
o.modalonly = false;
|
||||||
|
o.cfgvalue = function (sectionId) {
|
||||||
|
const domains = normalizeListValues(uci.get(UCI_PACKAGE, sectionId, "blocked_domains"));
|
||||||
|
const mode = uci.get(UCI_PACKAGE, sectionId, "mode") || "block";
|
||||||
|
if (domains.length === 0) {
|
||||||
|
return '<span style="opacity:0.5;">' + _("None") + "</span>";
|
||||||
|
}
|
||||||
|
const modeBadge =
|
||||||
|
mode === "allow"
|
||||||
|
? '<span style="color:#68d391;font-weight:600;">🟢 ' + _("Allow only") + "</span>"
|
||||||
|
: '<span style="color:#fc8181;font-weight:600;">🚫 ' + _("Block") + "</span>";
|
||||||
|
const badges = domains
|
||||||
|
.map(
|
||||||
|
(d) =>
|
||||||
|
'<span class="badge" style="background:#2d3748;color:#f687b3;padding:2px 6px;border-radius:4px;font-size:11px;font-family:monospace;margin-right:4px;border:1px solid rgba(246,135,179,0.3);display:inline-block;margin-bottom:2px;">' +
|
||||||
|
d +
|
||||||
|
"</span>",
|
||||||
|
)
|
||||||
|
.join("");
|
||||||
|
return "<div>" + modeBadge + "<br>" + badges + "</div>";
|
||||||
|
};
|
||||||
|
o.textvalue = function (sectionId) {
|
||||||
|
const domains = normalizeListValues(uci.get(UCI_PACKAGE, sectionId, "blocked_domains"));
|
||||||
|
const mode = uci.get(UCI_PACKAGE, sectionId, "mode") || "block";
|
||||||
|
if (domains.length === 0) return _("None");
|
||||||
|
return (mode === "allow" ? _("Allow only: ") : _("Block: ")) + domains.join(", ");
|
||||||
|
};
|
||||||
|
|
||||||
// Live status badge in table
|
// Live status badge in table
|
||||||
o = section.option(form.DummyValue, "_live_status", _("Status"));
|
o = section.option(form.DummyValue, "_live_status", _("Status"));
|
||||||
o.rawhtml = true;
|
o.rawhtml = true;
|
||||||
@@ -389,6 +482,131 @@ function createParentalContent(section) {
|
|||||||
Object.entries(DAY_LABELS).forEach(([key, label]) => {
|
Object.entries(DAY_LABELS).forEach(([key, label]) => {
|
||||||
o.value(key, label);
|
o.value(key, label);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ─── Content blocking (domains) ────────────────────────────────────────────
|
||||||
|
|
||||||
|
// Blocked domains with quick presets
|
||||||
|
o = section.option(
|
||||||
|
form.TextValue,
|
||||||
|
"blocked_domains",
|
||||||
|
_("Blocked Sites (Domains)"),
|
||||||
|
_("Domains to block for the selected devices. Leave empty to block all internet. Enter one domain per line, e.g. youtube.com. Use the preset buttons to quickly add common categories."),
|
||||||
|
);
|
||||||
|
o.modalonly = true;
|
||||||
|
o.rmempty = true;
|
||||||
|
o.rows = 6;
|
||||||
|
o.wrap = "soft";
|
||||||
|
o.textarea = true;
|
||||||
|
o.placeholder = "youtube.com\ngooglevideo.com";
|
||||||
|
o.validate = function (sectionId, value) {
|
||||||
|
if (!value) return true;
|
||||||
|
const lines = `${value}`.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
|
||||||
|
for (const line of lines) {
|
||||||
|
const clean = line.replace(/^(full:|keyword:|regex:)/, "");
|
||||||
|
if (/^(full:|keyword:|regex:)/.test(line) && !clean) {
|
||||||
|
return _("Invalid domain: empty prefix value");
|
||||||
|
}
|
||||||
|
if (/^regex:/.test(line)) continue;
|
||||||
|
if (!/^([a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/.test(clean)) {
|
||||||
|
return _("Invalid domain: " + line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
o.write = function (sectionId, value) {
|
||||||
|
const lines = `${value || ""}`.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
|
||||||
|
const existingList = normalizeListValues(uci.get(UCI_PACKAGE, sectionId, "blocked_domains"));
|
||||||
|
for (const d of lines) {
|
||||||
|
if (!existingList.includes(d)) {
|
||||||
|
uci.add_list(UCI_PACKAGE, sectionId, "blocked_domains", d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const d of existingList) {
|
||||||
|
if (!lines.includes(d)) {
|
||||||
|
uci.remove_list(UCI_PACKAGE, sectionId, "blocked_domains", d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
o.load = function (sectionId) {
|
||||||
|
return normalizeListValues(uci.get(UCI_PACKAGE, sectionId, "blocked_domains")).join("\n");
|
||||||
|
};
|
||||||
|
o.remove = function (sectionId) {
|
||||||
|
uci.unset(UCI_PACKAGE, sectionId, "blocked_domains");
|
||||||
|
};
|
||||||
|
o.renderWidget = function (sectionId, optionIndex, cfgvalue) {
|
||||||
|
const container = E("div", { style: "width:100%;" });
|
||||||
|
|
||||||
|
// Preset buttons row
|
||||||
|
const presetRow = E("div", { style: "margin-bottom:6px;display:flex;flex-wrap:wrap;gap:4px;" });
|
||||||
|
Object.entries(DOMAIN_PRESETS).forEach(([key, preset]) => {
|
||||||
|
const btn = E(
|
||||||
|
"button",
|
||||||
|
{
|
||||||
|
class: "cbi-button cbi-button-neutral",
|
||||||
|
type: "button",
|
||||||
|
style: "padding:2px 8px;font-size:11px;",
|
||||||
|
title: preset.domains.join(", "),
|
||||||
|
},
|
||||||
|
preset.icon + " " + preset.label,
|
||||||
|
);
|
||||||
|
btn.addEventListener("click", function () {
|
||||||
|
const textarea = container.querySelector("textarea");
|
||||||
|
if (!textarea) return;
|
||||||
|
const current = textarea.value.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
|
||||||
|
const merged = current.slice();
|
||||||
|
for (const d of preset.domains) {
|
||||||
|
if (!merged.includes(d)) merged.push(d);
|
||||||
|
}
|
||||||
|
textarea.value = merged.join("\n");
|
||||||
|
});
|
||||||
|
presetRow.appendChild(btn);
|
||||||
|
});
|
||||||
|
container.appendChild(presetRow);
|
||||||
|
|
||||||
|
const textarea = E("textarea", {
|
||||||
|
id: `cbid.tachyon.${sectionId}.blocked_domains`,
|
||||||
|
class: "cbi-input-textarea",
|
||||||
|
style: "width:100%;min-height:110px;",
|
||||||
|
placeholder: "youtube.com\ngooglevideo.com",
|
||||||
|
});
|
||||||
|
if (cfgvalue) textarea.value = cfgvalue;
|
||||||
|
container.appendChild(textarea);
|
||||||
|
return container;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Content mode: block listed vs allow only listed (whitelist)
|
||||||
|
o = section.option(
|
||||||
|
form.ListValue,
|
||||||
|
"mode",
|
||||||
|
_("Content Mode"),
|
||||||
|
_("Block: deny the listed sites. Allow only (whitelist): deny everything except the listed sites. Whitelist mode requires DNS-level blocking and applies to the schedule window."),
|
||||||
|
);
|
||||||
|
o.modalonly = true;
|
||||||
|
o.default = "block";
|
||||||
|
o.value("block", _("Block listed sites (Standard)"));
|
||||||
|
o.value("allow", _("Allow only listed sites (Whitelist)"));
|
||||||
|
|
||||||
|
// DNS-level blocking
|
||||||
|
o = section.option(
|
||||||
|
form.Flag,
|
||||||
|
"dns_level",
|
||||||
|
_("Block at DNS level"),
|
||||||
|
_("Return NXDOMAIN for blocked domains (recommended). When enabled, blocked domains are not resolved at all. When disabled, only direct connections are rejected."),
|
||||||
|
);
|
||||||
|
o.modalonly = true;
|
||||||
|
o.default = "1";
|
||||||
|
o.rmempty = false;
|
||||||
|
|
||||||
|
// Telegram notification
|
||||||
|
o = section.option(
|
||||||
|
form.Flag,
|
||||||
|
"notify",
|
||||||
|
_("Notify in Telegram"),
|
||||||
|
_("Send a Telegram notification to admins when a blocked site is accessed. Requires the Telegram bot to be enabled."),
|
||||||
|
);
|
||||||
|
o.modalonly = true;
|
||||||
|
o.default = "0";
|
||||||
|
o.rmempty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EntryPoint = {
|
const EntryPoint = {
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TACHYON\n"
|
"Project-Id-Version: TACHYON\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-08-20 22:26+0300\n"
|
"POT-Creation-Date: 2026-08-21 05:02+0300\n"
|
||||||
"PO-Revision-Date: 2026-08-20 22:26+0300\n"
|
"PO-Revision-Date: 2026-08-21 05:02+0300\n"
|
||||||
"Last-Translator: Dushnilin\n"
|
"Last-Translator: Dushnilin\n"
|
||||||
"Language-Team: none\n"
|
"Language-Team: none\n"
|
||||||
"Language: ru\n"
|
"Language: ru\n"
|
||||||
@@ -146,6 +146,9 @@ msgstr "Адрес"
|
|||||||
msgid "Administrator Chat IDs"
|
msgid "Administrator Chat IDs"
|
||||||
msgstr "Chat ID администраторов"
|
msgstr "Chat ID администраторов"
|
||||||
|
|
||||||
|
msgid "Adult content"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Advanced self-healing features. Requires Watchdog to be enabled."
|
msgid "Advanced self-healing features. Requires Watchdog to be enabled."
|
||||||
msgstr "Расширенные функции самовосстановления. Требуется включённый Watchdog."
|
msgstr "Расширенные функции самовосстановления. Требуется включённый Watchdog."
|
||||||
|
|
||||||
@@ -251,6 +254,15 @@ msgstr "Разрешено в интервале"
|
|||||||
msgid "Allow Insecure TLS"
|
msgid "Allow Insecure TLS"
|
||||||
msgstr "Разрешить небезопасный TLS"
|
msgstr "Разрешить небезопасный TLS"
|
||||||
|
|
||||||
|
msgid "Allow only"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Allow only listed sites (Whitelist)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Allow only:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Allowed domain prefixes are full:, keyword:, and regex:"
|
msgid "Allowed domain prefixes are full:, keyword:, and regex:"
|
||||||
msgstr "Допустимые префиксы доменов: full:, keyword:, и regex:"
|
msgstr "Допустимые префиксы доменов: full:, keyword:, и regex:"
|
||||||
|
|
||||||
@@ -380,15 +392,36 @@ msgstr "Беларусь (by)"
|
|||||||
msgid "BitTorrent / P2P"
|
msgid "BitTorrent / P2P"
|
||||||
msgstr "BitTorrent / P2P"
|
msgstr "BitTorrent / P2P"
|
||||||
|
|
||||||
|
msgid "Block"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Block / Disable in scheduled hours (Standard)"
|
msgid "Block / Disable in scheduled hours (Standard)"
|
||||||
msgstr "Блокировать / Отключать в указанные часы (Стандарт)"
|
msgstr "Блокировать / Отключать в указанные часы (Стандарт)"
|
||||||
|
|
||||||
|
msgid "Block at DNS level"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Block in interval"
|
msgid "Block in interval"
|
||||||
msgstr "Блокируется в интервале"
|
msgstr "Блокируется в интервале"
|
||||||
|
|
||||||
msgid "Block internet access or specific proxy sections for individual devices based on time and days."
|
msgid "Block internet access or specific proxy sections for individual devices based on time and days."
|
||||||
msgstr "Блокировка доступа в интернет или определенных секций маршрутизации для отдельных устройств по времени и дням недели."
|
msgstr "Блокировка доступа в интернет или определенных секций маршрутизации для отдельных устройств по времени и дням недели."
|
||||||
|
|
||||||
|
msgid "Block listed sites (Standard)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Block:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Block: deny the listed sites. Allow only (whitelist): deny everything except the listed sites. Whitelist mode requires DNS-level blocking and applies to the schedule window."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Blocked Sites"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Blocked Sites (Domains)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Bootstrap DNS"
|
msgid "Bootstrap DNS"
|
||||||
msgstr "Bootstrap DNS"
|
msgstr "Bootstrap DNS"
|
||||||
|
|
||||||
@@ -686,6 +719,9 @@ msgstr "Подключения недоступны"
|
|||||||
msgid "Connectivity probe failed"
|
msgid "Connectivity probe failed"
|
||||||
msgstr "Проверка соединения не прошла"
|
msgstr "Проверка соединения не прошла"
|
||||||
|
|
||||||
|
msgid "Content Mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Cookie packet junk size (S3)"
|
msgid "Cookie packet junk size (S3)"
|
||||||
msgstr "Размер мусора в пакете cookie (S3)"
|
msgstr "Размер мусора в пакете cookie (S3)"
|
||||||
|
|
||||||
@@ -989,6 +1025,9 @@ msgstr "Домены"
|
|||||||
msgid "Domains automatically detected by Smart Detect or added via Telegram bot. You can manually edit or remove them here."
|
msgid "Domains automatically detected by Smart Detect or added via Telegram bot. You can manually edit or remove them here."
|
||||||
msgstr "Домены, автоматически определённые Smart Detect или добавленные через Telegram-бота. Вы можете вручную отредактировать или удалить их здесь."
|
msgstr "Домены, автоматически определённые Smart Detect или добавленные через Telegram-бота. Вы можете вручную отредактировать или удалить их здесь."
|
||||||
|
|
||||||
|
msgid "Domains to block for the selected devices. Leave empty to block all internet. Enter one domain per line, e.g. youtube.com. Use the preset buttons to quickly add common categories."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Done"
|
msgid "Done"
|
||||||
msgstr "Готово"
|
msgstr "Готово"
|
||||||
|
|
||||||
@@ -1433,6 +1472,9 @@ msgstr "IP игровых консолей"
|
|||||||
msgid "Game Console Optimizer (NAT Type 1)"
|
msgid "Game Console Optimizer (NAT Type 1)"
|
||||||
msgstr "Оптимизатор игровых консолей (NAT Type 1)"
|
msgstr "Оптимизатор игровых консолей (NAT Type 1)"
|
||||||
|
|
||||||
|
msgid "Gaming"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Generate a random 16-character hexadecimal HWID"
|
msgid "Generate a random 16-character hexadecimal HWID"
|
||||||
msgstr "Сгенерировать случайный 16-символьный шестнадцатеричный HWID"
|
msgstr "Сгенерировать случайный 16-символьный шестнадцатеричный HWID"
|
||||||
|
|
||||||
@@ -1736,6 +1778,9 @@ msgstr "Неверный порт DNS-сервера"
|
|||||||
msgid "Invalid domain address"
|
msgid "Invalid domain address"
|
||||||
msgstr "Неверный домен"
|
msgstr "Неверный домен"
|
||||||
|
|
||||||
|
msgid "Invalid domain: empty prefix value"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Invalid format. Use an IP address or CIDR subnet"
|
msgid "Invalid format. Use an IP address or CIDR subnet"
|
||||||
msgstr "Неверный формат. Используйте IP-адрес или подсеть CIDR"
|
msgstr "Неверный формат. Используйте IP-адрес или подсеть CIDR"
|
||||||
|
|
||||||
@@ -2168,6 +2213,9 @@ msgstr "Максимальное время ожидания разрешени
|
|||||||
msgid "Memory Usage"
|
msgid "Memory Usage"
|
||||||
msgstr "Использование памяти"
|
msgstr "Использование памяти"
|
||||||
|
|
||||||
|
msgid "Messengers"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Method"
|
msgid "Method"
|
||||||
msgstr "Метод"
|
msgstr "Метод"
|
||||||
|
|
||||||
@@ -2378,6 +2426,9 @@ msgstr "Не запущено"
|
|||||||
msgid "Not set"
|
msgid "Not set"
|
||||||
msgstr "Не задано"
|
msgstr "Не задано"
|
||||||
|
|
||||||
|
msgid "Notify in Telegram"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Notify on Certificate Warnings"
|
msgid "Notify on Certificate Warnings"
|
||||||
msgstr "Уведомлять о предупреждениях сертификатов"
|
msgstr "Уведомлять о предупреждениях сертификатов"
|
||||||
|
|
||||||
@@ -2909,6 +2960,9 @@ msgstr "Восстановление прямого интернета (оста
|
|||||||
msgid "Resume updates"
|
msgid "Resume updates"
|
||||||
msgstr "Продолжить обновление"
|
msgstr "Продолжить обновление"
|
||||||
|
|
||||||
|
msgid "Return NXDOMAIN for blocked domains (recommended). When enabled, blocked domains are not resolved at all. When disabled, only direct connections are rejected."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Route"
|
msgid "Route"
|
||||||
msgstr "Маршрут"
|
msgstr "Маршрут"
|
||||||
|
|
||||||
@@ -3176,6 +3230,9 @@ msgstr "Отправлять уведомление в Telegram, если SSL/TL
|
|||||||
msgid "Send a Telegram notification if the Tachyon service is restarted by the watchdog."
|
msgid "Send a Telegram notification if the Tachyon service is restarted by the watchdog."
|
||||||
msgstr "Отправлять уведомление в Telegram, если сервис Tachyon перезапущен watchdog."
|
msgstr "Отправлять уведомление в Telegram, если сервис Tachyon перезапущен watchdog."
|
||||||
|
|
||||||
|
msgid "Send a Telegram notification to admins when a blocked site is accessed. Requires the Telegram bot to be enabled."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Send a Telegram notification when a URLTest group switches to a new server."
|
msgid "Send a Telegram notification when a URLTest group switches to a new server."
|
||||||
msgstr "Отправлять уведомление в Telegram при переключении группы URLTest на новый сервер."
|
msgstr "Отправлять уведомление в Telegram при переключении группы URLTest на новый сервер."
|
||||||
|
|
||||||
@@ -3266,6 +3323,9 @@ msgstr "Настройки"
|
|||||||
msgid "Settings have been reset to defaults. The page will reload."
|
msgid "Settings have been reset to defaults. The page will reload."
|
||||||
msgstr "Настройки сброшены к значениям по умолчанию. Страница будет перезагружена."
|
msgstr "Настройки сброшены к значениям по умолчанию. Страница будет перезагружена."
|
||||||
|
|
||||||
|
msgid "Shopping"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Show metadata on dashboard"
|
msgid "Show metadata on dashboard"
|
||||||
msgstr "Показывать метаданные на дашборде"
|
msgstr "Показывать метаданные на дашборде"
|
||||||
|
|
||||||
@@ -3350,6 +3410,9 @@ msgstr "Снапшот восстановлен. Сервис перезапус
|
|||||||
msgid "Snell Version"
|
msgid "Snell Version"
|
||||||
msgstr "Версия Snell"
|
msgstr "Версия Snell"
|
||||||
|
|
||||||
|
msgid "Social media"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Sort Alphabetically"
|
msgid "Sort Alphabetically"
|
||||||
msgstr "Сортировать по алфавиту"
|
msgstr "Сортировать по алфавиту"
|
||||||
|
|
||||||
@@ -4061,6 +4124,9 @@ msgstr "Проверка готовности роутера и служб..."
|
|||||||
msgid "Via country.is"
|
msgid "Via country.is"
|
||||||
msgstr "Через country.is"
|
msgstr "Через country.is"
|
||||||
|
|
||||||
|
msgid "Video streaming"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "View logs"
|
msgid "View logs"
|
||||||
msgstr "Посмотреть логи"
|
msgstr "Посмотреть логи"
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TACHYON\n"
|
"Project-Id-Version: TACHYON\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-08-20 19:26+0300\n"
|
"POT-Creation-Date: 2026-08-21 02:02+0300\n"
|
||||||
"PO-Revision-Date: 2026-08-20 19:26+0300\n"
|
"PO-Revision-Date: 2026-08-21 02:02+0300\n"
|
||||||
"Last-Translator: Dushnilin <dushnilin@gmail.com>\n"
|
"Last-Translator: Dushnilin <dushnilin@gmail.com>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
"Language: \n"
|
"Language: \n"
|
||||||
@@ -105,7 +105,7 @@ msgstr ""
|
|||||||
msgid "Action"
|
msgid "Action"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:348
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:441
|
||||||
msgid "Action Mode"
|
msgid "Action Mode"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -118,13 +118,13 @@ msgstr ""
|
|||||||
msgid "Active"
|
msgid "Active"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:260
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:353
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:280
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:373
|
||||||
msgid "Active (Allowed)"
|
msgid "Active (Allowed)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:260
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:353
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:280
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:373
|
||||||
msgid "Active (Blocking)"
|
msgid "Active (Blocking)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -223,6 +223,10 @@ msgstr ""
|
|||||||
msgid "Administrator Chat IDs"
|
msgid "Administrator Chat IDs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:73
|
||||||
|
msgid "Adult content"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/tachyon/tabs/dashboard/partials/renderAdvancedSettings.ts:595
|
#: src/tachyon/tabs/dashboard/partials/renderAdvancedSettings.ts:595
|
||||||
msgid "Advanced self-healing features. Requires Watchdog to be enabled."
|
msgid "Advanced self-healing features. Requires Watchdog to be enabled."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -327,8 +331,8 @@ msgstr ""
|
|||||||
msgid "All checks passed — Telegram bot should work correctly"
|
msgid "All checks passed — Telegram bot should work correctly"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:139
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:201
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:159
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:221
|
||||||
msgid "All devices"
|
msgid "All devices"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -336,12 +340,12 @@ msgstr ""
|
|||||||
msgid "All except selected"
|
msgid "All except selected"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:169
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:231
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:194
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:256
|
||||||
msgid "All Internet"
|
msgid "All Internet"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:320
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:413
|
||||||
msgid "All Internet (Complete internet cutoff)"
|
msgid "All Internet (Complete internet cutoff)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -372,12 +376,12 @@ msgstr ""
|
|||||||
msgid "All traffic from these IP addresses will be routed through the section unconditionally, ignoring all other conditions."
|
msgid "All traffic from these IP addresses will be routed through the section unconditionally, ignoring all other conditions."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:354
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:447
|
||||||
msgid "Allow / Enable ONLY in scheduled hours (White period)"
|
msgid "Allow / Enable ONLY in scheduled hours (White period)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:206
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:268
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:212
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:274
|
||||||
msgid "Allow in interval"
|
msgid "Allow in interval"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -385,6 +389,18 @@ msgstr ""
|
|||||||
msgid "Allow Insecure TLS"
|
msgid "Allow Insecure TLS"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:314
|
||||||
|
msgid "Allow only"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:587
|
||||||
|
msgid "Allow only listed sites (Whitelist)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:330
|
||||||
|
msgid "Allow only:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:5332
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:5332
|
||||||
msgid "Allowed domain prefixes are full:, keyword:, and regex:"
|
msgid "Allowed domain prefixes are full:, keyword:, and regex:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -563,7 +579,7 @@ msgstr ""
|
|||||||
msgid "Bearer Auth Token"
|
msgid "Bearer Auth Token"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:361
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:454
|
||||||
msgid "Beginning of the schedule interval (e.g. 22:00)"
|
msgid "Beginning of the schedule interval (e.g. 22:00)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -576,12 +592,20 @@ msgstr ""
|
|||||||
msgid "BitTorrent / P2P"
|
msgid "BitTorrent / P2P"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:353
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:315
|
||||||
|
msgid "Block"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:446
|
||||||
msgid "Block / Disable in scheduled hours (Standard)"
|
msgid "Block / Disable in scheduled hours (Standard)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:208
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:593
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:212
|
msgid "Block at DNS level"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:270
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:274
|
||||||
msgid "Block in interval"
|
msgid "Block in interval"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -589,6 +613,26 @@ msgstr ""
|
|||||||
msgid "Block internet access or specific proxy sections for individual devices based on time and days."
|
msgid "Block internet access or specific proxy sections for individual devices based on time and days."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:586
|
||||||
|
msgid "Block listed sites (Standard)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:330
|
||||||
|
msgid "Block:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:582
|
||||||
|
msgid "Block: deny the listed sites. Allow only (whitelist): deny everything except the listed sites. Whitelist mode requires DNS-level blocking and applies to the schedule window."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:303
|
||||||
|
msgid "Blocked Sites"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:492
|
||||||
|
msgid "Blocked Sites (Domains)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8905
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8905
|
||||||
#: src/tachyon/tabs/diagnostic/checks/runDnsCheck.ts:57
|
#: src/tachyon/tabs/diagnostic/checks/runDnsCheck.ts:57
|
||||||
msgid "Bootstrap DNS"
|
msgid "Bootstrap DNS"
|
||||||
@@ -861,17 +905,17 @@ msgstr ""
|
|||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8845
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8845
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9323
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9323
|
||||||
#: src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:10
|
|
||||||
#: src/tachyon/tabs/diagnostic/helpers/getMeta.ts:26
|
#: src/tachyon/tabs/diagnostic/helpers/getMeta.ts:26
|
||||||
|
#: src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:10
|
||||||
msgid "Checks failed"
|
msgid "Checks failed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8834
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8834
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9280
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9280
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9334
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9334
|
||||||
|
#: src/tachyon/tabs/diagnostic/helpers/getMeta.ts:13
|
||||||
#: src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:23
|
#: src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:23
|
||||||
#: src/tachyon/tabs/diagnostic/checks/runFakeIPCheck.ts:43
|
#: src/tachyon/tabs/diagnostic/checks/runFakeIPCheck.ts:43
|
||||||
#: src/tachyon/tabs/diagnostic/helpers/getMeta.ts:13
|
|
||||||
msgid "Checks passed"
|
msgid "Checks passed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -888,7 +932,7 @@ msgstr ""
|
|||||||
msgid "Choose Hosts File..."
|
msgid "Choose Hosts File..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:316
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:409
|
||||||
msgid "Choose whether to restrict the entire internet or only specific Tachyon routing sections."
|
msgid "Choose whether to restrict the entire internet or only specific Tachyon routing sections."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -896,7 +940,7 @@ msgstr ""
|
|||||||
msgid "Choose whether to route traffic to all destinations except selected countries (Exclude) or only to selected countries (Include)."
|
msgid "Choose whether to route traffic to all destinations except selected countries (Exclude) or only to selected countries (Include)."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:328
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:421
|
||||||
msgid "Choose which routing sections to apply this schedule to."
|
msgid "Choose which routing sections to apply this schedule to."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1118,6 +1162,10 @@ msgstr ""
|
|||||||
msgid "Connectivity probe failed"
|
msgid "Connectivity probe failed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:581
|
||||||
|
msgid "Content Mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:3415
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:3415
|
||||||
msgid "Cookie packet junk size (S3)"
|
msgid "Cookie packet junk size (S3)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -1230,7 +1278,7 @@ msgstr ""
|
|||||||
msgid "Dashboard currently unavailable"
|
msgid "Dashboard currently unavailable"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:384
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:477
|
||||||
msgid "Days of Week"
|
msgid "Days of Week"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1288,7 +1336,7 @@ msgstr ""
|
|||||||
msgid "detour must be a non-empty string"
|
msgid "detour must be a non-empty string"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:132
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:194
|
||||||
msgid "Device / IP / MAC"
|
msgid "Device / IP / MAC"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1366,8 +1414,8 @@ msgstr ""
|
|||||||
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-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:250
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:343
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:277
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:370
|
||||||
msgid "Disabled"
|
msgid "Disabled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1577,6 +1625,10 @@ msgstr ""
|
|||||||
msgid "Domains automatically detected by Smart Detect or added via Telegram bot. You can manually edit or remove them here."
|
msgid "Domains automatically detected by Smart Detect or added via Telegram bot. You can manually edit or remove them here."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:493
|
||||||
|
msgid "Domains to block for the selected devices. Leave empty to block all internet. Enter one domain per line, e.g. youtube.com. Use the preset buttons to quickly add common categories."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:8301
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:8301
|
||||||
msgid "Done"
|
msgid "Done"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -1674,7 +1726,7 @@ msgstr ""
|
|||||||
msgid "e.g. google.com, 1.1.1.1, 443"
|
msgid "e.g. google.com, 1.1.1.1, 443"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:290
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:383
|
||||||
msgid "e.g. Kids Phone (Night YouTube)"
|
msgid "e.g. Kids Phone (Night YouTube)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1691,7 +1743,7 @@ msgstr ""
|
|||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:125
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:187
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:7235
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:7235
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:2618
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:2618
|
||||||
msgid "Enable"
|
msgid "Enable"
|
||||||
@@ -1825,11 +1877,11 @@ msgstr ""
|
|||||||
msgid "Enables the background watchdog process to monitor services and auto-recover on failures."
|
msgid "Enables the background watchdog process to monitor services and auto-recover on failures."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:373
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:466
|
||||||
msgid "End of the schedule interval (e.g. 08:00). Supports spans crossing midnight."
|
msgid "End of the schedule interval (e.g. 08:00). Supports spans crossing midnight."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:372
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:465
|
||||||
msgid "End Time (HH:MM)"
|
msgid "End Time (HH:MM)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1895,7 +1947,7 @@ msgstr ""
|
|||||||
msgid "Error updating lists:"
|
msgid "Error updating lists:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:98
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:160
|
||||||
msgid "Every day"
|
msgid "Every day"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -2012,12 +2064,12 @@ msgstr ""
|
|||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:16728
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:16728
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:16786
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:16786
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:16957
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:16957
|
||||||
#: src/tachyon/methods/shell/index.ts:172
|
|
||||||
#: src/tachyon/methods/shell/index.ts:179
|
|
||||||
#: src/tachyon/tabs/updates/initController.ts:631
|
#: src/tachyon/tabs/updates/initController.ts:631
|
||||||
#: src/tachyon/tabs/updates/initController.ts:632
|
#: src/tachyon/tabs/updates/initController.ts:632
|
||||||
#: src/tachyon/tabs/updates/initController.ts:707
|
#: src/tachyon/tabs/updates/initController.ts:707
|
||||||
#: src/tachyon/tabs/updates/initController.ts:920
|
#: src/tachyon/tabs/updates/initController.ts:920
|
||||||
|
#: src/tachyon/methods/shell/index.ts:172
|
||||||
|
#: src/tachyon/methods/shell/index.ts:179
|
||||||
msgid "Failed to execute"
|
msgid "Failed to execute"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -2269,6 +2321,10 @@ msgstr ""
|
|||||||
msgid "Game Console Optimizer (NAT Type 1)"
|
msgid "Game Console Optimizer (NAT Type 1)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:63
|
||||||
|
msgid "Gaming"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:2489
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:2489
|
||||||
msgid "Generate a random 16-character hexadecimal HWID"
|
msgid "Generate a random 16-character hexadecimal HWID"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -2729,6 +2785,10 @@ msgstr ""
|
|||||||
msgid "Invalid domain address"
|
msgid "Invalid domain address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:507
|
||||||
|
msgid "Invalid domain: empty prefix value"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:206
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:206
|
||||||
#: src/validators/validateSubnet.ts:10
|
#: src/validators/validateSubnet.ts:10
|
||||||
msgid "Invalid format. Use an IP address or CIDR subnet"
|
msgid "Invalid format. Use an IP address or CIDR subnet"
|
||||||
@@ -2811,7 +2871,7 @@ msgstr ""
|
|||||||
msgid "Invalid IP address"
|
msgid "Invalid IP address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:120
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:182
|
||||||
msgid "Invalid IP or MAC address. Expected e.g. 192.168.1.150 or AA:BB:CC:DD:EE:FF"
|
msgid "Invalid IP or MAC address. Expected e.g. 192.168.1.150 or AA:BB:CC:DD:EE:FF"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -2939,7 +2999,7 @@ msgstr ""
|
|||||||
msgid "Invalid SOCKS URL: parsing failed"
|
msgid "Invalid SOCKS URL: parsing failed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:47
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:109
|
||||||
msgid "Invalid time format. Expected HH:MM (e.g. 22:00)"
|
msgid "Invalid time format. Expected HH:MM (e.g. 22:00)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -3086,8 +3146,8 @@ msgstr ""
|
|||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8840
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:8840
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9329
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:9329
|
||||||
#: src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:17
|
|
||||||
#: src/tachyon/tabs/diagnostic/helpers/getMeta.ts:20
|
#: src/tachyon/tabs/diagnostic/helpers/getMeta.ts:20
|
||||||
|
#: src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:17
|
||||||
msgid "Issues detected"
|
msgid "Issues detected"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -3420,6 +3480,10 @@ msgstr ""
|
|||||||
msgid "Memory Usage"
|
msgid "Memory Usage"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:84
|
||||||
|
msgid "Messengers"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:2968
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:2968
|
||||||
msgid "Method"
|
msgid "Method"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -3448,7 +3512,7 @@ msgstr ""
|
|||||||
msgid "Mixed Proxy Username"
|
msgid "Mixed Proxy Username"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:200
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:262
|
||||||
msgid "Mode"
|
msgid "Mode"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -3677,8 +3741,8 @@ msgstr ""
|
|||||||
msgid "No rules use Zapret2"
|
msgid "No rules use Zapret2"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:177
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:239
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:196
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:258
|
||||||
msgid "No sections selected"
|
msgid "No sections selected"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -3697,6 +3761,8 @@ msgid "Nodes"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:12555
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:12555
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:310
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:329
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:449
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:449
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:2741
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:2741
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:3033
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:3033
|
||||||
@@ -3786,6 +3852,10 @@ msgstr ""
|
|||||||
msgid "Not set"
|
msgid "Not set"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:604
|
||||||
|
msgid "Notify in Telegram"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:2241
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:2241
|
||||||
msgid "Notify on Certificate Warnings"
|
msgid "Notify on Certificate Warnings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -4084,8 +4154,8 @@ msgid "PEM-encoded client private key"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:5187
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:5187
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:271
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:364
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:281
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:374
|
||||||
#: src/tachyon/tabs/diagnostic/diagnostic.store.ts:63
|
#: src/tachyon/tabs/diagnostic/diagnostic.store.ts:63
|
||||||
msgid "Pending"
|
msgid "Pending"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -4594,6 +4664,10 @@ msgstr ""
|
|||||||
msgid "Resume updates"
|
msgid "Resume updates"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:594
|
||||||
|
msgid "Return NXDOMAIN for blocked domains (recommended). When enabled, blocked domains are not resolved at all. When disabled, only direct connections are rejected."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:14571
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:14571
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:14619
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:14619
|
||||||
#: src/tachyon/tabs/monitoring/initController.ts:871
|
#: src/tachyon/tabs/monitoring/initController.ts:871
|
||||||
@@ -4643,7 +4717,7 @@ msgstr ""
|
|||||||
msgid "Rule"
|
msgid "Rule"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:287
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:380
|
||||||
msgid "Rule Name"
|
msgid "Rule Name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4773,7 +4847,7 @@ msgstr ""
|
|||||||
msgid "Saving…"
|
msgid "Saving…"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:216
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:278
|
||||||
msgid "Schedule"
|
msgid "Schedule"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4873,7 +4947,7 @@ msgstr ""
|
|||||||
msgid "Select a transit section"
|
msgid "Select a transit section"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:385
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:478
|
||||||
msgid "Select active days. If none selected, the rule applies every day."
|
msgid "Select active days. If none selected, the rule applies every day."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4901,7 +4975,7 @@ msgstr ""
|
|||||||
msgid "Select DNS protocol to use"
|
msgid "Select DNS protocol to use"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:297
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:390
|
||||||
msgid "Select LAN devices to apply this schedule to, or enter IP or MAC addresses manually."
|
msgid "Select LAN devices to apply this schedule to, or enter IP or MAC addresses manually."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4929,7 +5003,7 @@ msgstr ""
|
|||||||
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-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:327
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:420
|
||||||
msgid "Select Sections"
|
msgid "Select Sections"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4955,7 +5029,7 @@ msgstr ""
|
|||||||
msgid "Select the WAN interfaces to be monitored"
|
msgid "Select the WAN interfaces to be monitored"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:349
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:442
|
||||||
msgid "Select whether to disable the target during the schedule or enable it ONLY during the schedule."
|
msgid "Select whether to disable the target during the schedule or enable it ONLY during the schedule."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4996,6 +5070,10 @@ msgstr ""
|
|||||||
msgid "Send a Telegram notification if the Tachyon service is restarted by the watchdog."
|
msgid "Send a Telegram notification if the Tachyon service is restarted by the watchdog."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:605
|
||||||
|
msgid "Send a Telegram notification to admins when a blocked site is accessed. Requires the Telegram bot to be enabled."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:2216
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:2216
|
||||||
msgid "Send a Telegram notification when a URLTest group switches to a new server."
|
msgid "Send a Telegram notification when a URLTest group switches to a new server."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -5100,9 +5178,9 @@ msgstr ""
|
|||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:3410
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:3410
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:3429
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:3429
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:12323
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:12323
|
||||||
|
#: src/tachyon/tabs/diagnostic/initController.ts:604
|
||||||
#: src/tachyon/methods/shell/index.ts:422
|
#: src/tachyon/methods/shell/index.ts:422
|
||||||
#: src/tachyon/methods/shell/index.ts:443
|
#: src/tachyon/methods/shell/index.ts:443
|
||||||
#: src/tachyon/tabs/diagnostic/initController.ts:604
|
|
||||||
msgid "Service action failed"
|
msgid "Service action failed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -5144,6 +5222,10 @@ msgstr ""
|
|||||||
msgid "Settings have been reset to defaults. The page will reload."
|
msgid "Settings have been reset to defaults. The page will reload."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:93
|
||||||
|
msgid "Shopping"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:2529
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:2529
|
||||||
msgid "Show metadata on dashboard"
|
msgid "Show metadata on dashboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -5267,6 +5349,10 @@ msgstr ""
|
|||||||
msgid "Snell Version"
|
msgid "Snell Version"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:43
|
||||||
|
msgid "Social media"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:7810
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js:7810
|
||||||
msgid "Sort Alphabetically"
|
msgid "Sort Alphabetically"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -5295,7 +5381,7 @@ msgstr ""
|
|||||||
msgid "Source Network Interface"
|
msgid "Source Network Interface"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:321
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:414
|
||||||
msgid "Specific Sections (Select sections below)"
|
msgid "Specific Sections (Select sections below)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -5386,7 +5472,7 @@ msgstr ""
|
|||||||
msgid "Start Tachyon"
|
msgid "Start Tachyon"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:360
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:453
|
||||||
msgid "Start Time (HH:MM)"
|
msgid "Start Time (HH:MM)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -5405,7 +5491,7 @@ msgid "Starting…"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:2424
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:2424
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:241
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:334
|
||||||
#: src/tachyon/tabs/dashboard/partials/renderAdvancedSettings.ts:465
|
#: src/tachyon/tabs/dashboard/partials/renderAdvancedSettings.ts:465
|
||||||
#: src/tachyon/tabs/dashboard/partials/renderSections.ts:666
|
#: src/tachyon/tabs/dashboard/partials/renderSections.ts:666
|
||||||
msgid "Status"
|
msgid "Status"
|
||||||
@@ -5655,15 +5741,15 @@ msgstr ""
|
|||||||
msgid "Tailscale hostname"
|
msgid "Tailscale hostname"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:163
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:225
|
||||||
msgid "Target"
|
msgid "Target"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:296
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:389
|
||||||
msgid "Target Devices (IP / MAC)"
|
msgid "Target Devices (IP / MAC)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:315
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:408
|
||||||
msgid "Target Scope"
|
msgid "Target Scope"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -5834,7 +5920,7 @@ msgstr ""
|
|||||||
msgid "Time in seconds for DNS record caching (default: 60)"
|
msgid "Time in seconds for DNS record caching (default: 60)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:43
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:105
|
||||||
msgid "Time is required (e.g. 22:00)"
|
msgid "Time is required (e.g. 22:00)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -6446,6 +6532,10 @@ msgstr ""
|
|||||||
msgid "Via country.is"
|
msgid "Via country.is"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:53
|
||||||
|
msgid "Video streaming"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:10216
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:10216
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:12485
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js:12485
|
||||||
#: src/tachyon/tabs/diagnostic/initController.ts:820
|
#: src/tachyon/tabs/diagnostic/initController.ts:820
|
||||||
@@ -6524,11 +6614,11 @@ msgstr ""
|
|||||||
msgid "Wednesday"
|
msgid "Wednesday"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:106
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:168
|
||||||
msgid "Weekdays (Mon-Fri)"
|
msgid "Weekdays (Mon-Fri)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:110
|
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:172
|
||||||
msgid "Weekends (Sat-Sun)"
|
msgid "Weekends (Sat-Sun)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|||||||
@@ -1735,6 +1735,29 @@ function validate_schedule(schedule, sections) {
|
|||||||
if (!found)
|
if (!found)
|
||||||
fail_validation("Schedule '" + name + "' references unknown section '" + sec_name + "'. Aborted.");
|
fail_validation("Schedule '" + name + "' references unknown section '" + sec_name + "'. Aborted.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let blocked_domains = list_option(schedule, "blocked_domains");
|
||||||
|
if (length(blocked_domains) == 0) {
|
||||||
|
let single_domain = option(schedule, "blocked_domains", "");
|
||||||
|
if (single_domain != "") blocked_domains = [ single_domain ];
|
||||||
|
}
|
||||||
|
for (let domain in blocked_domains) {
|
||||||
|
let clean_domain = trim(as_string(domain));
|
||||||
|
if (clean_domain != "" && !combined_domain_valid(clean_domain))
|
||||||
|
fail_validation("Schedule '" + name + "' has invalid blocked domain '" + clean_domain + "'. Use plain domains or full:, keyword:, regex: prefixes. Aborted.");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mode = option(schedule, "mode", "block");
|
||||||
|
if (mode != "" && mode != "block" && mode != "allow")
|
||||||
|
fail_validation("Schedule '" + name + "' has invalid mode '" + mode + "'. Expected 'block' or 'allow'. Aborted.");
|
||||||
|
|
||||||
|
let dns_level = option(schedule, "dns_level", "1");
|
||||||
|
if (dns_level != "" && dns_level != "0" && dns_level != "1")
|
||||||
|
fail_validation("Schedule '" + name + "' has invalid dns_level '" + dns_level + "'. Expected 0 or 1. Aborted.");
|
||||||
|
|
||||||
|
let notify = option(schedule, "notify", "0");
|
||||||
|
if (notify != "" && notify != "0" && notify != "1")
|
||||||
|
fail_validation("Schedule '" + name + "' has invalid notify '" + notify + "'. Expected 0 or 1. Aborted.");
|
||||||
}
|
}
|
||||||
|
|
||||||
function validate_runtime_config(context) {
|
function validate_runtime_config(context) {
|
||||||
|
|||||||
@@ -135,6 +135,9 @@ function constants_map() {
|
|||||||
c.SB_DNS_INBOUND_TAG = env("SB_DNS_INBOUND_TAG", "dns-in");
|
c.SB_DNS_INBOUND_TAG = env("SB_DNS_INBOUND_TAG", "dns-in");
|
||||||
c.SB_DNS_INBOUND_ADDRESS = env("SB_DNS_INBOUND_ADDRESS", "127.0.0.42");
|
c.SB_DNS_INBOUND_ADDRESS = env("SB_DNS_INBOUND_ADDRESS", "127.0.0.42");
|
||||||
c.SB_DNS_INBOUND_PORT = env("SB_DNS_INBOUND_PORT", "53");
|
c.SB_DNS_INBOUND_PORT = env("SB_DNS_INBOUND_PORT", "53");
|
||||||
|
c.SB_DNS_BLOCK_INBOUND_TAG = env("SB_DNS_BLOCK_INBOUND_TAG", "dns-block-in");
|
||||||
|
c.SB_DNS_BLOCK_INBOUND_ADDRESS = env("SB_DNS_BLOCK_INBOUND_ADDRESS", "127.0.0.43");
|
||||||
|
c.SB_DNS_BLOCK_INBOUND_PORT = env("SB_DNS_BLOCK_INBOUND_PORT", "1053");
|
||||||
c.SB_SERVICE_MIXED_INBOUND_TAG = env("SB_SERVICE_MIXED_INBOUND_TAG", "service-mixed-in");
|
c.SB_SERVICE_MIXED_INBOUND_TAG = env("SB_SERVICE_MIXED_INBOUND_TAG", "service-mixed-in");
|
||||||
c.SB_SERVICE_MIXED_INBOUND_ADDRESS = env("SB_SERVICE_MIXED_INBOUND_ADDRESS", "127.0.0.1");
|
c.SB_SERVICE_MIXED_INBOUND_ADDRESS = env("SB_SERVICE_MIXED_INBOUND_ADDRESS", "127.0.0.1");
|
||||||
c.SB_SERVICE_MIXED_INBOUND_PORT = env("SB_SERVICE_MIXED_INBOUND_PORT", "4534");
|
c.SB_SERVICE_MIXED_INBOUND_PORT = env("SB_SERVICE_MIXED_INBOUND_PORT", "4534");
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ const SB_SERVICE_FAKEIP_DNS_RULE_TAG = getenv("SB_SERVICE_FAKEIP_DNS_RULE_TAG")
|
|||||||
const SB_TPROXY_INBOUND_TAG = getenv("SB_TPROXY_INBOUND_TAG") || "tproxy-in";
|
const SB_TPROXY_INBOUND_TAG = getenv("SB_TPROXY_INBOUND_TAG") || "tproxy-in";
|
||||||
const SB_TPROXY_INBOUND6_TAG = getenv("SB_TPROXY_INBOUND6_TAG") || "tproxy6-in";
|
const SB_TPROXY_INBOUND6_TAG = getenv("SB_TPROXY_INBOUND6_TAG") || "tproxy6-in";
|
||||||
const SB_DNS_INBOUND_TAG = getenv("SB_DNS_INBOUND_TAG") || "dns-in";
|
const SB_DNS_INBOUND_TAG = getenv("SB_DNS_INBOUND_TAG") || "dns-in";
|
||||||
|
const SB_DNS_BLOCK_INBOUND_TAG = getenv("SB_DNS_BLOCK_INBOUND_TAG") || "dns-block-in";
|
||||||
const SB_SERVICE_MIXED_INBOUND_TAG = getenv("SB_SERVICE_MIXED_INBOUND_TAG") || "service-mixed-in";
|
const SB_SERVICE_MIXED_INBOUND_TAG = getenv("SB_SERVICE_MIXED_INBOUND_TAG") || "service-mixed-in";
|
||||||
const SB_DIRECT_OUTBOUND_TAG = getenv("SB_DIRECT_OUTBOUND_TAG") || "direct-out";
|
const SB_DIRECT_OUTBOUND_TAG = getenv("SB_DIRECT_OUTBOUND_TAG") || "direct-out";
|
||||||
const SB_BYPASS_OUTBOUND_TAG = getenv("SB_BYPASS_OUTBOUND_TAG") || "bypass-out";
|
const SB_BYPASS_OUTBOUND_TAG = getenv("SB_BYPASS_OUTBOUND_TAG") || "bypass-out";
|
||||||
@@ -540,6 +541,7 @@ function default_reserved_runtime_tags() {
|
|||||||
SB_TPROXY_INBOUND_TAG,
|
SB_TPROXY_INBOUND_TAG,
|
||||||
SB_TPROXY_INBOUND6_TAG,
|
SB_TPROXY_INBOUND6_TAG,
|
||||||
SB_DNS_INBOUND_TAG,
|
SB_DNS_INBOUND_TAG,
|
||||||
|
SB_DNS_BLOCK_INBOUND_TAG,
|
||||||
SB_SERVICE_MIXED_INBOUND_TAG,
|
SB_SERVICE_MIXED_INBOUND_TAG,
|
||||||
SB_DIRECT_OUTBOUND_TAG,
|
SB_DIRECT_OUTBOUND_TAG,
|
||||||
SB_BYPASS_OUTBOUND_TAG
|
SB_BYPASS_OUTBOUND_TAG
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ let domain_config = require("config.domain");
|
|||||||
let connections = require("config.connections");
|
let connections = require("config.connections");
|
||||||
let routing_rulesets = require("routing.rulesets");
|
let routing_rulesets = require("routing.rulesets");
|
||||||
const CONFIG_NAME = getenv("TACHYON_CONFIG_NAME") || "tachyon";
|
const CONFIG_NAME = getenv("TACHYON_CONFIG_NAME") || "tachyon";
|
||||||
|
const DNS_BLOCK_TARGET = getenv("SB_DNS_BLOCK_INBOUND_ADDRESS") || "127.0.0.43:1053";
|
||||||
|
|
||||||
let common_read_json_file = common.read_json_file;
|
let common_read_json_file = common.read_json_file;
|
||||||
let list_option = common.list_option;
|
let list_option = common.list_option;
|
||||||
@@ -975,6 +976,90 @@ function nft_add_schedule_rules_from_uci(table, sections) {
|
|||||||
return nft_add_schedule_rules_from_schedules(uci_sections("schedule"), sections, table);
|
return nft_add_schedule_rules_from_schedules(uci_sections("schedule"), sections, table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─── Content blocking DNS redirect ───────────────────────────────────────────
|
||||||
|
// Schedules with blocked_domains redirect the device's DNS queries (udp/tcp
|
||||||
|
// 53) to the dedicated sing-box dns-block-in inbound (127.0.0.43:1053) when
|
||||||
|
// the schedule's time window is active. Inside the window the block inbound
|
||||||
|
// rejects the blocked domains; outside it the query flows to the normal
|
||||||
|
// dns-in inbound as usual. MAC-address devices match via ether saddr, which
|
||||||
|
// also covers devices whose IP is DHCP-assigned.
|
||||||
|
|
||||||
|
function nft_add_dns_block_rules_from_schedules(schedules, table) {
|
||||||
|
let added = false;
|
||||||
|
for (let schedule in schedules) {
|
||||||
|
schedule = object_or_empty(schedule);
|
||||||
|
if (!bool_option(schedule, "enabled", true))
|
||||||
|
continue;
|
||||||
|
if (length(list_option(schedule, "blocked_domains")) == 0) {
|
||||||
|
let single_domain = option(schedule, "blocked_domains", "");
|
||||||
|
if (single_domain == "") continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let raw_ips = list_option(schedule, "device_ip");
|
||||||
|
if (length(raw_ips) == 0) {
|
||||||
|
let single_ip = option(schedule, "device_ip", "");
|
||||||
|
if (single_ip != "") raw_ips = [ single_ip ];
|
||||||
|
}
|
||||||
|
if (length(raw_ips) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
let label = as_string(option(schedule, "label", schedule[".name"]));
|
||||||
|
let comment = "tachyon-block:" + label;
|
||||||
|
|
||||||
|
let start_time = option(schedule, "start_time", "");
|
||||||
|
let end_time = option(schedule, "end_time", "");
|
||||||
|
let intervals = nft_schedule_time_intervals(start_time, end_time);
|
||||||
|
let days_args = nft_schedule_days_match_args(schedule);
|
||||||
|
let always_on = start_time == "" && end_time == "";
|
||||||
|
|
||||||
|
for (let raw_ip in raw_ips) {
|
||||||
|
let dev_str = trim(as_string(raw_ip));
|
||||||
|
if (dev_str == "") continue;
|
||||||
|
let is_mac = match(dev_str, /^([0-9a-fA-F]{2}[:-]){5}[0-9a-fA-F]{2}$/) != null;
|
||||||
|
let family = is_mac ? 0 : core_ip.ip_family(dev_str);
|
||||||
|
if (!is_mac && family != 4)
|
||||||
|
continue; // dns-block-in listens on IPv4 only
|
||||||
|
|
||||||
|
for (let interval in intervals) {
|
||||||
|
let match_args = [];
|
||||||
|
if (is_mac) {
|
||||||
|
append_array(match_args, [ "ether", "saddr", lc(replace(dev_str, "-", ":")) ]);
|
||||||
|
} else {
|
||||||
|
append_array(match_args, [ "ip", "saddr", dev_str ]);
|
||||||
|
}
|
||||||
|
if (!always_on) {
|
||||||
|
append_array(match_args, [ "meta", "hour", sprintf("\"%s\"-\"%s\"", interval[0], interval[1]) ]);
|
||||||
|
}
|
||||||
|
append_array(match_args, days_args);
|
||||||
|
append_array(match_args, [ "udp", "dport", "53", "redirect", "to", DNS_BLOCK_TARGET, "counter", "comment", "\"" + comment + "\"" ]);
|
||||||
|
if (!nft_add_rule(table, "dns_block", match_args))
|
||||||
|
return false;
|
||||||
|
added = true;
|
||||||
|
|
||||||
|
let tcp_args = [];
|
||||||
|
if (is_mac) {
|
||||||
|
append_array(tcp_args, [ "ether", "saddr", lc(replace(dev_str, "-", ":")) ]);
|
||||||
|
} else {
|
||||||
|
append_array(tcp_args, [ "ip", "saddr", dev_str ]);
|
||||||
|
}
|
||||||
|
if (!always_on) {
|
||||||
|
append_array(tcp_args, [ "meta", "hour", sprintf("\"%s\"-\"%s\"", interval[0], interval[1]) ]);
|
||||||
|
}
|
||||||
|
append_array(tcp_args, days_args);
|
||||||
|
append_array(tcp_args, [ "tcp", "dport", "53", "redirect", "to", DNS_BLOCK_TARGET, "counter", "comment", "\"" + comment + "\"" ]);
|
||||||
|
if (!nft_add_rule(table, "dns_block", tcp_args))
|
||||||
|
return false;
|
||||||
|
added = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return added;
|
||||||
|
}
|
||||||
|
|
||||||
|
function nft_add_dns_block_rules_from_uci(table) {
|
||||||
|
return nft_add_dns_block_rules_from_schedules(uci_sections("schedule"), table);
|
||||||
|
}
|
||||||
|
|
||||||
function nft_create_runtime_base(table, localv4_set, common_set, port_set, ip_port_set, interface_set, source_interfaces, fakeip_mark, outbound_mark, fakeip_range, tproxy_port, exclude_ntp, localv6_set, common6_set, ip_port6_set, fakeip6_range, tproxy6_address) {
|
function nft_create_runtime_base(table, localv4_set, common_set, port_set, ip_port_set, interface_set, source_interfaces, fakeip_mark, outbound_mark, fakeip_range, tproxy_port, exclude_ntp, localv6_set, common6_set, ip_port6_set, fakeip6_range, tproxy6_address) {
|
||||||
localv6_set = default_arg(localv6_set, "localv6");
|
localv6_set = default_arg(localv6_set, "localv6");
|
||||||
common6_set = default_arg(common6_set, "tachyon_subnets6");
|
common6_set = default_arg(common6_set, "tachyon_subnets6");
|
||||||
@@ -1004,6 +1089,7 @@ function nft_create_runtime_base(table, localv4_set, common_set, port_set, ip_po
|
|||||||
!nft_create_priority_chains(table) ||
|
!nft_create_priority_chains(table) ||
|
||||||
!nft_create_chain(table, "parental_control", "{ }") ||
|
!nft_create_chain(table, "parental_control", "{ }") ||
|
||||||
!nft_create_chain(table, "parental_forward", "{ }") ||
|
!nft_create_chain(table, "parental_forward", "{ }") ||
|
||||||
|
!nft_create_chain(table, "dns_block", "{ type nat hook prerouting priority -101; policy accept; }") ||
|
||||||
!nft_create_chain(table, "proxy", "{ type filter hook prerouting priority -100; policy accept; }"))
|
!nft_create_chain(table, "proxy", "{ type filter hook prerouting priority -100; policy accept; }"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -1781,6 +1867,8 @@ function nft_schedule_signature_body(body, schedule) {
|
|||||||
body = signature_add_value(body, "schedule." + name + ".start_time", option(schedule, "start_time", ""));
|
body = signature_add_value(body, "schedule." + name + ".start_time", option(schedule, "start_time", ""));
|
||||||
body = signature_add_value(body, "schedule." + name + ".end_time", option(schedule, "end_time", ""));
|
body = signature_add_value(body, "schedule." + name + ".end_time", option(schedule, "end_time", ""));
|
||||||
body = signature_add_value(body, "schedule." + name + ".days", join(",", list_option(schedule, "days")));
|
body = signature_add_value(body, "schedule." + name + ".days", join(",", list_option(schedule, "days")));
|
||||||
|
body = signature_add_value(body, "schedule." + name + ".blocked_domains", join(",", list_option(schedule, "blocked_domains")));
|
||||||
|
body = signature_add_value(body, "schedule." + name + ".mode", option(schedule, "mode", "block"));
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1849,6 +1937,7 @@ function nft_create_full_runtime_from_uci(rt_table, table, localv4_set, common_s
|
|||||||
nft_create_runtime_base_from_uci(table, localv4_set, common_set, port_set, ip_port_set, interface_set, fakeip_mark, outbound_mark, fakeip_range, tproxy_port, localv6_set, common6_set, ip_port6_set, fakeip6_range, tproxy6_address) &&
|
nft_create_runtime_base_from_uci(table, localv4_set, common_set, port_set, ip_port_set, interface_set, fakeip_mark, outbound_mark, fakeip_range, tproxy_port, localv6_set, common6_set, ip_port6_set, fakeip6_range, tproxy6_address) &&
|
||||||
nft_add_section_priority_rules_from_sections(uci_sections("section"), table, interface_set, localv4_set, localv6_set, fakeip_mark) &&
|
nft_add_section_priority_rules_from_sections(uci_sections("section"), table, interface_set, localv4_set, localv6_set, fakeip_mark) &&
|
||||||
nft_add_schedule_rules_from_uci(table, uci_sections("section")) &&
|
nft_add_schedule_rules_from_uci(table, uci_sections("section")) &&
|
||||||
|
nft_add_dns_block_rules_from_uci(table) &&
|
||||||
nft_create_provider_output_rules_from_uci(table, "zapret", zapret_bin, zapret_route_mark_base, zapret_queue_base, zapret_desync_mark, zapret_desync_mark_postnat) &&
|
nft_create_provider_output_rules_from_uci(table, "zapret", zapret_bin, zapret_route_mark_base, zapret_queue_base, zapret_desync_mark, zapret_desync_mark_postnat) &&
|
||||||
nft_create_provider_output_rules_from_uci(table, "zapret2", zapret2_bin, zapret2_route_mark_base, zapret2_queue_base, zapret2_desync_mark, zapret2_desync_mark_postnat) &&
|
nft_create_provider_output_rules_from_uci(table, "zapret2", zapret2_bin, zapret2_route_mark_base, zapret2_queue_base, zapret2_desync_mark, zapret2_desync_mark_postnat) &&
|
||||||
nft_create_runtime_output_rules(table, localv4_set, common_set, port_set, ip_port_set, fakeip_mark, fakeip_range, localv6_set, common6_set, ip_port6_set, fakeip6_range);
|
nft_create_runtime_output_rules(table, localv4_set, common_set, port_set, ip_port_set, fakeip_mark, fakeip_range, localv6_set, common6_set, ip_port6_set, fakeip6_range);
|
||||||
@@ -2135,6 +2224,8 @@ else if (mode == "nft-add-section-priority-rules-fixture")
|
|||||||
exit(nft_add_section_priority_rules_from_sections(fixture_section_list(object_or_empty(common_read_json_file(ARGV[1])), "section"), ARGV[2], ARGV[3], ARGV[4], ARGV[5], ARGV[6]) ? 0 : 1);
|
exit(nft_add_section_priority_rules_from_sections(fixture_section_list(object_or_empty(common_read_json_file(ARGV[1])), "section"), ARGV[2], ARGV[3], ARGV[4], ARGV[5], ARGV[6]) ? 0 : 1);
|
||||||
else if (mode == "nft-add-schedule-rules-fixture")
|
else if (mode == "nft-add-schedule-rules-fixture")
|
||||||
exit(nft_add_schedule_rules_from_schedules(fixture_section_list(object_or_empty(common_read_json_file(ARGV[1])), "schedule"), fixture_section_list(object_or_empty(common_read_json_file(ARGV[1])), "section"), ARGV[2]) ? 0 : 1);
|
exit(nft_add_schedule_rules_from_schedules(fixture_section_list(object_or_empty(common_read_json_file(ARGV[1])), "schedule"), fixture_section_list(object_or_empty(common_read_json_file(ARGV[1])), "section"), ARGV[2]) ? 0 : 1);
|
||||||
|
else if (mode == "nft-add-dns-block-rules-fixture")
|
||||||
|
exit(nft_add_dns_block_rules_from_schedules(fixture_section_list(object_or_empty(common_read_json_file(ARGV[1])), "schedule"), ARGV[2]) ? 0 : 1);
|
||||||
else if (mode == "nft-create-full-runtime-from-uci")
|
else if (mode == "nft-create-full-runtime-from-uci")
|
||||||
exit(nft_create_full_runtime_from_uci(ARGV[1], ARGV[2], ARGV[3], ARGV[4], ARGV[5], ARGV[6], ARGV[7], ARGV[8], ARGV[9], ARGV[10], ARGV[11], ARGV[12], ARGV[13], ARGV[14], ARGV[15], ARGV[16], ARGV[17], ARGV[18], ARGV[19], ARGV[20], ARGV[21], ARGV[22], ARGV[23], ARGV[24], ARGV[25], ARGV[26]) ? 0 : 1);
|
exit(nft_create_full_runtime_from_uci(ARGV[1], ARGV[2], ARGV[3], ARGV[4], ARGV[5], ARGV[6], ARGV[7], ARGV[8], ARGV[9], ARGV[10], ARGV[11], ARGV[12], ARGV[13], ARGV[14], ARGV[15], ARGV[16], ARGV[17], ARGV[18], ARGV[19], ARGV[20], ARGV[21], ARGV[22], ARGV[23], ARGV[24], ARGV[25], ARGV[26]) ? 0 : 1);
|
||||||
else if (mode == "nft-rebuild-runtime-from-uci")
|
else if (mode == "nft-rebuild-runtime-from-uci")
|
||||||
|
|||||||
@@ -2748,6 +2748,87 @@ function check_notified_updates(token, admin_ids) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─── Content blocking notifications ──────────────────────────────────────────
|
||||||
|
// Reads the dns_block nftables chain counters and notifies admins when a
|
||||||
|
// device tried to reach a blocked domain (parental control content rules).
|
||||||
|
// The counters are cumulative; we persist the last-seen total per rule and
|
||||||
|
// only report the delta. The per-rule label is written into nft comments
|
||||||
|
// by the apply step so the counter line can be matched back to the rule.
|
||||||
|
|
||||||
|
const BLOCKED_STATE_FILE = "/var/run/tachyon_blocked_counts.json";
|
||||||
|
const BLOCKED_POLL_INTERVAL = 60;
|
||||||
|
|
||||||
|
function block_schedules_with_notify() {
|
||||||
|
let result = [];
|
||||||
|
for (let s in uci_core.sections(CONFIG_NAME, "schedule")) {
|
||||||
|
s = object_or_empty(s);
|
||||||
|
if (option(s, "enabled", "1") != "0" &&
|
||||||
|
option(s, "notify", "0") == "1" &&
|
||||||
|
length(common.list_option(s, "blocked_domains")) > 0)
|
||||||
|
push(result, s);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function load_blocked_counts() {
|
||||||
|
try {
|
||||||
|
let raw = trim(fs.readfile(BLOCKED_STATE_FILE) || "");
|
||||||
|
if (raw == "") return {};
|
||||||
|
return json(raw);
|
||||||
|
} catch (e) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function save_blocked_counts(counts) {
|
||||||
|
try {
|
||||||
|
fs.writefile(BLOCKED_STATE_FILE, sprintf("%J", counts));
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_blocked_activity(cfg) {
|
||||||
|
let schedules = block_schedules_with_notify();
|
||||||
|
if (length(schedules) == 0) return;
|
||||||
|
|
||||||
|
let out = command_capture(command_from_args([ "nft", "list", "chain", "inet", "tachyon", "dns_block" ]));
|
||||||
|
if (!out || out.status != 0) return;
|
||||||
|
|
||||||
|
let previous = load_blocked_counts();
|
||||||
|
let current = {};
|
||||||
|
for (let schedule in schedules) {
|
||||||
|
let label = as_string(option(schedule, "label", schedule[".name"]));
|
||||||
|
let needle = "tachyon-block:" + label;
|
||||||
|
let total = 0;
|
||||||
|
let match_count = 0;
|
||||||
|
for (let line in split(out.output || "", "\n")) {
|
||||||
|
if (index(line, needle) < 0)
|
||||||
|
continue;
|
||||||
|
let m = match(line, /packets[= ]+([0-9]+)/);
|
||||||
|
if (!m || !m[1]) continue;
|
||||||
|
total += int(m[1]);
|
||||||
|
match_count++;
|
||||||
|
}
|
||||||
|
if (match_count == 0)
|
||||||
|
continue;
|
||||||
|
current[label] = total;
|
||||||
|
let prev = int(previous[label] || "0");
|
||||||
|
if (total > prev) {
|
||||||
|
let delta = total - prev;
|
||||||
|
let admins = split(cfg.admin_ids || "", /,/);
|
||||||
|
for (let admin in admins) {
|
||||||
|
let cid = trim(admin);
|
||||||
|
if (cid != "")
|
||||||
|
send_message(cfg.bot_token, cid,
|
||||||
|
"🚫 <b>Заблокированная активность</b>\n" +
|
||||||
|
"Правило: <code>" + escape_html(label) + "</code>\n" +
|
||||||
|
"Попыток доступа к заблокированным сайтам: <code>" + as_string(delta) + "</code>",
|
||||||
|
"HTML", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
save_blocked_counts(current);
|
||||||
|
}
|
||||||
|
|
||||||
function worker() {
|
function worker() {
|
||||||
let cfg = settings();
|
let cfg = settings();
|
||||||
if (cfg.enabled != "1" || !cfg.bot_token) return 0;
|
if (cfg.enabled != "1" || !cfg.bot_token) return 0;
|
||||||
@@ -2791,6 +2872,7 @@ function worker() {
|
|||||||
|
|
||||||
let last_report_day = -1;
|
let last_report_day = -1;
|
||||||
let last_update_check = 0;
|
let last_update_check = 0;
|
||||||
|
let last_blocked_check = 0;
|
||||||
let consecutive_failures = 0;
|
let consecutive_failures = 0;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -2825,6 +2907,11 @@ function worker() {
|
|||||||
check_notified_updates(cfg.bot_token, cfg.admin_ids);
|
check_notified_updates(cfg.bot_token, cfg.admin_ids);
|
||||||
last_update_check = now;
|
last_update_check = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (now - last_blocked_check > BLOCKED_POLL_INTERVAL) {
|
||||||
|
check_blocked_activity(cfg);
|
||||||
|
last_blocked_check = now;
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
consecutive_failures++;
|
consecutive_failures++;
|
||||||
command_success_from_args(["logger", "-t", "tachyon-telegram", "[err] Worker loop error: " + as_string(e)]);
|
command_success_from_args(["logger", "-t", "tachyon-telegram", "[err] Worker loop error: " + as_string(e)]);
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ const TPROXY_INBOUND_PORT = 1602;
|
|||||||
const DNS_INBOUND_TAG = "dns-in";
|
const DNS_INBOUND_TAG = "dns-in";
|
||||||
const DNS_INBOUND_ADDRESS = "127.0.0.42";
|
const DNS_INBOUND_ADDRESS = "127.0.0.42";
|
||||||
const DNS_INBOUND_PORT = 53;
|
const DNS_INBOUND_PORT = 53;
|
||||||
|
const DNS_BLOCK_INBOUND_TAG = "dns-block-in";
|
||||||
|
const DNS_BLOCK_INBOUND_ADDRESS = "127.0.0.43";
|
||||||
|
const DNS_BLOCK_INBOUND_PORT = 1053;
|
||||||
|
|
||||||
const SERVICE_MIXED_INBOUND_TAG = "service-mixed-in";
|
const SERVICE_MIXED_INBOUND_TAG = "service-mixed-in";
|
||||||
const SERVICE_MIXED_INBOUND_ADDRESS = "127.0.0.1";
|
const SERVICE_MIXED_INBOUND_ADDRESS = "127.0.0.1";
|
||||||
@@ -49,6 +52,7 @@ const RESERVED_TAGS = {
|
|||||||
[TPROXY_INBOUND_TAG]: true,
|
[TPROXY_INBOUND_TAG]: true,
|
||||||
[TPROXY_INBOUND6_TAG]: true,
|
[TPROXY_INBOUND6_TAG]: true,
|
||||||
[DNS_INBOUND_TAG]: true,
|
[DNS_INBOUND_TAG]: true,
|
||||||
|
[DNS_BLOCK_INBOUND_TAG]: true,
|
||||||
[SERVICE_MIXED_INBOUND_TAG]: true,
|
[SERVICE_MIXED_INBOUND_TAG]: true,
|
||||||
[DIRECT_OUTBOUND_TAG]: true,
|
[DIRECT_OUTBOUND_TAG]: true,
|
||||||
[BYPASS_OUTBOUND_TAG]: true
|
[BYPASS_OUTBOUND_TAG]: true
|
||||||
@@ -94,6 +98,9 @@ return {
|
|||||||
DNS_INBOUND_TAG,
|
DNS_INBOUND_TAG,
|
||||||
DNS_INBOUND_ADDRESS,
|
DNS_INBOUND_ADDRESS,
|
||||||
DNS_INBOUND_PORT,
|
DNS_INBOUND_PORT,
|
||||||
|
DNS_BLOCK_INBOUND_TAG,
|
||||||
|
DNS_BLOCK_INBOUND_ADDRESS,
|
||||||
|
DNS_BLOCK_INBOUND_PORT,
|
||||||
SERVICE_MIXED_INBOUND_TAG,
|
SERVICE_MIXED_INBOUND_TAG,
|
||||||
SERVICE_MIXED_INBOUND_ADDRESS,
|
SERVICE_MIXED_INBOUND_ADDRESS,
|
||||||
SERVICE_MIXED_INBOUND_PORT,
|
SERVICE_MIXED_INBOUND_PORT,
|
||||||
|
|||||||
@@ -686,6 +686,170 @@ function add_service_mixed_proxy(config, settings, sections) {
|
|||||||
runtime_generate_unsupported("download components via proxy section is not set");
|
runtime_generate_unsupported("download components via proxy section is not set");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─── Content blocking (parental control domains) ─────────────────────────────
|
||||||
|
// Each enabled `config schedule` with blocked_domains generates:
|
||||||
|
// 1. DNS rules (on the dedicated dns-block-in inbound) that reject the
|
||||||
|
// blocked domains for the schedule's devices. IP-addressed devices get
|
||||||
|
// source_ip_cidr scoping; MAC-only devices are covered by the nftables
|
||||||
|
// DNS redirect (the DNS packets only reach dns-block-in when the
|
||||||
|
// nftables redirect rule fires, which already matches by MAC+time).
|
||||||
|
// 2. Route rules with action reject as a fallback when DNS cannot be
|
||||||
|
// redirected (always-on schedules only; time-gated schedules rely on
|
||||||
|
// the nftables redirect so their route rules would leak outside the
|
||||||
|
// active window).
|
||||||
|
// mode=allow (whitelist) inverts the DNS match: everything except the
|
||||||
|
// listed domains is rejected for the device.
|
||||||
|
|
||||||
|
function schedule_list_value(schedule, key) {
|
||||||
|
let values = list_option(schedule, key);
|
||||||
|
if (length(values) > 0)
|
||||||
|
return values;
|
||||||
|
let single = option(schedule, key, "");
|
||||||
|
return single == "" ? [] : [ single ];
|
||||||
|
}
|
||||||
|
|
||||||
|
function schedule_has_time_window(schedule) {
|
||||||
|
return trim(option(schedule, "start_time", "")) != "" ||
|
||||||
|
trim(option(schedule, "end_time", "")) != "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function schedule_source_ip_cidrs(schedule) {
|
||||||
|
let result = [];
|
||||||
|
for (let raw in schedule_list_value(schedule, "device_ip")) {
|
||||||
|
let device = trim(as_string(raw));
|
||||||
|
if (device == "")
|
||||||
|
continue;
|
||||||
|
let is_mac = match(device, /^([0-9a-fA-F]{2}[:-]){5}[0-9a-fA-F]{2}$/) != null;
|
||||||
|
if (is_mac)
|
||||||
|
continue;
|
||||||
|
if (core_ip.valid_ip(device))
|
||||||
|
push(result, core_ip.valid_ipv6(device) ? device + "/128" : device + "/32");
|
||||||
|
else if (core_ip.valid_ip_cidr(device))
|
||||||
|
push(result, device);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function schedule_domain_matcher_rule(rule, schedule) {
|
||||||
|
let raw = schedule_list_value(schedule, "blocked_domains");
|
||||||
|
let plain = [];
|
||||||
|
let keyword = [];
|
||||||
|
let regex = [];
|
||||||
|
let full = [];
|
||||||
|
for (let domain in raw) {
|
||||||
|
let value = trim(as_string(domain));
|
||||||
|
if (value == "")
|
||||||
|
continue;
|
||||||
|
if (substr(value, 0, 6) == "full:")
|
||||||
|
push(full, trim(substr(value, 6)));
|
||||||
|
else if (substr(value, 0, 8) == "keyword:")
|
||||||
|
push(keyword, trim(substr(value, 8)));
|
||||||
|
else if (substr(value, 0, 6) == "regex:")
|
||||||
|
push(regex, trim(substr(value, 6)));
|
||||||
|
else if (substr(value, 0, 1) == "." || index(value, "*") >= 0)
|
||||||
|
push(plain, value);
|
||||||
|
else
|
||||||
|
push(full, value);
|
||||||
|
}
|
||||||
|
if (length(full) > 0)
|
||||||
|
rule.domain = full;
|
||||||
|
if (length(plain) > 0)
|
||||||
|
rule.domain_suffix = plain;
|
||||||
|
if (length(keyword) > 0)
|
||||||
|
rule.domain_keyword = keyword;
|
||||||
|
if (length(regex) > 0)
|
||||||
|
rule.domain_regex = regex;
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
function schedule_blocked_domains(schedule) {
|
||||||
|
let result = [];
|
||||||
|
for (let domain in schedule_list_value(schedule, "blocked_domains")) {
|
||||||
|
let value = trim(as_string(domain));
|
||||||
|
if (value != "")
|
||||||
|
push(result, value);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function enabled_content_block_schedules() {
|
||||||
|
let result = [];
|
||||||
|
ctx.uci_cursor().foreach(CONFIG_NAME, "schedule", function(schedule) {
|
||||||
|
if (section_enabled(schedule) && length(schedule_blocked_domains(schedule)) > 0)
|
||||||
|
push(result, schedule);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_content_block_dns_inbound(config) {
|
||||||
|
push(config.inbounds, {
|
||||||
|
type: "direct",
|
||||||
|
tag: runtime_constants.DNS_BLOCK_INBOUND_TAG,
|
||||||
|
listen: runtime_constants.DNS_BLOCK_INBOUND_ADDRESS,
|
||||||
|
listen_port: runtime_constants.DNS_BLOCK_INBOUND_PORT
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_content_block_dns_rules(config, schedules) {
|
||||||
|
let added = false;
|
||||||
|
for (let schedule in schedules) {
|
||||||
|
let mode = option(schedule, "mode", "block");
|
||||||
|
let sources = schedule_source_ip_cidrs(schedule);
|
||||||
|
for (let raw_domain in schedule_blocked_domains(schedule)) {
|
||||||
|
let domain_value = trim(as_string(raw_domain));
|
||||||
|
if (domain_value == "")
|
||||||
|
continue;
|
||||||
|
let rule = {
|
||||||
|
action: "reject",
|
||||||
|
inbound: [ runtime_constants.DNS_BLOCK_INBOUND_TAG ]
|
||||||
|
};
|
||||||
|
let matchers = {};
|
||||||
|
schedule_domain_matcher_rule(matchers, { blocked_domains: [ domain_value ] });
|
||||||
|
for (let key in [ "domain", "domain_suffix", "domain_keyword", "domain_regex" ]) {
|
||||||
|
if (matchers[key] != null)
|
||||||
|
rule[key] = matchers[key];
|
||||||
|
}
|
||||||
|
if (length(sources) > 0)
|
||||||
|
rule.source_ip_cidr = sources;
|
||||||
|
if (mode == "allow")
|
||||||
|
rule.invert = true;
|
||||||
|
push(config.dns.rules, rule);
|
||||||
|
added = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return added;
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_content_block_route_rules(config, schedules) {
|
||||||
|
for (let schedule in schedules) {
|
||||||
|
if (schedule_has_time_window(schedule))
|
||||||
|
continue;
|
||||||
|
let mode = option(schedule, "mode", "block");
|
||||||
|
let sources = schedule_source_ip_cidrs(schedule);
|
||||||
|
if (length(sources) == 0)
|
||||||
|
continue;
|
||||||
|
let rule = {
|
||||||
|
action: "reject",
|
||||||
|
inbound: tproxy_inbound_matcher()
|
||||||
|
};
|
||||||
|
schedule_domain_matcher_rule(rule, schedule);
|
||||||
|
rule.source_ip_cidr = sources;
|
||||||
|
if (mode == "allow")
|
||||||
|
rule.invert = true;
|
||||||
|
push(config.route.rules, rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_content_blocking(config) {
|
||||||
|
let schedules = enabled_content_block_schedules();
|
||||||
|
if (length(schedules) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
add_content_block_dns_inbound(config);
|
||||||
|
add_content_block_dns_rules(config, schedules);
|
||||||
|
add_content_block_route_rules(config, schedules);
|
||||||
|
}
|
||||||
|
|
||||||
function generate_config(output_path, service_address, mwan3_active, supports_xhttp) {
|
function generate_config(output_path, service_address, mwan3_active, supports_xhttp) {
|
||||||
ctx.runtime_ruleset_folder = runtime_ruleset_folder;
|
ctx.runtime_ruleset_folder = runtime_ruleset_folder;
|
||||||
runtime_supports_xhttp = supports_xhttp == null || as_string(supports_xhttp) == ""
|
runtime_supports_xhttp = supports_xhttp == null || as_string(supports_xhttp) == ""
|
||||||
@@ -728,6 +892,8 @@ function generate_config(output_path, service_address, mwan3_active, supports_xh
|
|||||||
for (let section in sections)
|
for (let section in sections)
|
||||||
add_mixed_proxy_for_section(config, section, service_address);
|
add_mixed_proxy_for_section(config, section, service_address);
|
||||||
|
|
||||||
|
add_content_blocking(config);
|
||||||
|
|
||||||
assert_unique_outbound_tags(config);
|
assert_unique_outbound_tags(config);
|
||||||
strip_internal_fields(config);
|
strip_internal_fields(config);
|
||||||
if (!atomic_write_json_file(output_path, config)) {
|
if (!atomic_write_json_file(output_path, config)) {
|
||||||
|
|||||||
@@ -0,0 +1,327 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
TACHYON_LIB="$ROOT_DIR/tachyon/files/usr/lib"
|
||||||
|
GENERATOR_UC="$TACHYON_LIB/singbox/generator.uc"
|
||||||
|
NFT_RUNTIME="$TACHYON_LIB/nft/apply.uc"
|
||||||
|
VALIDATOR_RUNTIME="$TACHYON_LIB/config/validator.uc"
|
||||||
|
WORK_DIR="$(mktemp -d)"
|
||||||
|
NFT_LOG="$WORK_DIR/nft.log"
|
||||||
|
|
||||||
|
nft_ucode() {
|
||||||
|
ucode -L "$TACHYON_LIB" "$NFT_RUNTIME" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
rm -rf "$WORK_DIR"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
printf 'FAIL: %s\n' "$1" >&2
|
||||||
|
cat "$NFT_LOG" >&2 2>/dev/null || true
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_contains() {
|
||||||
|
local file="$1"
|
||||||
|
local expected="$2"
|
||||||
|
local label="$3"
|
||||||
|
|
||||||
|
grep -Fq "$expected" "$file" || fail "$label: expected '$expected'"
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_config() {
|
||||||
|
local fixture="$1"
|
||||||
|
local output="$2"
|
||||||
|
|
||||||
|
mkdir -p "$output.section-cache" "$output.rulesets"
|
||||||
|
ucode -L "$TACHYON_LIB" "$GENERATOR_UC" generate-config-fixture \
|
||||||
|
"$fixture" "$output" "127.0.0.1" "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ─── Fixture: always-on block with IP device ─────────────────────────────────
|
||||||
|
cat >"$WORK_DIR/fixture_always_on.json" <<'JSON'
|
||||||
|
{
|
||||||
|
"settings": {
|
||||||
|
".name": "settings",
|
||||||
|
".type": "settings",
|
||||||
|
"config_path": "/tmp/sing-box/config.json",
|
||||||
|
"dns_server": "1.1.1.1",
|
||||||
|
"service_listen_address": "127.0.0.1"
|
||||||
|
},
|
||||||
|
"section": [
|
||||||
|
{
|
||||||
|
".name": "sec_proxy",
|
||||||
|
"enabled": "1",
|
||||||
|
"action": "connection",
|
||||||
|
"label": "Main proxy",
|
||||||
|
"selector_proxy_links": [ "socks5://127.0.0.1:1080#Proxy" ]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"schedule": [
|
||||||
|
{
|
||||||
|
".name": "kids_youtube",
|
||||||
|
"enabled": "1",
|
||||||
|
"label": "Kids YouTube",
|
||||||
|
"device_ip": [ "192.168.1.150" ],
|
||||||
|
"blocked_domains": [ "youtube.com", "googlevideo.com" ],
|
||||||
|
"mode": "block",
|
||||||
|
"dns_level": "1",
|
||||||
|
"notify": "1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
|
OUT="$WORK_DIR/always_on.json"
|
||||||
|
generate_config "$WORK_DIR/fixture_always_on.json" "$OUT"
|
||||||
|
|
||||||
|
# dns-block-in inbound must exist
|
||||||
|
assert_contains "$OUT" '"tag": "dns-block-in"' "always-on: dns-block-in inbound"
|
||||||
|
assert_contains "$OUT" '"listen_port": 1053' "always-on: block inbound port 1053"
|
||||||
|
|
||||||
|
# DNS reject rules with source_ip_cidr for IP devices
|
||||||
|
grep -o '"source_ip_cidr": \[ [^]]*\]' "$OUT" | grep -q '192.168.1.150/32' ||
|
||||||
|
fail "always-on: DNS rule must carry source_ip_cidr 192.168.1.150/32"
|
||||||
|
assert_contains "$OUT" '"action": "reject"' "always-on: DNS reject action"
|
||||||
|
|
||||||
|
# Route rule fallback (always-on schedule, IP device)
|
||||||
|
grep -o '"action": "reject"' "$OUT" | head -2 >/dev/null ||
|
||||||
|
fail "always-on: route reject rule missing"
|
||||||
|
|
||||||
|
# ─── Fixture: whitelist (allow only) mode ────────────────────────────────────
|
||||||
|
cat >"$WORK_DIR/fixture_allow.json" <<'JSON'
|
||||||
|
{
|
||||||
|
"settings": {
|
||||||
|
".name": "settings",
|
||||||
|
".type": "settings",
|
||||||
|
"config_path": "/tmp/sing-box/config.json",
|
||||||
|
"dns_server": "1.1.1.1",
|
||||||
|
"service_listen_address": "127.0.0.1"
|
||||||
|
},
|
||||||
|
"section": [
|
||||||
|
{
|
||||||
|
".name": "sec_proxy",
|
||||||
|
"enabled": "1",
|
||||||
|
"action": "connection",
|
||||||
|
"label": "Main proxy",
|
||||||
|
"selector_proxy_links": [ "socks5://127.0.0.1:1080#Proxy" ]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"schedule": [
|
||||||
|
{
|
||||||
|
".name": "kids_whitelist",
|
||||||
|
"enabled": "1",
|
||||||
|
"label": "Kids Whitelist",
|
||||||
|
"device_ip": [ "192.168.1.151" ],
|
||||||
|
"blocked_domains": [ "school.edu", "khanacademy.org" ],
|
||||||
|
"mode": "allow",
|
||||||
|
"dns_level": "1",
|
||||||
|
"notify": "0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
|
OUT="$WORK_DIR/allow.json"
|
||||||
|
generate_config "$WORK_DIR/fixture_allow.json" "$OUT"
|
||||||
|
|
||||||
|
# Whitelist mode must invert the DNS rule
|
||||||
|
grep -o '"invert": true' "$OUT" | head -1 >/dev/null ||
|
||||||
|
fail "whitelist: DNS rule must be inverted"
|
||||||
|
assert_contains "$OUT" '"source_ip_cidr": [ "192.168.1.151/32" ]' "whitelist: source_ip_cidr scoped"
|
||||||
|
|
||||||
|
# ─── Fixture: MAC-only device (no IP in DNS rules, nft redirect only) ────────
|
||||||
|
cat >"$WORK_DIR/fixture_mac.json" <<'JSON'
|
||||||
|
{
|
||||||
|
"settings": {
|
||||||
|
".name": "settings",
|
||||||
|
".type": "settings",
|
||||||
|
"config_path": "/tmp/sing-box/config.json",
|
||||||
|
"dns_server": "1.1.1.1",
|
||||||
|
"service_listen_address": "127.0.0.1"
|
||||||
|
},
|
||||||
|
"section": [
|
||||||
|
{
|
||||||
|
".name": "sec_proxy",
|
||||||
|
"enabled": "1",
|
||||||
|
"action": "connection",
|
||||||
|
"label": "Main proxy",
|
||||||
|
"selector_proxy_links": [ "socks5://127.0.0.1:1080#Proxy" ]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"schedule": [
|
||||||
|
{
|
||||||
|
".name": "tv_block",
|
||||||
|
"enabled": "1",
|
||||||
|
"label": "TV Block",
|
||||||
|
"device_ip": [ "11:22:33:44:55:66" ],
|
||||||
|
"blocked_domains": [ "netflix.com" ],
|
||||||
|
"mode": "block",
|
||||||
|
"dns_level": "1",
|
||||||
|
"notify": "0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
|
OUT="$WORK_DIR/mac.json"
|
||||||
|
generate_config "$WORK_DIR/fixture_mac.json" "$OUT"
|
||||||
|
|
||||||
|
# MAC-only device: DNS rules must NOT carry source_ip_cidr (no IP known)
|
||||||
|
if grep -o '"source_ip_cidr"' "$OUT" | head -1 >/dev/null; then
|
||||||
|
fail "mac-only: DNS rule must not carry source_ip_cidr for MAC-only device"
|
||||||
|
fi
|
||||||
|
# But dns-block-in must still exist
|
||||||
|
assert_contains "$OUT" '"tag": "dns-block-in"' "mac-only: dns-block-in inbound"
|
||||||
|
|
||||||
|
# ─── nftables DNS redirect rules ─────────────────────────────────────────────
|
||||||
|
mkdir -p "$WORK_DIR/bin"
|
||||||
|
cat >"$WORK_DIR/bin/nft" <<NFT
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -eo pipefail
|
||||||
|
{
|
||||||
|
printf 'nft'
|
||||||
|
for arg in "\$@"; do
|
||||||
|
printf '\t%s' "\$arg"
|
||||||
|
done
|
||||||
|
printf '\n'
|
||||||
|
} >>"$NFT_LOG"
|
||||||
|
exit 0
|
||||||
|
NFT
|
||||||
|
chmod +x "$WORK_DIR/bin/nft"
|
||||||
|
export PATH="$WORK_DIR/bin:$PATH"
|
||||||
|
|
||||||
|
cat >"$WORK_DIR/nft_fixture.json" <<'JSON'
|
||||||
|
{
|
||||||
|
"schedule": [
|
||||||
|
{
|
||||||
|
".name": "kids_youtube",
|
||||||
|
"enabled": "1",
|
||||||
|
"label": "Kids YouTube",
|
||||||
|
"device_ip": [ "192.168.1.150", "11:22:33:44:55:66" ],
|
||||||
|
"blocked_domains": [ "youtube.com" ],
|
||||||
|
"start_time": "22:00",
|
||||||
|
"end_time": "08:00",
|
||||||
|
"mode": "block",
|
||||||
|
"dns_level": "1",
|
||||||
|
"notify": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
".name": "tv_always",
|
||||||
|
"enabled": "1",
|
||||||
|
"label": "TV Always",
|
||||||
|
"device_ip": [ "192.168.1.160" ],
|
||||||
|
"blocked_domains": [ "netflix.com" ],
|
||||||
|
"mode": "block",
|
||||||
|
"dns_level": "1",
|
||||||
|
"notify": "0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
|
nft_ucode nft-add-dns-block-rules-fixture "$WORK_DIR/nft_fixture.json" "tachyon"
|
||||||
|
|
||||||
|
# Time-gated rule: IP device, meta hour window, redirect to block target
|
||||||
|
assert_contains "$NFT_LOG" "dns_block ip saddr 192.168.1.150 meta hour \"22:00:00\"-\"23:59:59\" udp dport 53 redirect to 127.0.0.43:1053 counter comment" "time-gated udp redirect"
|
||||||
|
assert_contains "$NFT_LOG" "dns_block ip saddr 192.168.1.150 meta hour \"00:00:00\"-\"08:00:00\" udp dport 53 redirect to 127.0.0.43:1053" "midnight wrap udp redirect"
|
||||||
|
assert_contains "$NFT_LOG" "tcp dport 53 redirect to 127.0.0.43:1053" "tcp dns redirect"
|
||||||
|
|
||||||
|
# MAC device redirect
|
||||||
|
assert_contains "$NFT_LOG" "dns_block ether saddr 11:22:33:44:55:66 meta hour" "mac redirect with time"
|
||||||
|
|
||||||
|
# Always-on schedule: no meta hour matcher
|
||||||
|
if grep -Fq "192.168.1.160 meta hour" "$NFT_LOG"; then
|
||||||
|
fail "always-on schedule must not carry meta hour matcher"
|
||||||
|
fi
|
||||||
|
assert_contains "$NFT_LOG" "ip saddr 192.168.1.160 udp dport 53 redirect to 127.0.0.43:1053" "always-on redirect"
|
||||||
|
|
||||||
|
# ─── Validator: invalid blocked domain rejected ──────────────────────────────
|
||||||
|
cat >"$WORK_DIR/invalid_domain.json" <<'JSON'
|
||||||
|
{
|
||||||
|
"settings": { ".name": "settings", ".type": "settings", "dns_server": ["77.88.8.8"], "bootstrap_dns_server": ["77.88.8.8"] },
|
||||||
|
"schedule": [
|
||||||
|
{
|
||||||
|
".name": "bad_domain",
|
||||||
|
"enabled": "1",
|
||||||
|
"device_ip": "192.168.1.100",
|
||||||
|
"blocked_domains": [ "not a domain!!" ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
|
if ucode -L "$TACHYON_LIB" "$VALIDATOR_RUNTIME" validate-runtime-fixture "$WORK_DIR/invalid_domain.json" "{}" >/dev/null 2>&1; then
|
||||||
|
fail "Validator must reject invalid blocked_domains"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ─── Validator: invalid mode rejected ────────────────────────────────────────
|
||||||
|
cat >"$WORK_DIR/invalid_mode.json" <<'JSON'
|
||||||
|
{
|
||||||
|
"settings": { ".name": "settings", ".type": "settings", "dns_server": ["77.88.8.8"], "bootstrap_dns_server": ["77.88.8.8"] },
|
||||||
|
"schedule": [
|
||||||
|
{
|
||||||
|
".name": "bad_mode",
|
||||||
|
"enabled": "1",
|
||||||
|
"device_ip": "192.168.1.100",
|
||||||
|
"blocked_domains": [ "youtube.com" ],
|
||||||
|
"mode": "banana"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
|
if ucode -L "$TACHYON_LIB" "$VALIDATOR_RUNTIME" validate-runtime-fixture "$WORK_DIR/invalid_mode.json" "{}" >/dev/null 2>&1; then
|
||||||
|
fail "Validator must reject invalid mode"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ─── Validator: invalid dns_level rejected ───────────────────────────────────
|
||||||
|
cat >"$WORK_DIR/invalid_dns_level.json" <<'JSON'
|
||||||
|
{
|
||||||
|
"settings": { ".name": "settings", ".type": "settings", "dns_server": ["77.88.8.8"], "bootstrap_dns_server": ["77.88.8.8"] },
|
||||||
|
"schedule": [
|
||||||
|
{
|
||||||
|
".name": "bad_level",
|
||||||
|
"enabled": "1",
|
||||||
|
"device_ip": "192.168.1.100",
|
||||||
|
"blocked_domains": [ "youtube.com" ],
|
||||||
|
"dns_level": "5"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
|
if ucode -L "$TACHYON_LIB" "$VALIDATOR_RUNTIME" validate-runtime-fixture "$WORK_DIR/invalid_dns_level.json" "{}" >/dev/null 2>&1; then
|
||||||
|
fail "Validator must reject invalid dns_level"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ─── Signature changes when blocked_domains change ───────────────────────────
|
||||||
|
SIG1="$(nft_ucode nft-runtime-signature-fixture "$WORK_DIR/nft_fixture.json")"
|
||||||
|
|
||||||
|
cat >"$WORK_DIR/nft_fixture2.json" <<'JSON'
|
||||||
|
{
|
||||||
|
"schedule": [
|
||||||
|
{
|
||||||
|
".name": "kids_youtube",
|
||||||
|
"enabled": "1",
|
||||||
|
"label": "Kids YouTube",
|
||||||
|
"device_ip": [ "192.168.1.150" ],
|
||||||
|
"blocked_domains": [ "tiktok.com" ],
|
||||||
|
"start_time": "22:00",
|
||||||
|
"end_time": "08:00",
|
||||||
|
"mode": "block",
|
||||||
|
"dns_level": "1",
|
||||||
|
"notify": "1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
|
SIG2="$(nft_ucode nft-runtime-signature-fixture "$WORK_DIR/nft_fixture2.json")"
|
||||||
|
|
||||||
|
[ "$SIG1" != "$SIG2" ] || fail "Signature must change when blocked_domains are updated"
|
||||||
|
|
||||||
|
printf 'Content blocking checks passed\n'
|
||||||
Reference in New Issue
Block a user