luci-app-passwall2: sync upstream

last commit: 489893bc86
This commit is contained in:
gitea-action 2025-04-01 02:31:12 +08:00
parent eb5b203669
commit b0f5377491
19 changed files with 206 additions and 129 deletions

View File

@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall2
PKG_VERSION:=25.3.2
PKG_VERSION:=25.4.1
PKG_RELEASE:=1
PKG_CONFIG_DEPENDS:= \

View File

@ -176,7 +176,7 @@ function get_redir_log()
local name = luci.http.formvalue("name")
local file_path = "/tmp/etc/passwall2/acl/" .. id .. "/" .. name .. ".log"
if nixio.fs.access(file_path) then
local content = luci.sys.exec("cat '" .. file_path .. "'")
local content = luci.sys.exec("tail -n 19999 '" .. file_path .. "'")
content = content:gsub("\n", "<br />")
luci.http.write(content)
else
@ -188,7 +188,7 @@ function get_socks_log()
local name = luci.http.formvalue("name")
local path = "/tmp/etc/passwall2/SOCKS_" .. name .. ".log"
if nixio.fs.access(path) then
local content = luci.sys.exec("cat ".. path)
local content = luci.sys.exec("tail -n 5000 ".. path)
content = content:gsub("\n", "<br />")
luci.http.write(content)
else

View File

@ -1,7 +1,7 @@
local api = require "luci.passwall2.api"
local appname = api.appname
local datatypes = api.datatypes
local has_singbox = api.finded_com("singbox")
local has_singbox = api.finded_com("sing-box")
local has_xray = api.finded_com("xray")
m = Map(appname)

View File

@ -3,7 +3,7 @@ local appname = api.appname
local uci = api.uci
local has_ss = api.is_finded("ss-redir")
local has_ss_rust = api.is_finded("sslocal")
local has_singbox = api.finded_com("singbox")
local has_singbox = api.finded_com("sing-box")
local has_xray = api.finded_com("xray")
local has_hysteria2 = api.finded_com("hysteria")
local ss_type = {}

View File

@ -11,7 +11,7 @@ end
local has_ss = api.is_finded("ss-redir")
local has_ss_rust = api.is_finded("sslocal")
local has_singbox = api.finded_com("singbox")
local has_singbox = api.finded_com("sing-box")
local has_xray = api.finded_com("xray")
local has_hysteria2 = api.finded_com("hysteria")
local ss_type = {}

View File

@ -1,7 +1,7 @@
local api = require "luci.passwall2.api"
local appname = api.appname
local fs = api.fs
local has_singbox = api.finded_com("singbox")
local has_singbox = api.finded_com("sing-box")
local has_xray = api.finded_com("xray")
local has_fw3 = api.is_finded("fw3")
local has_fw4 = api.is_finded("fw4")

View File

@ -8,7 +8,7 @@ if not arg[1] or not m:get(arg[1]) then
luci.http.redirect(api.url())
end
local has_singbox = api.finded_com("singbox")
local has_singbox = api.finded_com("sing-box")
local has_xray = api.finded_com("xray")
local nodes_table = {}

View File

@ -95,7 +95,7 @@ m.uci:foreach(appname, "socks", function(s)
end)
-- 负载均衡列表
local o = s:option(DynamicList, _n("balancing_node"), translate("Load balancing node list"), translate("Load balancing node list, <a target='_blank' href='https://toutyrater.github.io/routing/balance2.html'>document</a>"))
local o = s:option(DynamicList, _n("balancing_node"), translate("Load balancing node list"), translate("Load balancing node list, <a target='_blank' href='https://xtls.github.io/config/routing.html#balancerobject'>document</a>"))
o:depends({ [_n("protocol")] = "_balancing" })
for k, v in pairs(nodes_table) do o:value(v.id, v.remark) end
@ -104,7 +104,8 @@ o:depends({ [_n("protocol")] = "_balancing" })
o:value("random")
o:value("roundRobin")
o:value("leastPing")
o.default = "leastPing"
o:value("leastLoad")
o.default = "leastLoad"
-- Fallback Node
if api.compare_versions(xray_version, ">=", "1.8.10") then
@ -133,6 +134,7 @@ end
-- 探测地址
local ucpu = s:option(Flag, _n("useCustomProbeUrl"), translate("Use Custome Probe URL"), translate("By default the built-in probe URL will be used, enable this option to use a custom probe URL."))
ucpu:depends({ [_n("balancingStrategy")] = "leastPing" })
ucpu:depends({ [_n("balancingStrategy")] = "leastLoad" })
local pu = s:option(Value, _n("probeUrl"), translate("Probe URL"))
pu:depends({ [_n("useCustomProbeUrl")] = true })
@ -148,8 +150,9 @@ pu.description = translate("The URL used to detect the connection status.")
-- 探测间隔
local pi = s:option(Value, _n("probeInterval"), translate("Probe Interval"))
pi:depends({ [_n("balancingStrategy")] = "leastPing" })
pi:depends({ [_n("balancingStrategy")] = "leastLoad" })
pi.default = "1m"
pi.description = translate("The interval between initiating probes. Every time this time elapses, a server status check is performed on a server. The time format is numbers + units, such as '10s', '2h45m', and the supported time units are <code>ns</code>, <code>us</code>, <code>ms</code>, <code>s</code>, <code>m</code>, <code>h</code>, which correspond to nanoseconds, microseconds, milliseconds, seconds, minutes, and hours, respectively.")
pi.description = translate("The interval between initiating probes. The time format is numbers + units, such as '10s', '2h45m', and the supported time units are <code>ns</code>, <code>us</code>, <code>ms</code>, <code>s</code>, <code>m</code>, <code>h</code>, which correspond to nanoseconds, microseconds, milliseconds, seconds, minutes, and hours, respectively.")
if api.compare_versions(xray_version, ">=", "1.8.12") then
ucpu:depends({ [_n("protocol")] = "_balancing" })
@ -159,6 +162,12 @@ else
pi:depends({ [_n("balancingStrategy")] = "leastPing" })
end
o = s:option(Value, _n("expected"), translate("Preferred Node Count"))
o:depends({ [_n("balancingStrategy")] = "leastLoad" })
o.datatype = "uinteger"
o.default = "2"
o.description = translate("The load balancer selects the optimal number of nodes, and traffic is randomly distributed among them.")
-- [[ 分流模块 ]]
if #nodes_table > 0 then

View File

@ -2,7 +2,7 @@ local m, s = ...
local api = require "luci.passwall2.api"
local singbox_bin = api.finded_com("singbox")
local singbox_bin = api.finded_com("sing-box")
if not singbox_bin then
return
@ -401,6 +401,10 @@ if singbox_tags:find("with_quic") then
end
if singbox_tags:find("with_quic") then
o = s:option(Value, _n("hysteria2_ports"), translate("Port hopping range"))
o.description = translate("Format as 1000:2000 Multiple groups are separated by commas (,).")
o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))
o:depends({ [_n("protocol")] = "hysteria2" })

View File

@ -2,7 +2,7 @@ local m, s = ...
local api = require "luci.passwall2.api"
local singbox_bin = api.finded_com("singbox")
local singbox_bin = api.finded_com("sing-box")
if not singbox_bin then
return

View File

@ -23,7 +23,7 @@ _M.hysteria = {
}
}
_M.singbox = {
_M["sing-box"] = {
name = "Sing-Box",
repo = "SagerNet/sing-box",
get_url = gh_release_url,

View File

@ -149,7 +149,7 @@ local function start()
bin = ln_run(api.get_app_path("xray"), "xray", "run -c " .. config_file, log_path)
elseif type == "sing-box" then
config = require(require_dir .. "util_sing-box").gen_config_server(user)
bin = ln_run(api.get_app_path("singbox"), "sing-box", "run -c " .. config_file, log_path)
bin = ln_run(api.get_app_path("sing-box"), "sing-box", "run -c " .. config_file, log_path)
elseif type == "Hysteria2" then
config = require(require_dir .. "util_hysteria2").gen_config_server(user)
bin = ln_run(api.get_app_path("hysteria"), "hysteria", "-c " .. config_file .. " server", log_path)

View File

@ -8,7 +8,7 @@ local fs = api.fs
local CACHE_PATH = api.CACHE_PATH
local split = api.split
local local_version = api.get_app_version("singbox")
local local_version = api.get_app_version("sing-box")
local version_ge_1_11_0 = api.compare_versions(local_version:match("[^v]+"), ">=", "1.11.0")
local new_port
@ -349,7 +349,17 @@ function gen_outbound(flag, node, tag, proxy_table)
end
if node.protocol == "hysteria2" then
local server_ports = {}
if node.hysteria2_ports then
for range in node.hysteria2_ports:gmatch("([^,]+)") do
if range:match("^%d+:%d+$") then
table.insert(server_ports, range)
end
end
end
protocol_table = {
server_ports = next(server_ports) and server_ports or nil,
hop_interval = next(server_ports) and "30s" or nil,
up_mbps = (node.hysteria2_up_mbps and tonumber(node.hysteria2_up_mbps)) and tonumber(node.hysteria2_up_mbps) or nil,
down_mbps = (node.hysteria2_down_mbps and tonumber(node.hysteria2_down_mbps)) and tonumber(node.hysteria2_down_mbps) or nil,
obfs = {

View File

@ -584,7 +584,8 @@ function gen_config(var)
local inbounds = {}
local outbounds = {}
local routing = nil
local observatory = nil
local burstObservatory = nil
local strategy = nil
local COMMON = {}
local CACHE_TEXT_FILE = CACHE_PATH .. "/cache_" .. flag .. ".txt"
@ -758,19 +759,33 @@ function gen_config(var)
end
end
end
if _node.balancingStrategy == "leastLoad" then
strategy = {
type = _node.balancingStrategy,
settings = {
expected = _node.expected and tonumber(_node.expected) and tonumber(_node.expected) or 2,
maxRTT = "1s"
}
}
else
strategy = { type = _node.balancingStrategy or "random" }
end
table.insert(balancers, {
tag = balancer_tag,
selector = valid_nodes,
fallbackTag = fallback_node_tag,
strategy = { type = _node.balancingStrategy or "random" }
strategy = strategy
})
if _node.balancingStrategy == "leastPing" or fallback_node_tag then
if not observatory then
observatory = {
if _node.balancingStrategy == "leastPing" or _node.balancingStrategy == "leastLoad" or fallback_node_tag then
if not burstObservatory then
burstObservatory = {
subjectSelector = { "blc-" },
probeUrl = _node.useCustomProbeUrl and _node.probeUrl or nil,
probeInterval = _node.probeInterval or "1m",
enableConcurrency = true
pingConfig = {
destination = _node.useCustomProbeUrl and _node.probeUrl or nil,
interval = _node.probeInterval or "1m",
sampling = 3,
timeout = "5s"
}
}
end
end
@ -1483,7 +1498,7 @@ function gen_config(var)
-- 传出连接
outbounds = outbounds,
-- 连接观测
observatory = observatory,
burstObservatory = burstObservatory,
-- 路由
routing = routing,
-- 本地策略

View File

@ -10,7 +10,7 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin
-%>
<script src="<%=resource%>/qrcode.min.js"></script>
<script type="text/javascript">//<![CDATA[
let has_singbox = "<%=api.finded_com("singbox")%>"
let has_singbox = "<%=api.finded_com("sing-box")%>"
let has_xray = "<%=api.finded_com("xray")%>"
let has_hysteria2 = "<%=api.finded_com("hysteria")%>"
let ss_type = "<%=ss_type%>"

View File

@ -313,82 +313,84 @@ table td, .table .td {
}
/* 自动Ping */
if (auto_detection_time == "icmp" || auto_detection_time == "tcping") {
var nodes = [];
const ping_value = document.getElementsByClassName(auto_detection_time == "tcping" ? 'tcping_value' : 'ping_value');
for (var i = 0; i < ping_value.length; i++) {
var cbi_id = ping_value[i].getAttribute("cbiid");
var full = get_address_full(cbi_id);
if (full != null) {
var flag = false;
//当有多个相同地址和端口时合在一起
for (var j = 0; j < nodes.length; j++) {
if (nodes[j].address == full.address && nodes[j].port == full.port) {
nodes[j].indexs = nodes[j].indexs + "," + i;
flag = true;
break;
function pingAllNodes() {
if (auto_detection_time == "icmp" || auto_detection_time == "tcping") {
var nodes = [];
const ping_value = document.getElementsByClassName(auto_detection_time == "tcping" ? 'tcping_value' : 'ping_value');
for (var i = 0; i < ping_value.length; i++) {
var cbi_id = ping_value[i].getAttribute("cbiid");
var full = get_address_full(cbi_id);
if (full != null) {
var flag = false;
//当有多个相同地址和端口时合在一起
for (var j = 0; j < nodes.length; j++) {
if (nodes[j].address == full.address && nodes[j].port == full.port) {
nodes[j].indexs = nodes[j].indexs + "," + i;
flag = true;
break;
}
}
if (flag)
continue;
nodes.push({
indexs: i + "",
address: full.address,
port: full.port
});
}
if (flag)
continue;
nodes.push({
indexs: i + "",
address: full.address,
port: full.port
});
}
}
const _xhr = (index) => {
return new Promise((res) => {
const dom = nodes[index];
if (!dom) res()
ajax.post('<%=api.url("ping_node")%>', {
index: dom.indexs,
address: dom.address,
port: dom.port,
type: auto_detection_time
},
function(x, result) {
if (x && x.status == 200) {
var strs = dom.indexs.split(",");
for (var i = 0; i < strs.length; i++) {
if (result.ping == null || result.ping.trim() == "") {
ping_value[strs[i]].innerHTML = "<font style='color:red'><%:Timeout%></font>";
} else {
var ping = parseInt(result.ping);
if (ping < 100)
ping_value[strs[i]].innerHTML = "<font style='color:green'>" + result.ping + " ms" + "</font>";
else if (ping < 200)
ping_value[strs[i]].innerHTML = "<font style='color:#fb9a05'>" + result.ping + " ms" + "</font>";
else if (ping >= 200)
ping_value[strs[i]].innerHTML = "<font style='color:red'>" + result.ping + " ms" + "</font>";
const _xhr = (index) => {
return new Promise((res) => {
const dom = nodes[index];
if (!dom) res()
ajax.post('<%=api.url("ping_node")%>', {
index: dom.indexs,
address: dom.address,
port: dom.port,
type: auto_detection_time
},
function(x, result) {
if (x && x.status == 200) {
var strs = dom.indexs.split(",");
for (var i = 0; i < strs.length; i++) {
if (result.ping == null || result.ping.trim() == "") {
ping_value[strs[i]].innerHTML = "<font style='color:red'><%:Timeout%></font>";
} else {
var ping = parseInt(result.ping);
if (ping < 100)
ping_value[strs[i]].innerHTML = "<font style='color:green'>" + result.ping + " ms" + "</font>";
else if (ping < 200)
ping_value[strs[i]].innerHTML = "<font style='color:#fb9a05'>" + result.ping + " ms" + "</font>";
else if (ping >= 200)
ping_value[strs[i]].innerHTML = "<font style='color:red'>" + result.ping + " ms" + "</font>";
}
}
}
res();
},
5000,
function(x) {
var strs = dom.indexs.split(",");
for (var i = 0; i < strs.length; i++) {
ping_value[strs[i]].innerHTML = "<font style='color:red'><%:Timeout%></font>";
}
res();
}
res();
},
5000,
function(x) {
var strs = dom.indexs.split(",");
for (var i = 0; i < strs.length; i++) {
ping_value[strs[i]].innerHTML = "<font style='color:red'><%:Timeout%></font>";
}
res();
}
);
})
}
let task = -1;
const thread = () => {
task = task + 1
if (nodes[task]) {
_xhr(task).then(thread);
);
})
}
let task = -1;
const thread = () => {
task = task + 1
if (nodes[task]) {
_xhr(task).then(thread);
}
}
for (let i = 0; i < 20; i++) {
thread()
}
}
for (let i = 0; i < 20; i++) {
thread()
}
}
@ -445,6 +447,14 @@ table td, .table .td {
}
document.getElementById("div_node_count").innerHTML = "<div style='margin-top:5px'>" + str + "</div>";
}
//UI渲染完成后再自动Ping
window.onload = function () {
setTimeout(function () {
pingAllNodes();
}, 800);
};
//]]>
</script>

View File

@ -355,8 +355,14 @@ msgstr "用于检测连接状态的网址。"
msgid "Probe Interval"
msgstr "探测间隔"
msgid "The interval between initiating probes. Every time this time elapses, a server status check is performed on a server. The time format is numbers + units, such as '10s', '2h45m', and the supported time units are <code>ns</code>, <code>us</code>, <code>ms</code>, <code>s</code>, <code>m</code>, <code>h</code>, which correspond to nanoseconds, microseconds, milliseconds, seconds, minutes, and hours, respectively."
msgstr "发起探测的间隔。每经过这个时间,就会对一个服务器进行服务器状态检测。时间格式为数字+单位,比如<code>&quot;10s&quot;</code>, <code>&quot;2h45m&quot;</code>,支持的时间单位有 <code>ns</code><code>us</code><code>ms</code><code>s</code><code>m</code><code>h</code>,分别对应纳秒、微秒、毫秒、秒、分、时。"
msgid "The interval between initiating probes. The time format is numbers + units, such as '10s', '2h45m', and the supported time units are <code>ns</code>, <code>us</code>, <code>ms</code>, <code>s</code>, <code>m</code>, <code>h</code>, which correspond to nanoseconds, microseconds, milliseconds, seconds, minutes, and hours, respectively."
msgstr "发起探测的间隔。时间格式为数字+单位,比如<code>&quot;10s&quot;</code>, <code>&quot;2h45m&quot;</code>,支持的时间单位有 <code>ns</code><code>us</code><code>ms</code><code>s</code><code>m</code><code>h</code>,分别对应纳秒、微秒、毫秒、秒、分、时。"
msgid "Preferred Node Count"
msgstr "优选节点数量"
msgid "The load balancer selects the optimal number of nodes, and traffic is randomly distributed among them."
msgstr "负载均衡器选出最优节点的个数,流量将在这几个节点中随机分配。"
msgid "Shunt"
msgstr "分流"
@ -406,8 +412,8 @@ msgstr "IPOnDemand当匹配时碰到任何基于 IP 的规则,将域名立
msgid "Load balancing node list"
msgstr "负载均衡节点列表"
msgid "Load balancing node list, <a target='_blank' href='https://toutyrater.github.io/routing/balance2.html'>document</a>"
msgstr "负载均衡节点列表,<a target='_blank' href='https://toutyrater.github.io/routing/balance2.html'>文档原理</a>"
msgid "Load balancing node list, <a target='_blank' href='https://xtls.github.io/config/routing.html#balancerobject'>document</a>"
msgstr "负载均衡节点列表,<a target='_blank' href='https://xtls.github.io/config/routing.html#balancerobject'>文档原理</a>"
msgid "From Share URL"
msgstr "导入分享URL"
@ -1677,3 +1683,9 @@ msgstr "中断现有连接"
msgid "Interrupt existing connections when the selected outbound has changed."
msgstr "当选择的出站发生变化时中断现有连接。"
msgid "Port hopping range"
msgstr "端口跳跃范围"
msgid "Format as 1000:2000 Multiple groups are separated by commas (,)."
msgstr "格式为1000:2000 多组时用逗号(,)隔开。"

View File

@ -8,7 +8,7 @@ server_port=$4
probe_file="/tmp/etc/passwall2/haproxy/Probe_URL"
probeUrl="https://www.google.com/generate_204"
if [ -f "$probe_file" ]; then
firstLine=$(head -n 1 "$probe_file" | tr -d ' \t')
firstLine=$(head -n 1 "$probe_file" | tr -d ' \t\n')
[ -n "$firstLine" ] && probeUrl="$firstLine"
fi

View File

@ -23,7 +23,7 @@ uci:revert(appname)
local has_ss = api.is_finded("ss-redir")
local has_ss_rust = api.is_finded("sslocal")
local has_singbox = api.finded_com("singbox")
local has_singbox = api.finded_com("sing-box")
local has_xray = api.finded_com("xray")
local has_hysteria2 = api.finded_com("hysteria")
local allowInsecure_default = true
@ -182,6 +182,11 @@ do
if true then
local i = 0
local option = "lbss"
local function is_ip_port(str)
if type(str) ~= "string" then return false end
local ip, port = str:match("^([%d%.]+):(%d+)$")
return ip and datatypes.ipaddr(ip) and tonumber(port) and tonumber(port) <= 65535
end
uci:foreach(appname, "haproxy_config", function(t)
i = i + 1
local node_id = t[option]
@ -191,11 +196,17 @@ do
remarks = "HAProxy负载均衡节点列表[" .. i .. "]",
currentNode = node_id and uci:get_all(appname, node_id) or nil,
set = function(o, server)
uci:set(appname, t[".name"], option, server)
o.newNodeId = server
-- 如果当前 lbss 值不是 ip:port 格式,才进行修改
if not is_ip_port(t[option]) then
uci:set(appname, t[".name"], option, server)
o.newNodeId = server
end
end,
delete = function(o)
uci:delete(appname, t[".name"])
-- 如果当前 lbss 值不是 ip:port 格式,才进行删除
if not is_ip_port(t[option]) then
uci:delete(appname, t[".name"])
end
end
}
end)
@ -1294,19 +1305,21 @@ local function processData(szType, content, add_mode, add_from)
end
local function curl(url, file, ua, mode)
local curl_args = api.clone(api.curl_args)
local curl_args = {
"-skL", "-w %{http_code}", "--retry 3", "--connect-timeout 3"
}
if ua and ua ~= "" and ua ~= "curl" then
table.insert(curl_args, '--user-agent "' .. ua .. '"')
curl_args[#curl_args + 1] = '--user-agent "' .. ua .. '"'
end
local return_code
local return_code, result
if mode == "direct" then
return_code = api.curl_direct(url, file, curl_args)
return_code, result = api.curl_direct(url, file, curl_args)
elseif mode == "proxy" then
return_code = api.curl_proxy(url, file, curl_args)
return_code, result = api.curl_proxy(url, file, curl_args)
else
return_code = api.curl_auto(url, file, curl_args)
return_code, result = api.curl_auto(url, file, curl_args)
end
return return_code
return tonumber(result)
end
local function truncate_nodes(add_from)
@ -1630,7 +1643,7 @@ local function parse_link(raw, add_mode, add_from, cfgid)
log('成功解析【' .. add_from .. '】节点数量: ' .. #node_list)
else
if add_mode == "2" then
log('获取到的【' .. add_from .. '】订阅内容为空,可能是订阅地址失效,或是网络问题,请请检测。')
log('获取到的【' .. add_from .. '】订阅内容为空,可能是订阅地址无效,或是网络问题,请诊断!')
end
end
end
@ -1705,23 +1718,27 @@ local execute = function()
local result = (not access_mode) and "自动" or (access_mode == "direct" and "直连访问" or (access_mode == "proxy" and "通过代理" or "自动"))
log('正在订阅:【' .. remark .. '' .. url .. ' [' .. result .. ']')
local tmp_file = "/tmp/" .. cfgid
local raw = curl(url, tmp_file, ua, access_mode)
if raw == 0 then
local f = io.open(tmp_file, "r")
local stdout = f:read("*all")
f:close()
raw = trim(stdout)
local old_md5 = value.md5 or ""
local new_md5 = luci.sys.exec("[ -f " .. tmp_file .. " ] && md5sum " .. tmp_file .. " | awk '{print $1}' || echo 0"):gsub("\n", "")
os.remove(tmp_file)
if old_md5 == new_md5 then
log('订阅:【' .. remark .. '】没有变化,无需更新。')
else
parse_link(raw, "2", remark, cfgid)
uci:set(appname, cfgid, "md5", new_md5)
end
else
value.http_code = curl(url, tmp_file, ua, access_mode)
if value.http_code ~= 200 then
fail_list[#fail_list + 1] = value
else
if luci.sys.call("[ -f " .. tmp_file .. " ] && sed -i -e '/^[ \t]*$/d' -e '/^[ \t]*\r$/d' " .. tmp_file) == 0 then
local f = io.open(tmp_file, "r")
local stdout = f:read("*all")
f:close()
local raw_data = trim(stdout)
local old_md5 = value.md5 or ""
local new_md5 = luci.sys.exec("md5sum " .. tmp_file .. " 2>/dev/null | awk '{print $1}'"):gsub("\n", "")
os.remove(tmp_file)
if old_md5 == new_md5 then
log('订阅:【' .. remark .. '】没有变化,无需更新。')
else
parse_link(raw_data, "2", remark, cfgid)
uci:set(appname, cfgid, "md5", new_md5)
end
else
fail_list[#fail_list + 1] = value
end
end
allowInsecure_default = true
filter_keyword_mode_default = uci:get(appname, "@global_subscribe[0]", "filter_keyword_mode") or "0"
@ -1736,7 +1753,7 @@ local execute = function()
if #fail_list > 0 then
for index, value in ipairs(fail_list) do
log(string.format('【%s】订阅失败可能是订阅地址失效,或是网络问题,请诊断!', value.remark))
log(string.format('【%s】订阅失败可能是订阅地址无效,或是网络问题,请诊断![%s]', value.remark, tostring(value.http_code)))
end
end
update_node(0)