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:
Dushnilin
2026-08-21 05:11:39 +03:00
parent 7084b9ba3d
commit bd083cc5d3
14 changed files with 1573 additions and 181 deletions
@@ -38,6 +38,68 @@ const DAY_INDEX_MAP = {
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) {
if (!value) {
return _("Time is required (e.g. 22:00)");
@@ -237,6 +299,37 @@ function createParentalContent(section) {
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
o = section.option(form.DummyValue, "_live_status", _("Status"));
o.rawhtml = true;
@@ -389,6 +482,131 @@ function createParentalContent(section) {
Object.entries(DAY_LABELS).forEach(([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 = {
+68 -2
View File
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: TACHYON\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-08-20 22:26+0300\n"
"PO-Revision-Date: 2026-08-20 22:26+0300\n"
"POT-Creation-Date: 2026-08-21 05:02+0300\n"
"PO-Revision-Date: 2026-08-21 05:02+0300\n"
"Last-Translator: Dushnilin\n"
"Language-Team: none\n"
"Language: ru\n"
@@ -146,6 +146,9 @@ msgstr "Адрес"
msgid "Administrator Chat IDs"
msgstr "Chat ID администраторов"
msgid "Adult content"
msgstr ""
msgid "Advanced self-healing features. Requires Watchdog to be enabled."
msgstr "Расширенные функции самовосстановления. Требуется включённый Watchdog."
@@ -251,6 +254,15 @@ msgstr "Разрешено в интервале"
msgid "Allow Insecure 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:"
msgstr "Допустимые префиксы доменов: full:, keyword:, и regex:"
@@ -380,15 +392,36 @@ msgstr "Беларусь (by)"
msgid "BitTorrent / P2P"
msgstr "BitTorrent / P2P"
msgid "Block"
msgstr ""
msgid "Block / Disable in scheduled hours (Standard)"
msgstr "Блокировать / Отключать в указанные часы (Стандарт)"
msgid "Block at DNS level"
msgstr ""
msgid "Block in interval"
msgstr "Блокируется в интервале"
msgid "Block internet access or specific proxy sections for individual devices based on time and days."
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"
msgstr "Bootstrap DNS"
@@ -686,6 +719,9 @@ msgstr "Подключения недоступны"
msgid "Connectivity probe failed"
msgstr "Проверка соединения не прошла"
msgid "Content Mode"
msgstr ""
msgid "Cookie packet junk size (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."
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"
msgstr "Готово"
@@ -1433,6 +1472,9 @@ msgstr "IP игровых консолей"
msgid "Game Console Optimizer (NAT Type 1)"
msgstr "Оптимизатор игровых консолей (NAT Type 1)"
msgid "Gaming"
msgstr ""
msgid "Generate a random 16-character hexadecimal HWID"
msgstr "Сгенерировать случайный 16-символьный шестнадцатеричный HWID"
@@ -1736,6 +1778,9 @@ msgstr "Неверный порт DNS-сервера"
msgid "Invalid domain address"
msgstr "Неверный домен"
msgid "Invalid domain: empty prefix value"
msgstr ""
msgid "Invalid format. Use an IP address or CIDR subnet"
msgstr "Неверный формат. Используйте IP-адрес или подсеть CIDR"
@@ -2168,6 +2213,9 @@ msgstr "Максимальное время ожидания разрешени
msgid "Memory Usage"
msgstr "Использование памяти"
msgid "Messengers"
msgstr ""
msgid "Method"
msgstr "Метод"
@@ -2378,6 +2426,9 @@ msgstr "Не запущено"
msgid "Not set"
msgstr "Не задано"
msgid "Notify in Telegram"
msgstr ""
msgid "Notify on Certificate Warnings"
msgstr "Уведомлять о предупреждениях сертификатов"
@@ -2909,6 +2960,9 @@ msgstr "Восстановление прямого интернета (оста
msgid "Resume updates"
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"
msgstr "Маршрут"
@@ -3176,6 +3230,9 @@ msgstr "Отправлять уведомление в Telegram, если SSL/TL
msgid "Send a Telegram notification if the Tachyon service is restarted by the 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."
msgstr "Отправлять уведомление в Telegram при переключении группы URLTest на новый сервер."
@@ -3266,6 +3323,9 @@ msgstr "Настройки"
msgid "Settings have been reset to defaults. The page will reload."
msgstr "Настройки сброшены к значениям по умолчанию. Страница будет перезагружена."
msgid "Shopping"
msgstr ""
msgid "Show metadata on dashboard"
msgstr "Показывать метаданные на дашборде"
@@ -3350,6 +3410,9 @@ msgstr "Снапшот восстановлен. Сервис перезапус
msgid "Snell Version"
msgstr "Версия Snell"
msgid "Social media"
msgstr ""
msgid "Sort Alphabetically"
msgstr "Сортировать по алфавиту"
@@ -4061,6 +4124,9 @@ msgstr "Проверка готовности роутера и служб..."
msgid "Via country.is"
msgstr "Через country.is"
msgid "Video streaming"
msgstr ""
msgid "View logs"
msgstr "Посмотреть логи"
+148 -58
View File
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: TACHYON\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-08-20 19:26+0300\n"
"PO-Revision-Date: 2026-08-20 19:26+0300\n"
"POT-Creation-Date: 2026-08-21 02:02+0300\n"
"PO-Revision-Date: 2026-08-21 02:02+0300\n"
"Last-Translator: Dushnilin <dushnilin@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
@@ -105,7 +105,7 @@ msgstr ""
msgid "Action"
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"
msgstr ""
@@ -118,13 +118,13 @@ msgstr ""
msgid "Active"
msgstr ""
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:260
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:280
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:353
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:373
msgid "Active (Allowed)"
msgstr ""
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:260
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:280
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:353
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:373
msgid "Active (Blocking)"
msgstr ""
@@ -223,6 +223,10 @@ msgstr ""
msgid "Administrator Chat IDs"
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
msgid "Advanced self-healing features. Requires Watchdog to be enabled."
msgstr ""
@@ -327,8 +331,8 @@ msgstr ""
msgid "All checks passed — Telegram bot should work correctly"
msgstr ""
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:139
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:159
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:201
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:221
msgid "All devices"
msgstr ""
@@ -336,12 +340,12 @@ msgstr ""
msgid "All except selected"
msgstr ""
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:169
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:194
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:231
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:256
msgid "All Internet"
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)"
msgstr ""
@@ -372,12 +376,12 @@ msgstr ""
msgid "All traffic from these IP addresses will be routed through the section unconditionally, ignoring all other conditions."
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)"
msgstr ""
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:206
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:212
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:268
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:274
msgid "Allow in interval"
msgstr ""
@@ -385,6 +389,18 @@ msgstr ""
msgid "Allow Insecure TLS"
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
msgid "Allowed domain prefixes are full:, keyword:, and regex:"
msgstr ""
@@ -563,7 +579,7 @@ msgstr ""
msgid "Bearer Auth Token"
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)"
msgstr ""
@@ -576,12 +592,20 @@ msgstr ""
msgid "BitTorrent / P2P"
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)"
msgstr ""
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:208
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:212
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:593
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"
msgstr ""
@@ -589,6 +613,26 @@ msgstr ""
msgid "Block internet access or specific proxy sections for individual devices based on time and days."
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
#: src/tachyon/tabs/diagnostic/checks/runDnsCheck.ts:57
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:9323
#: src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:10
#: src/tachyon/tabs/diagnostic/helpers/getMeta.ts:26
#: src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:10
msgid "Checks failed"
msgstr ""
#: ../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:9334
#: src/tachyon/tabs/diagnostic/helpers/getMeta.ts:13
#: src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:23
#: src/tachyon/tabs/diagnostic/checks/runFakeIPCheck.ts:43
#: src/tachyon/tabs/diagnostic/helpers/getMeta.ts:13
msgid "Checks passed"
msgstr ""
@@ -888,7 +932,7 @@ msgstr ""
msgid "Choose Hosts File..."
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."
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)."
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."
msgstr ""
@@ -1118,6 +1162,10 @@ msgstr ""
msgid "Connectivity probe failed"
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
msgid "Cookie packet junk size (S3)"
msgstr ""
@@ -1230,7 +1278,7 @@ msgstr ""
msgid "Dashboard currently unavailable"
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"
msgstr ""
@@ -1288,7 +1336,7 @@ msgstr ""
msgid "detour must be a non-empty string"
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"
msgstr ""
@@ -1366,8 +1414,8 @@ msgstr ""
msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming"
msgstr ""
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:250
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:277
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:343
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:370
msgid "Disabled"
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."
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
msgid "Done"
msgstr ""
@@ -1674,7 +1726,7 @@ msgstr ""
msgid "e.g. google.com, 1.1.1.1, 443"
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)"
msgstr ""
@@ -1691,7 +1743,7 @@ msgstr ""
msgid "Edit"
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/server.js:2618
msgid "Enable"
@@ -1825,11 +1877,11 @@ msgstr ""
msgid "Enables the background watchdog process to monitor services and auto-recover on failures."
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."
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)"
msgstr ""
@@ -1895,7 +1947,7 @@ msgstr ""
msgid "Error updating lists:"
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"
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:16786
#: ../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:632
#: src/tachyon/tabs/updates/initController.ts:707
#: 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"
msgstr ""
@@ -2269,6 +2321,10 @@ msgstr ""
msgid "Game Console Optimizer (NAT Type 1)"
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
msgid "Generate a random 16-character hexadecimal HWID"
msgstr ""
@@ -2729,6 +2785,10 @@ msgstr ""
msgid "Invalid domain address"
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
#: src/validators/validateSubnet.ts:10
msgid "Invalid format. Use an IP address or CIDR subnet"
@@ -2811,7 +2871,7 @@ msgstr ""
msgid "Invalid IP address"
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"
msgstr ""
@@ -2939,7 +2999,7 @@ msgstr ""
msgid "Invalid SOCKS URL: parsing failed"
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)"
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:9329
#: src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:17
#: src/tachyon/tabs/diagnostic/helpers/getMeta.ts:20
#: src/tachyon/tabs/diagnostic/checks/getCheckItemsMeta.ts:17
msgid "Issues detected"
msgstr ""
@@ -3420,6 +3480,10 @@ msgstr ""
msgid "Memory Usage"
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
msgid "Method"
msgstr ""
@@ -3448,7 +3512,7 @@ msgstr ""
msgid "Mixed Proxy Username"
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"
msgstr ""
@@ -3677,8 +3741,8 @@ msgstr ""
msgid "No rules use Zapret2"
msgstr ""
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:177
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:196
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:239
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:258
msgid "No sections selected"
msgstr ""
@@ -3697,6 +3761,8 @@ msgid "Nodes"
msgstr ""
#: ../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:2741
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/server.js:3033
@@ -3786,6 +3852,10 @@ msgstr ""
msgid "Not set"
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
msgid "Notify on Certificate Warnings"
msgstr ""
@@ -4084,8 +4154,8 @@ msgid "PEM-encoded client private key"
msgstr ""
#: ../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:281
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:364
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/parental.js:374
#: src/tachyon/tabs/diagnostic/diagnostic.store.ts:63
msgid "Pending"
msgstr ""
@@ -4594,6 +4664,10 @@ msgstr ""
msgid "Resume updates"
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:14619
#: src/tachyon/tabs/monitoring/initController.ts:871
@@ -4643,7 +4717,7 @@ msgstr ""
msgid "Rule"
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"
msgstr ""
@@ -4773,7 +4847,7 @@ msgstr ""
msgid "Saving…"
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"
msgstr ""
@@ -4873,7 +4947,7 @@ msgstr ""
msgid "Select a transit section"
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."
msgstr ""
@@ -4901,7 +4975,7 @@ msgstr ""
msgid "Select DNS protocol to use"
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."
msgstr ""
@@ -4929,7 +5003,7 @@ msgstr ""
msgid "Select path for sing-box config file. Change this ONLY if you know what you are doing"
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"
msgstr ""
@@ -4955,7 +5029,7 @@ msgstr ""
msgid "Select the WAN interfaces to be monitored"
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."
msgstr ""
@@ -4996,6 +5070,10 @@ msgstr ""
msgid "Send a Telegram notification if the Tachyon service is restarted by the watchdog."
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
msgid "Send a Telegram notification when a URLTest group switches to a new server."
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:3429
#: ../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:443
#: src/tachyon/tabs/diagnostic/initController.ts:604
msgid "Service action failed"
msgstr ""
@@ -5144,6 +5222,10 @@ msgstr ""
msgid "Settings have been reset to defaults. The page will reload."
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
msgid "Show metadata on dashboard"
msgstr ""
@@ -5267,6 +5349,10 @@ msgstr ""
msgid "Snell Version"
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
msgid "Sort Alphabetically"
msgstr ""
@@ -5295,7 +5381,7 @@ msgstr ""
msgid "Source Network Interface"
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)"
msgstr ""
@@ -5386,7 +5472,7 @@ msgstr ""
msgid "Start Tachyon"
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)"
msgstr ""
@@ -5405,7 +5491,7 @@ msgid "Starting…"
msgstr ""
#: ../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/renderSections.ts:666
msgid "Status"
@@ -5655,15 +5741,15 @@ msgstr ""
msgid "Tailscale hostname"
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"
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)"
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"
msgstr ""
@@ -5834,7 +5920,7 @@ msgstr ""
msgid "Time in seconds for DNS record caching (default: 60)"
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)"
msgstr ""
@@ -6446,6 +6532,10 @@ msgstr ""
msgid "Via country.is"
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:12485
#: src/tachyon/tabs/diagnostic/initController.ts:820
@@ -6524,11 +6614,11 @@ msgstr ""
msgid "Wednesday"
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)"
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)"
msgstr ""