Release 1.2.43 - Pre-download and cache all preset rulesets & databases

This commit is contained in:
Dushnilin
2026-07-29 08:58:00 +03:00
parent 28f2a04f02
commit c7ff142a48
11 changed files with 205 additions and 14 deletions
+6
View File
@@ -845,6 +845,12 @@ msgstr "Включить быстрый DNS-кэш"
msgid "Enable list updates"
msgstr "Включить обновление списков"
msgid "Pre-download all preset lists"
msgstr "Скачивать все предустановленные списки"
msgid "Cache all built-in lists and databases even if they are not currently selected in any section. Recommended if you have plenty of storage space or USB drive."
msgstr "Кешировать все встроенные списки и базы (даже если они не выбраны ни в одной секции). Рекомендуется при наличии свободного места или USB-накопителя."
msgid "Enable Mixed Proxy"
msgstr "Включить смешанный прокси"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "fe-app-tachyon",
"version": "1.2.35",
"version": "1.2.43",
"license": "MIT",
"type": "module",
"scripts": {
@@ -1362,6 +1362,18 @@ function createSettingsContent(section, capabilities) {
return _("Use sing-box duration format like 1d, 12h or 30m");
};
o = section.option(
form.Flag,
"download_all_presets",
_("Pre-download all preset lists"),
_(
"Cache all built-in lists and databases even if they are not currently selected in any section. Recommended if you have plenty of storage space or USB drive.",
),
);
o.depends("list_update_enabled", "1");
o.default = "0";
o.rmempty = false;
o = section.option(
form.Flag,
"component_update_check_enabled",
+6
View File
@@ -845,6 +845,12 @@ msgstr "Включить быстрый DNS-кэш"
msgid "Enable list updates"
msgstr "Включить обновление списков"
msgid "Pre-download all preset lists"
msgstr "Скачивать все предустановленные списки"
msgid "Cache all built-in lists and databases even if they are not currently selected in any section. Recommended if you have plenty of storage space or USB drive."
msgstr "Кешировать все встроенные списки и базы (даже если они не выбраны ни в одной секции). Рекомендуется при наличии свободного места или USB-накопителя."
msgid "Enable Mixed Proxy"
msgstr "Включить смешанный прокси"
+1
View File
@@ -23,6 +23,7 @@ config settings 'settings'
option disable_quic '0'
option list_update_enabled '1'
option update_interval '1d'
option download_all_presets '0'
option component_update_check_enabled '1'
option component_update_check_interval '1d'
option latency_test_url 'https://www.gstatic.com/generate_204'
+103 -2
View File
@@ -595,7 +595,11 @@ function rule_has_list_update_source(section) {
);
}
function has_list_update_sources(sections) {
function has_list_update_sources(sections, settings) {
if (settings == null)
settings = uci_settings();
if (bool_option(settings, "download_all_presets", false))
return true;
for (let section in sections)
if (rule_has_list_update_source(section))
return true;
@@ -689,7 +693,7 @@ function cron_refresh_plan_rows(settings, sections, bin, list_marker, subscripti
let status = 0;
let rows = [];
if (has_list_update_sources(sections)) {
if (has_list_update_sources(sections, settings)) {
let interval = settings_update_interval(settings);
if (interval == "") {
push(rows, "list-disabled");
@@ -2143,6 +2147,97 @@ function rebuild_domain_ip_lists_from_rule(section, settings) {
return ok;
}
function import_community_srs_file(service, settings) {
service = as_string(service);
if (!singbox_rulesets_module().is_community(service))
return true;
let url = singbox_rulesets_module().community_url(service);
let cached_file = TMP_RULESET_FOLDER + "/community-" + service + ".srs";
let persistent_file = "/etc/tachyon/rulesets/community-" + service + ".srs";
let tmpfile = temp_path();
if (tmpfile == "")
return false;
let ok = true;
if (download_to_file(url, tmpfile, service_proxy_address(settings, "lists")) && file_nonempty(tmpfile)) {
ensure_dir(TMP_RULESET_FOLDER);
copy_file(tmpfile, cached_file);
ensure_dir("/etc/tachyon/rulesets");
copy_file(tmpfile, persistent_file);
log_message("Successfully cached preset ruleset " + service, "info");
}
else if (file_exists_value(persistent_file)) {
ensure_dir(TMP_RULESET_FOLDER);
copy_file(persistent_file, cached_file);
}
else {
log_message("Failed to download preset ruleset " + service + "; skipping it until next update", "warn");
ok = false;
}
remove_file(tmpfile);
return ok;
}
function import_all_preset_lists(settings) {
log_message("Pre-downloading all preset lists and databases", "info");
let ok = true;
for (let service, urls in BUILTIN_SUBNET_URLS) {
if (type(urls) != "array")
continue;
let cached_file = TMP_RULESET_FOLDER + "/community-subnets-" + as_string(service) + ".lst";
let persistent_file = "/etc/tachyon/rulesets/community-subnets-" + as_string(service) + ".lst";
let combined_lines = [];
for (let url in urls) {
let tmpfile = temp_path();
if (tmpfile == "") {
ok = false;
continue;
}
let downloaded = download_to_file(url, tmpfile, service_proxy_address(settings, "lists")) && file_nonempty(tmpfile);
if (!downloaded) {
remove_file(tmpfile);
if (file_exists_value(persistent_file)) {
tmpfile = persistent_file;
} else {
log_message("Failed to download built-in preset subnet list " + as_string(service) + "; skipping it until next update", "warn");
continue;
}
}
let lines = split(as_string(fs.readfile(tmpfile)), "\n");
for (let l in lines) {
l = trim(replace(as_string(l), /\r/g, ""));
if (l != "" && substr(l, 0, 1) != "#")
push(combined_lines, l);
}
if (downloaded)
remove_file(tmpfile);
}
if (length(combined_lines) > 0) {
ensure_dir(TMP_RULESET_FOLDER);
write_file(cached_file, join("\n", combined_lines) + "\n");
ensure_dir("/etc/tachyon/rulesets");
write_file(persistent_file, join("\n", combined_lines) + "\n");
}
}
let community_services = keys(singbox_rulesets_module().COMMUNITY_SERVICES);
for (let service in community_services) {
if (!import_community_srs_file(service, settings))
ok = false;
}
return ok;
}
function import_builtin_subnets_from_rule(section, settings) {
if (!bool_option(section, "enabled", true))
return true;
@@ -2154,6 +2249,8 @@ function import_builtin_subnets_from_rule(section, settings) {
if (!singbox_rulesets_module().is_community(service))
continue;
import_community_srs_file(service, settings);
let urls = BUILTIN_SUBNET_URLS[as_string(service)];
if (type(urls) != "array")
continue;
@@ -2555,6 +2652,10 @@ function list_update() {
let ok = true;
// Фаза 1: скачивание файлов (без блокировки, не трогает nft)
if (bool_option(settings, "download_all_presets", false)) {
if (!import_all_preset_lists(settings))
ok = false;
}
for (let section in sections)
if (!rebuild_domain_ip_lists_from_rule(section, settings))
ok = false;
+2
View File
@@ -1562,6 +1562,8 @@ function nft_rule_signature_body(body, section) {
body = signature_add_value(body, "rule." + section_name + ".ports", section_rule_ports_csv(section));
body = signature_add_value(body, "rule." + section_name + ".fully_routed_ips", option(section, "fully_routed_ips", ""));
body = signature_add_value(body, "rule." + section_name + ".excluded_ips", option(section, "excluded_ips", ""));
body = signature_add_value(body, "rule." + section_name + ".excluded_protocol", option(section, "excluded_protocol", ""));
body = signature_add_value(body, "rule." + section_name + ".protocol", option(section, "protocol", ""));
body = signature_add_value(body, "rule." + section_name + ".community_subnet_lists", filter_community_subnet_lists_value(connections.community_lists_value(section)));
body = signature_add_value(body, "rule." + section_name + ".remote_subnet_lists", option(section, "remote_subnet_lists", ""));
body = signature_add_value(body, "rule." + section_name + ".rule_set_with_subnets", connections.rule_sets_with_subnets_value(section));
@@ -754,17 +754,37 @@ function ensure_community_ruleset(config, section_name, community) {
let tag_name = ruleset_tag(section_name, community, "community");
if (!ruleset_registered(config, tag_name)) {
let rule_set = {
type: "remote",
tag: tag_name,
format: "binary",
url: runtime_rulesets.community_url(community),
update_interval: remote_ruleset_update_interval()
};
let detour = ctx.download_detour_tag(ctx.runtime_settings(), "lists");
if (detour != "")
rule_set.download_detour = detour;
push(config.route.rule_set, rule_set);
let folder = ctx.runtime_ruleset_folder || runtime_ruleset_folder;
let tmp_srs = folder + "/community-" + community + ".srs";
let etc_srs = "/etc/tachyon/rulesets/community-" + community + ".srs";
let local_path = null;
if (fs.stat(tmp_srs) != null && int(fs.stat(tmp_srs).size || 0) > 0)
local_path = tmp_srs;
else if (fs.stat(etc_srs) != null && int(fs.stat(etc_srs).size || 0) > 0)
local_path = etc_srs;
if (local_path != null) {
push(config.route.rule_set, {
type: "local",
tag: tag_name,
format: "binary",
path: local_path
});
}
else {
let rule_set = {
type: "remote",
tag: tag_name,
format: "binary",
url: runtime_rulesets.community_url(community),
update_interval: remote_ruleset_update_interval()
};
let detour = ctx.download_detour_tag(ctx.runtime_settings(), "lists");
if (detour != "")
rule_set.download_detour = detour;
push(config.route.rule_set, rule_set);
}
}
return {
tag: tag_name,
+12
View File
@@ -654,6 +654,10 @@ bypass
192.168.1.10/32
[rule.text_rule.excluded_ips]
[rule.text_rule.excluded_protocol]
[rule.text_rule.protocol]
[rule.text_rule.community_subnet_lists]
meta telegram discord
[rule.text_rule.remote_subnet_lists]
@@ -676,6 +680,10 @@ proxy
[rule.default_enabled.excluded_ips]
[rule.default_enabled.excluded_protocol]
[rule.default_enabled.protocol]
[rule.default_enabled.community_subnet_lists]
cloudflare roblox
[rule.default_enabled.remote_subnet_lists]
@@ -728,6 +736,10 @@ bypass
192.168.1.10/32
[rule.enabled.excluded_ips]
[rule.enabled.excluded_protocol]
[rule.enabled.protocol]
[rule.enabled.community_subnet_lists]
meta telegram discord
[rule.enabled.remote_subnet_lists]
+16
View File
@@ -663,6 +663,10 @@ ads
198.51.100.2
[rule.proxy1.excluded_ips]
[rule.proxy1.excluded_protocol]
[rule.proxy1.protocol]
[rule.proxy1.community_lists]
telegram
[rule.proxy1.rule_set]
@@ -741,6 +745,10 @@ disabled
[rule.out1.excluded_ips]
[rule.out1.excluded_protocol]
[rule.out1.protocol]
[rule.out1.community_lists]
[rule.out1.rule_set]
@@ -775,6 +783,10 @@ byedpi
[rule.bye1.excluded_ips]
[rule.bye1.excluded_protocol]
[rule.bye1.protocol]
[rule.bye1.community_lists]
[rule.bye1.rule_set]
@@ -853,6 +865,10 @@ disabled
[rule.vpn1.excluded_ips]
[rule.vpn1.excluded_protocol]
[rule.vpn1.protocol]
[rule.vpn1.community_lists]
[rule.vpn1.rule_set]
+15
View File
@@ -163,6 +163,21 @@ assert_eq $'list\t*/30 * * * * /usr/bin/tachyon list_update_if_due # list\nsubsc
grep -Fq 'fs.writefile(tmp, as_string(text)) == null' "$UPDATES_UC" ||
fail "empty crontab writes must not be treated as fs.writefile failure"
cat >"$WORK_DIR/cron-plan-all-presets.json" <<'JSON'
{
"settings": {
"list_update_enabled": "1",
"update_interval": "1h",
"download_all_presets": "1"
},
"section": []
}
JSON
assert_eq $'list\t0 * * * * /usr/bin/tachyon list_update_if_due # list' \
"$(updates_ucode cron-refresh-plan-fixture "$WORK_DIR/cron-plan-all-presets.json" /usr/bin/tachyon '# list' '# sub' '# comp')" \
"cron refresh plan with download_all_presets"
cat >"$WORK_DIR/cron-plan-list-disabled.json" <<'JSON'
{
"settings": {