luci: update and fix the subscribe module

This commit is contained in:
xiaorouji 2024-01-09 02:52:51 +08:00 committed by sbwml
parent 40caf0ed97
commit daee7a394b
5 changed files with 248 additions and 49 deletions

View File

@ -6,27 +6,46 @@ local has_trojan_plus = api.is_finded("trojan-plus")
local has_singbox = api.finded_com("singbox") local has_singbox = api.finded_com("singbox")
local has_xray = api.finded_com("xray") local has_xray = api.finded_com("xray")
local has_trojan_go = api.finded_com("trojan-go") local has_trojan_go = api.finded_com("trojan-go")
local has_hysteria2 = api.finded_com("hysteria")
local ss_aead_type = {} local ss_aead_type = {}
local trojan_type = {} local trojan_type = {}
local vmess_type = {}
local vless_type = {}
local hysteria2_type = {}
if has_ss then if has_ss then
ss_aead_type[#ss_aead_type + 1] = "shadowsocks-libev" local s = "shadowsocks-libev"
table.insert(ss_aead_type, s)
end end
if has_ss_rust then if has_ss_rust then
ss_aead_type[#ss_aead_type + 1] = "shadowsocks-rust" local s = "shadowsocks-rust"
table.insert(ss_aead_type, s)
end end
if has_trojan_plus then if has_trojan_plus then
trojan_type[#trojan_type + 1] = "trojan-plus" local s = "trojan-plus"
table.insert(trojan_type, s)
end end
if has_singbox then if has_singbox then
trojan_type[#trojan_type + 1] = "sing-box" local s = "sing-box"
ss_aead_type[#ss_aead_type + 1] = "sing-box" table.insert(trojan_type, s)
table.insert(ss_aead_type, s)
table.insert(vmess_type, s)
table.insert(vless_type, s)
table.insert(hysteria2_type, s)
end end
if has_xray then if has_xray then
trojan_type[#trojan_type + 1] = "xray" local s = "xray"
ss_aead_type[#ss_aead_type + 1] = "xray" table.insert(trojan_type, s)
table.insert(ss_aead_type, s)
table.insert(vmess_type, s)
table.insert(vless_type, s)
end end
if has_trojan_go then if has_trojan_go then
trojan_type[#trojan_type + 1] = "trojan-go" local s = "trojan-go"
table.insert(trojan_type, s)
end
if has_hysteria2 then
local s = "hysteria2"
table.insert(hysteria2_type, s)
end end
m = Map(appname) m = Map(appname)
@ -47,16 +66,46 @@ o = s:option(DynamicList, "filter_discard_list", translate("Discard List"))
o = s:option(DynamicList, "filter_keep_list", translate("Keep List")) o = s:option(DynamicList, "filter_keep_list", translate("Keep List"))
if #ss_aead_type > 0 then if #ss_aead_type > 0 then
o = s:option(ListValue, "ss_aead_type", translate("SS AEAD Node Use Type")) o = s:option(ListValue, "ss_aead_type", translatef("%s Node Use Type", "SS AEAD"))
for key, value in pairs(ss_aead_type) do for key, value in pairs(ss_aead_type) do
o:value(value, translate(value:gsub("^%l",string.upper))) o:value(value)
end end
end end
if #trojan_type > 0 then if #trojan_type > 0 then
o = s:option(ListValue, "trojan_type", translate("Trojan Node Use Type")) o = s:option(ListValue, "trojan_type", translatef("%s Node Use Type", "Trojan"))
for key, value in pairs(trojan_type) do for key, value in pairs(trojan_type) do
o:value(value, translate(value:gsub("^%l",string.upper))) o:value(value)
end
end
if #vmess_type > 0 then
o = s:option(ListValue, "vmess_type", translatef("%s Node Use Type", "VMess"))
for key, value in pairs(vmess_type) do
o:value(value)
end
if has_xray then
o.default = "xray"
end
end
if #vless_type > 0 then
o = s:option(ListValue, "vless_type", translatef("%s Node Use Type", "VLESS"))
for key, value in pairs(vless_type) do
o:value(value)
end
if has_xray then
o.default = "xray"
end
end
if #hysteria2_type > 0 then
o = s:option(ListValue, "hysteria2_type", translatef("%s Node Use Type", "Hysteria2"))
for key, value in pairs(hysteria2_type) do
o:value(value)
end
if has_hysteria2 then
o.default = "hysteria2"
end end
end end

View File

@ -1,33 +1,51 @@
local api = require "luci.passwall.api" local api = require "luci.passwall.api"
local appname = api.appname local appname = api.appname
local sys = api.sys
local has_ss = api.is_finded("ss-redir") local has_ss = api.is_finded("ss-redir")
local has_ss_rust = api.is_finded("sslocal") local has_ss_rust = api.is_finded("sslocal")
local has_trojan_plus = api.is_finded("trojan-plus") local has_trojan_plus = api.is_finded("trojan-plus")
local has_singbox = api.finded_com("singbox") local has_singbox = api.finded_com("singbox")
local has_xray = api.finded_com("xray") local has_xray = api.finded_com("xray")
local has_trojan_go = api.finded_com("trojan-go") local has_trojan_go = api.finded_com("trojan-go")
local has_hysteria2 = api.finded_com("hysteria")
local ss_aead_type = {} local ss_aead_type = {}
local trojan_type = {} local trojan_type = {}
local vmess_type = {}
local vless_type = {}
local hysteria2_type = {}
if has_ss then if has_ss then
ss_aead_type[#ss_aead_type + 1] = "shadowsocks-libev" local s = "shadowsocks-libev"
table.insert(ss_aead_type, s)
end end
if has_ss_rust then if has_ss_rust then
ss_aead_type[#ss_aead_type + 1] = "shadowsocks-rust" local s = "shadowsocks-rust"
table.insert(ss_aead_type, s)
end end
if has_trojan_plus then if has_trojan_plus then
trojan_type[#trojan_type + 1] = "trojan-plus" local s = "trojan-plus"
table.insert(trojan_type, s)
end end
if has_singbox then if has_singbox then
trojan_type[#trojan_type + 1] = "sing-box" local s = "sing-box"
ss_aead_type[#ss_aead_type + 1] = "sing-box" table.insert(trojan_type, s)
table.insert(ss_aead_type, s)
table.insert(vmess_type, s)
table.insert(vless_type, s)
table.insert(hysteria2_type, s)
end end
if has_xray then if has_xray then
trojan_type[#trojan_type + 1] = "xray" local s = "xray"
ss_aead_type[#ss_aead_type + 1] = "xray" table.insert(trojan_type, s)
table.insert(ss_aead_type, s)
table.insert(vmess_type, s)
table.insert(vless_type, s)
end end
if has_trojan_go then if has_trojan_go then
trojan_type[#trojan_type + 1] = "trojan-go" local s = "trojan-go"
table.insert(trojan_type, s)
end
if has_hysteria2 then
local s = "hysteria2"
table.insert(hysteria2_type, s)
end end
m = Map(appname) m = Map(appname)
@ -68,20 +86,47 @@ o:depends("filter_keyword_mode", "3")
o:depends("filter_keyword_mode", "4") o:depends("filter_keyword_mode", "4")
if #ss_aead_type > 0 then if #ss_aead_type > 0 then
o = s:option(ListValue, "ss_aead_type", translate("SS AEAD Node Use Type")) o = s:option(ListValue, "ss_aead_type", translatef("%s Node Use Type", "SS AEAD"))
o.default = "global" o.default = "global"
o:value("global", translate("Use global config")) o:value("global", translate("Use global config"))
for key, value in pairs(ss_aead_type) do for key, value in pairs(ss_aead_type) do
o:value(value, translate(value:gsub("^%l",string.upper))) o:value(value)
end end
end end
if #trojan_type > 0 then if #trojan_type > 0 then
o = s:option(ListValue, "trojan_type", translate("Trojan Node Use Type")) o = s:option(ListValue, "trojan_type", translatef("%s Node Use Type", "Trojan"))
o.default = "global" o.default = "global"
o:value("global", translate("Use global config")) o:value("global", translate("Use global config"))
for key, value in pairs(trojan_type) do for key, value in pairs(trojan_type) do
o:value(value, translate(value:gsub("^%l",string.upper))) o:value(value)
end
end
if #vmess_type > 0 then
o = s:option(ListValue, "vmess_type", translatef("%s Node Use Type", "VMess"))
o.default = "global"
o:value("global", translate("Use global config"))
for key, value in pairs(vmess_type) do
o:value(value)
end
end
if #vless_type > 0 then
o = s:option(ListValue, "vless_type", translatef("%s Node Use Type", "VLESS"))
o.default = "global"
o:value("global", translate("Use global config"))
for key, value in pairs(vless_type) do
o:value(value)
end
end
if #hysteria2_type > 0 then
o = s:option(ListValue, "hysteria2_type", translatef("%s Node Use Type", "Hysteria2"))
o.default = "global"
o:value("global", translate("Use global config"))
for key, value in pairs(hysteria2_type) do
o:value(value)
end end
end end

View File

@ -5,6 +5,7 @@ local api = require "luci.passwall.api"
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
let has_singbox = "<%=api.finded_com("singbox")%>" let has_singbox = "<%=api.finded_com("singbox")%>"
let has_xray = "<%=api.finded_com("xray")%>" let has_xray = "<%=api.finded_com("xray")%>"
let has_hysteria2 = "<%=api.finded_com("hysteria")%>"
function padright(str, cnt, pad) { function padright(str, cnt, pad) {
return str + Array(cnt + 1).join(pad); return str + Array(cnt + 1).join(pad);
@ -453,14 +454,21 @@ local api = require "luci.passwall.api"
} }
url += url_protocol; url += url_protocol;
url += params; url += params;
} else if (v_type === "Hysteria2") { } else if ((v_type === "Hysteria2") || (v_type === "sing-box" && opt.get(dom_prefix + "protocol").value === "hysteria2")) {
var v_port = opt.get(dom_prefix + "port"); var v_port = opt.get(dom_prefix + "port");
var params = ""; var params = "";
params += opt.query("auth", dom_prefix + "auth_password");
params += opt.query("sni", dom_prefix + "tls_serverName"); params += opt.query("sni", dom_prefix + "tls_serverName");
params += opt.query("insecure", dom_prefix + "tls_allowInsecure"); params += opt.query("insecure", dom_prefix + "tls_allowInsecure");
params += opt.query("obfs", "salamander"); params += opt.query("obfs", "salamander");
params += opt.query("obfs-password", dom_prefix + "obfs"); if (v_type === "Hysteria2") {
params += opt.query("obfs-password", "hysteria2_obfs");
params += opt.query("auth", "hysteria2_auth_password");
params += opt.query("pinSHA256", "hysteria2_tls_pinSHA256");
} else {
params += opt.query("obfs-password", dom_prefix + "hysteria2_obfs_password");
params += opt.query("auth", dom_prefix + "hysteria2_auth_password");
}
var url = var url =
_address + ":" + _address + ":" +
v_port.value + "?" + v_port.value + "?" +
@ -839,7 +847,8 @@ local api = require "luci.passwall.api"
if (has_singbox) { if (has_singbox) {
opt.set('type', "sing-box"); opt.set('type', "sing-box");
dom_prefix = "singbox_" dom_prefix = "singbox_"
} else if (has_xray) { }
if (has_xray) {
opt.set('type', "Xray"); opt.set('type', "Xray");
dom_prefix = "xray_" dom_prefix = "xray_"
} }
@ -888,12 +897,13 @@ local api = require "luci.passwall.api"
} }
} }
if (ssu[0] === "vless") { if (ssu[0] === "vless") {
if (has_singbox) {
opt.set('type', "sing-box");
dom_prefix = "singbox_"
}
if (has_xray) { if (has_xray) {
opt.set('type', "Xray"); opt.set('type', "Xray");
dom_prefix = "xray_" dom_prefix = "xray_"
} else if (has_singbox) {
opt.set('type', "sing-box");
dom_prefix = "singbox_"
} }
opt.set(dom_prefix + 'protocol', "vless"); opt.set(dom_prefix + 'protocol', "vless");
var m = parseNodeUrl(ssrurl); var m = parseNodeUrl(ssrurl);
@ -1037,14 +1047,7 @@ local api = require "luci.passwall.api"
opt.set('remarks', decodeURI(m.hash.substr(1))); opt.set('remarks', decodeURI(m.hash.substr(1)));
} }
} }
if (ssu[0] === "hysteria2") { if (ssu[0] === "hysteria2" || ssu[0] === "hy2") {
if (has_singbox) {
opt.set('type', "sing-box");
dom_prefix = "singbox_"
} else {
opt.set('type', "Hysteria2");
dom_prefix = "hysteria2_"
}
var m = parseNodeUrl(ssrurl); var m = parseNodeUrl(ssrurl);
var queryParam = {}; var queryParam = {};
if (m.search.length > 1) { if (m.search.length > 1) {
@ -1057,10 +1060,28 @@ local api = require "luci.passwall.api"
queryParam[decodeURIComponent(params[0])] = decodeURIComponent(params[1] || ''); queryParam[decodeURIComponent(params[0])] = decodeURIComponent(params[1] || '');
} }
} }
if (has_singbox) {
opt.set('type', "sing-box");
dom_prefix = "singbox_"
opt.set(dom_prefix + 'protocol', "hysteria2");
opt.set(dom_prefix + 'hysteria2_obfs_type', "salamander");
opt.set(dom_prefix + 'hysteria2_obfs_password', queryParam["obfs-password"]);
opt.set(dom_prefix + 'hysteria2_auth_password', queryParam.auth);
}
if (has_hysteria2) {
opt.set('type', "Hysteria2");
dom_prefix = "hysteria2_"
opt.set(dom_prefix + 'obfs', queryParam["obfs-password"]);
opt.set(dom_prefix + 'auth_password', queryParam.auth);
if (queryParam.pinSHA256) {
opt.set(dom_prefix + 'tls_pinSHA256', queryParam.pinSHA256);
}
}
opt.set(dom_prefix + 'address', m.hostname); opt.set(dom_prefix + 'address', m.hostname);
opt.set(dom_prefix + 'port', m.port || "443"); opt.set(dom_prefix + 'port', m.port || "443");
opt.set(dom_prefix + 'obfs', queryParam["obfs-password"]);
opt.set(dom_prefix + 'auth', queryParam.auth);
opt.set(dom_prefix + 'tls_serverName', queryParam.sni); opt.set(dom_prefix + 'tls_serverName', queryParam.sni);
if (queryParam.insecure && queryParam.insecure == "1") { if (queryParam.insecure && queryParam.insecure == "1") {
opt.set(dom_prefix + 'tls_allowInsecure', true); opt.set(dom_prefix + 'tls_allowInsecure', true);

View File

@ -1180,11 +1180,8 @@ msgstr "允许不安全连接"
msgid "Whether unsafe connections are allowed. When checked, Certificate validation will be skipped." msgid "Whether unsafe connections are allowed. When checked, Certificate validation will be skipped."
msgstr "是否允许不安全连接。当勾选时,将跳过证书验证。" msgstr "是否允许不安全连接。当勾选时,将跳过证书验证。"
msgid "SS AEAD Node Use Type" msgid "%s Node Use Type"
msgstr "SS AEAD节点使用类型" msgstr "%s 节点使用类型"
msgid "Trojan Node Use Type"
msgstr "Trojan节点使用类型"
msgid "Set the TUIC proxy server ip address" msgid "Set the TUIC proxy server ip address"
msgstr "指定远程TUIC服务器IP" msgstr "指定远程TUIC服务器IP"

View File

@ -28,9 +28,13 @@ local has_trojan_plus = api.is_finded("trojan-plus")
local has_singbox = api.finded_com("singbox") local has_singbox = api.finded_com("singbox")
local has_xray = api.finded_com("xray") local has_xray = api.finded_com("xray")
local has_trojan_go = api.finded_com("trojan-go") local has_trojan_go = api.finded_com("trojan-go")
local has_hysteria2 = api.finded_com("hysteria")
local allowInsecure_default = nil local allowInsecure_default = nil
local ss_aead_type_default = uci:get(appname, "@global_subscribe[0]", "ss_aead_type") or "shadowsocks-libev" local ss_aead_type_default = uci:get(appname, "@global_subscribe[0]", "ss_aead_type") or "shadowsocks-libev"
local trojan_type_default = uci:get(appname, "@global_subscribe[0]", "trojan_type") or "trojan-plus" local trojan_type_default = uci:get(appname, "@global_subscribe[0]", "trojan_type") or "trojan-plus"
local vmess_type_default = uci:get(appname, "@global_subscribe[0]", "vmess_type") or "xray"
local vless_type_default = uci:get(appname, "@global_subscribe[0]", "vless_type") or "xray"
local hysteria2_type_default = uci:get(appname, "@global_subscribe[0]", "hysteria2_type") or "hysteria2"
-- 判断是否过滤节点关键字 -- 判断是否过滤节点关键字
local filter_keyword_mode_default = uci:get(appname, "@global_subscribe[0]", "filter_keyword_mode") or "0" local filter_keyword_mode_default = uci:get(appname, "@global_subscribe[0]", "filter_keyword_mode") or "0"
local filter_keyword_discard_list_default = uci:get(appname, "@global_subscribe[0]", "filter_discard_list") or {} local filter_keyword_discard_list_default = uci:get(appname, "@global_subscribe[0]", "filter_discard_list") or {}
@ -376,9 +380,16 @@ local function processData(szType, content, add_mode, add_from)
local info = jsonParse(content) local info = jsonParse(content)
if has_singbox then if has_singbox then
result.type = 'sing-box' result.type = 'sing-box'
elseif has_xray then end
if has_xray then
result.type = 'Xray' result.type = 'Xray'
end end
if vmess_type_default == "sing-box" and has_singbox then
result.type = 'sing-box'
end
if vmess_type_default == "xray" and has_xray then
result.type = "Xray"
end
result.alter_id = info.aid result.alter_id = info.aid
result.address = info.add result.address = info.add
result.port = info.port result.port = info.port
@ -706,6 +717,12 @@ local function processData(szType, content, add_mode, add_from)
if has_xray then if has_xray then
result.type = 'Xray' result.type = 'Xray'
end end
if vless_type_default == "sing-box" and has_singbox then
result.type = 'sing-box'
end
if vless_type_default == "xray" and has_xray then
result.type = "Xray"
end
result.protocol = "vless" result.protocol = "vless"
local alias = "" local alias = ""
if content:find("#") then if content:find("#") then
@ -806,7 +823,6 @@ local function processData(szType, content, add_mode, add_from)
content = content:sub(0, idx_sp - 1) content = content:sub(0, idx_sp - 1)
end end
result.remarks = UrlDecode(alias) result.remarks = UrlDecode(alias)
result.type = "Hysteria"
local dat = split(content, '%?') local dat = split(content, '%?')
local host_port = dat[1] local host_port = dat[1]
@ -844,6 +860,62 @@ local function processData(szType, content, add_mode, add_from)
result.hysteria_alpn = params.alpn result.hysteria_alpn = params.alpn
result.hysteria_up_mbps = params.upmbps result.hysteria_up_mbps = params.upmbps
result.hysteria_down_mbps = params.downmbps result.hysteria_down_mbps = params.downmbps
if has_singbox then
result.type = 'sing-box'
result.protocol = "hysteria"
end
elseif szType == 'hysteria2' or szType == 'hy2' then
local alias = ""
if content:find("#") then
local idx_sp = content:find("#")
alias = content:sub(idx_sp + 1, -1)
content = content:sub(0, idx_sp - 1)
end
result.remarks = UrlDecode(alias)
local dat = split(content, '%?')
local host_port = dat[1]
local params = {}
for _, v in pairs(split(dat[2], '&')) do
local t = split(v, '=')
if #t > 0 then
params[t[1]] = t[2]
end
end
-- [2001:4860:4860::8888]:443
-- 8.8.8.8:443
if host_port:find(":") then
local sp = split(host_port, ":")
result.port = sp[#sp]
if api.is_ipv6addrport(host_port) then
result.address = api.get_ipv6_only(host_port)
else
result.address = sp[1]
end
else
result.address = host_port
end
result.hysteria2_auth_password = params.auth
result.tls_serverName = params.sni
if params.insecure and (params.insecure == "1" or params.insecure == "0") then
result.tls_allowInsecure = params.insecure
--log(result.remarks ..' 使用节点AllowInsecure设定: '.. result.tls_allowInsecure)
else
result.tls_allowInsecure = allowInsecure_default and "1" or "0"
end
result.hysteria2_tls_pinSHA256 = params.pinSHA256
if has_hysteria2 then
result.type = "Hysteria2"
result.hysteria2_obfs = params["obfs-password"]
end
if hysteria2_type_default == "sing-box" and has_singbox then
result.type = 'sing-box'
result.protocol = "hysteria2"
result.hysteria2_obfs_type = "salamander"
result.hysteria2_obfs_password = params["obfs-password"]
end
else else
log('暂时不支持' .. szType .. "类型的节点订阅,跳过此节点。") log('暂时不支持' .. szType .. "类型的节点订阅,跳过此节点。")
return nil return nil
@ -1216,6 +1288,18 @@ local execute = function()
if trojan_type ~= "global" then if trojan_type ~= "global" then
trojan_type_default = trojan_type trojan_type_default = trojan_type
end end
local vmess_type = value.vmess_type or "global"
if vmess_type ~= "global" then
vmess_type_default = vmess_type
end
local vless_type = value.vless_type or "global"
if vless_type ~= "global" then
vless_type_default = vless_type
end
local hysteria2_type = value.hysteria2_type or "global"
if hysteria2_type ~= "global" then
hysteria2_type_default = hysteria2_type
end
local ua = value.user_agent local ua = value.user_agent
log('正在订阅:【' .. remark .. '' .. url) log('正在订阅:【' .. remark .. '' .. url)
local raw = curl(url, "/tmp/" .. cfgid, ua) local raw = curl(url, "/tmp/" .. cfgid, ua)
@ -1235,6 +1319,9 @@ local execute = function()
filter_keyword_keep_list_default = uci:get(appname, "@global_subscribe[0]", "filter_keep_list") or {} filter_keyword_keep_list_default = uci:get(appname, "@global_subscribe[0]", "filter_keep_list") or {}
ss_aead_type_default = uci:get(appname, "@global_subscribe[0]", "ss_aead_type") or "shadowsocks-libev" ss_aead_type_default = uci:get(appname, "@global_subscribe[0]", "ss_aead_type") or "shadowsocks-libev"
trojan_type_default = uci:get(appname, "@global_subscribe[0]", "trojan_type") or "trojan-plus" trojan_type_default = uci:get(appname, "@global_subscribe[0]", "trojan_type") or "trojan-plus"
vmess_type_default = uci:get(appname, "@global_subscribe[0]", "vmess_type") or "xray"
vless_type_default = uci:get(appname, "@global_subscribe[0]", "vless_type") or "xray"
hysteria2_type_default = uci:get(appname, "@global_subscribe[0]", "hysteria2_type") or "hysteria2"
end end
if #fail_list > 0 then if #fail_list > 0 then