Release 1.2.43 - Pre-download and cache all preset rulesets & databases
This commit is contained in:
@@ -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,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",
|
||||
|
||||
@@ -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 "Включить смешанный прокси"
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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": {
|
||||
|
||||
Reference in New Issue
Block a user