mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-19 03:43:29 +00:00
luci-app-ssr-plus: optimize subscribe script and support ssd subscribe (#2726)
* luci-app-ssr-plus: optimize subscribe script and support ssd subscribe * luci-app-ssr-plus: optimize ping test and added socket test * luci-app-ssr-plus: fix script path * luci-app-ssr-plus: optimize script * luci-app-ssr-plus: optimize script and remove /tmp/ssrpro.log * luci-app-ssr-plus: adjust log function * luci-app-ssr-plus: fix index * luci-app-ssr-plus: adjust content
This commit is contained in:
parent
4da966dae3
commit
9fcb30d870
@ -9,61 +9,81 @@ function index()
|
||||
end
|
||||
|
||||
|
||||
entry({"admin", "services", "shadowsocksr"},alias("admin", "services", "shadowsocksr", "client"),_("ShadowSocksR Plus+"), 10).dependent = true
|
||||
entry({"admin", "services", "shadowsocksr"}, alias("admin", "services", "shadowsocksr", "client"),_("ShadowSocksR Plus+"), 10).dependent = true
|
||||
|
||||
entry({"admin", "services", "shadowsocksr", "client"}, cbi("shadowsocksr/client"),_("SSR Client"), 10).leaf = true
|
||||
|
||||
entry({"admin", "services", "shadowsocksr", "client"},cbi("shadowsocksr/client"),_("SSR Client"), 10).leaf = true
|
||||
|
||||
entry({"admin", "services", "shadowsocksr", "servers"}, arcombine(cbi("shadowsocksr/servers", {autoapply=true}), cbi("shadowsocksr/client-config")),_("Severs Nodes"), 20).leaf = true
|
||||
|
||||
entry({"admin", "services", "shadowsocksr", "control"},cbi("shadowsocksr/control"),_("Access Control"), 30).leaf = true
|
||||
|
||||
|
||||
entry({"admin", "services", "shadowsocksr", "control"},cbi("shadowsocksr/control"), _("Access Control"), 30).leaf = true
|
||||
|
||||
-- entry({"admin", "services", "shadowsocksr", "list"},form("shadowsocksr/list"),_("GFW List"), 40).leaf = true
|
||||
|
||||
|
||||
entry({"admin", "services", "shadowsocksr", "advanced"},cbi("shadowsocksr/advanced"),_("Advanced Settings"), 50).leaf = true
|
||||
|
||||
|
||||
if nixio.fs.access("/usr/bin/ssr-server") then
|
||||
entry({"admin", "services", "shadowsocksr", "server"},arcombine(cbi("shadowsocksr/server"), cbi("shadowsocksr/server-config")),_("SSR Server"), 60).leaf = true
|
||||
entry({"admin", "services", "shadowsocksr", "server"},arcombine(cbi("shadowsocksr/server"), cbi("shadowsocksr/server-config")),_("SSR Server"), 60).leaf = true
|
||||
end
|
||||
|
||||
|
||||
entry({"admin", "services", "shadowsocksr", "status"},form("shadowsocksr/status"),_("Status"), 70).leaf = true
|
||||
|
||||
|
||||
entry({"admin", "services", "shadowsocksr", "check"}, call("check_status"))
|
||||
entry({"admin", "services", "shadowsocksr", "refresh"}, call("refresh_data"))
|
||||
entry({"admin", "services", "shadowsocksr", "subscribe"}, call("subscribe"))
|
||||
|
||||
entry({"admin", "services", "shadowsocksr", "checkport"}, call("check_port"))
|
||||
|
||||
|
||||
entry({"admin", "services", "shadowsocksr", "log"},form("shadowsocksr/log"),_("Log"), 80).leaf = true
|
||||
|
||||
|
||||
entry({"admin", "services", "shadowsocksr","run"},call("act_status")).leaf=true
|
||||
|
||||
|
||||
entry({"admin", "services", "shadowsocksr", "ping"}, call("act_ping")).leaf=true
|
||||
|
||||
|
||||
end
|
||||
|
||||
function subscribe()
|
||||
luci.sys.call("/usr/bin/lua /usr/share/shadowsocksr/subscribe.lua >> /tmp/ssrplus.log 2>&1")
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ ret = 1 })
|
||||
end
|
||||
|
||||
function act_status()
|
||||
local e={}
|
||||
e.running=luci.sys.call("busybox ps -w | grep ssr-retcp | grep -v grep >/dev/null")==0
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
local e={}
|
||||
e.running=luci.sys.call("busybox ps -w | grep ssr-retcp | grep -v grep >/dev/null")==0
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
|
||||
function act_ping()
|
||||
local e={}
|
||||
e.index=luci.http.formvalue("index")
|
||||
e.ping=luci.sys.exec("ping -c 1 -W 1 %q 2>&1 | grep -o 'time=[0-9]*.[0-9]' | awk -F '=' '{print$2}'"%luci.http.formvalue("domain"))
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
local e = {}
|
||||
local domain = luci.http.formvalue("domain")
|
||||
local port = luci.http.formvalue("port")
|
||||
e.index = luci.http.formvalue("index")
|
||||
e.ping = luci.sys.exec("ping -c 1 -W 1 %q 2>&1 | grep -o 'time=[0-9]*.[0-9]' | awk -F '=' '{print$2}'" % domain)
|
||||
|
||||
local iret = luci.sys.call(" ipset add ss_spec_wan_ac " .. domain .. " 2>/dev/null")
|
||||
local socket = nixio.socket("inet", "stream")
|
||||
socket:setopt("socket", "rcvtimeo", 3)
|
||||
socket:setopt("socket", "sndtimeo", 3)
|
||||
e.socket = socket:connect(domain, port)
|
||||
socket:close()
|
||||
if (iret == 0) then
|
||||
luci.sys.call(" ipset del ss_spec_wan_ac " .. domain)
|
||||
end
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
|
||||
function check_status()
|
||||
local set ="/usr/bin/ssr-check www." .. luci.http.formvalue("set") .. ".com 80 3 1"
|
||||
sret=luci.sys.call(set)
|
||||
if sret== 0 then
|
||||
retstring ="0"
|
||||
else
|
||||
retstring ="1"
|
||||
end
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ ret=retstring })
|
||||
local set = "/usr/bin/ssr-check www." .. luci.http.formvalue("set") .. ".com 80 3 1"
|
||||
sret = luci.sys.call(set)
|
||||
if sret == 0 then
|
||||
retstring ="0"
|
||||
else
|
||||
retstring ="1"
|
||||
end
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ ret=retstring })
|
||||
end
|
||||
|
||||
function refresh_data()
|
||||
@ -72,84 +92,84 @@ local icount =0
|
||||
|
||||
if set == "gfw_data" then
|
||||
if nixio.fs.access("/usr/bin/wget-ssl") then
|
||||
refresh_cmd="wget-ssl --no-check-certificate https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt -O /tmp/gfw.b64"
|
||||
refresh_cmd="wget-ssl --no-check-certificate https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt -O /tmp/gfw.b64"
|
||||
else
|
||||
refresh_cmd="wget -O /tmp/gfw.b64 http://iytc.net/tools/list.b64"
|
||||
refresh_cmd="wget -O /tmp/gfw.b64 http://iytc.net/tools/list.b64"
|
||||
end
|
||||
sret=luci.sys.call(refresh_cmd .. " 2>/dev/null")
|
||||
if sret== 0 then
|
||||
luci.sys.call("/usr/bin/ssr-gfw")
|
||||
icount = luci.sys.exec("cat /tmp/gfwnew.txt | wc -l")
|
||||
if tonumber(icount)>1000 then
|
||||
oldcount=luci.sys.exec("cat /etc/dnsmasq.ssr/gfw_list.conf | wc -l")
|
||||
if tonumber(icount) ~= tonumber(oldcount) then
|
||||
luci.sys.exec("cp -f /tmp/gfwnew.txt /etc/dnsmasq.ssr/gfw_list.conf")
|
||||
retstring=tostring(math.ceil(tonumber(icount)/2))
|
||||
else
|
||||
retstring ="0"
|
||||
end
|
||||
else
|
||||
retstring ="-1"
|
||||
end
|
||||
luci.sys.exec("rm -f /tmp/gfwnew.txt ")
|
||||
luci.sys.call("/usr/bin/ssr-gfw")
|
||||
icount = luci.sys.exec("cat /tmp/gfwnew.txt | wc -l")
|
||||
if tonumber(icount)>1000 then
|
||||
oldcount=luci.sys.exec("cat /etc/dnsmasq.ssr/gfw_list.conf | wc -l")
|
||||
if tonumber(icount) ~= tonumber(oldcount) then
|
||||
luci.sys.exec("cp -f /tmp/gfwnew.txt /etc/dnsmasq.ssr/gfw_list.conf")
|
||||
retstring=tostring(math.ceil(tonumber(icount)/2))
|
||||
else
|
||||
retstring ="0"
|
||||
end
|
||||
else
|
||||
retstring ="-1"
|
||||
end
|
||||
luci.sys.exec("rm -f /tmp/gfwnew.txt ")
|
||||
else
|
||||
retstring ="-1"
|
||||
retstring ="-1"
|
||||
end
|
||||
elseif set == "ip_data" then
|
||||
refresh_cmd="wget -O- 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest' 2>/dev/null| awk -F\\| '/CN\\|ipv4/ { printf(\"%s/%d\\n\", $4, 32-log($5)/log(2)) }' > /tmp/china_ssr.txt"
|
||||
sret=luci.sys.call(refresh_cmd)
|
||||
icount = luci.sys.exec("cat /tmp/china_ssr.txt | wc -l")
|
||||
if sret== 0 and tonumber(icount)>1000 then
|
||||
oldcount=luci.sys.exec("cat /etc/china_ssr.txt | wc -l")
|
||||
if tonumber(icount) ~= tonumber(oldcount) then
|
||||
luci.sys.exec("cp -f /tmp/china_ssr.txt /etc/china_ssr.txt")
|
||||
retstring=tostring(tonumber(icount))
|
||||
else
|
||||
retstring ="0"
|
||||
end
|
||||
oldcount=luci.sys.exec("cat /etc/china_ssr.txt | wc -l")
|
||||
if tonumber(icount) ~= tonumber(oldcount) then
|
||||
luci.sys.exec("cp -f /tmp/china_ssr.txt /etc/china_ssr.txt")
|
||||
retstring=tostring(tonumber(icount))
|
||||
else
|
||||
retstring ="0"
|
||||
end
|
||||
|
||||
else
|
||||
retstring ="-1"
|
||||
retstring ="-1"
|
||||
end
|
||||
luci.sys.exec("rm -f /tmp/china_ssr.txt ")
|
||||
else
|
||||
local need_process = 0
|
||||
if nixio.fs.access("/usr/bin/wget-ssl") then
|
||||
refresh_cmd="wget-ssl --no-check-certificate -O - https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt > /tmp/adnew.conf"
|
||||
need_process = 1
|
||||
local need_process = 0
|
||||
if nixio.fs.access("/usr/bin/wget-ssl") then
|
||||
refresh_cmd="wget-ssl --no-check-certificate -O - https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt > /tmp/adnew.conf"
|
||||
need_process = 1
|
||||
else
|
||||
refresh_cmd="wget -O /tmp/ad.conf http://iytc.net/tools/ad.conf"
|
||||
refresh_cmd="wget -O /tmp/ad.conf http://iytc.net/tools/ad.conf"
|
||||
end
|
||||
sret=luci.sys.call(refresh_cmd .. " 2>/dev/null")
|
||||
if sret== 0 then
|
||||
if need_process == 1 then
|
||||
luci.sys.call("/usr/bin/ssr-ad")
|
||||
end
|
||||
icount = luci.sys.exec("cat /tmp/ad.conf | wc -l")
|
||||
if tonumber(icount)>1000 then
|
||||
if nixio.fs.access("/etc/dnsmasq.ssr/ad.conf") then
|
||||
oldcount=luci.sys.exec("cat /etc/dnsmasq.ssr/ad.conf | wc -l")
|
||||
else
|
||||
oldcount=0
|
||||
end
|
||||
|
||||
if tonumber(icount) ~= tonumber(oldcount) then
|
||||
luci.sys.exec("cp -f /tmp/ad.conf /etc/dnsmasq.ssr/ad.conf")
|
||||
retstring=tostring(math.ceil(tonumber(icount)))
|
||||
if oldcount==0 then
|
||||
luci.sys.call("/etc/init.d/dnsmasq restart")
|
||||
end
|
||||
else
|
||||
retstring ="0"
|
||||
end
|
||||
else
|
||||
retstring ="-1"
|
||||
end
|
||||
luci.sys.exec("rm -f /tmp/ad.conf ")
|
||||
if need_process == 1 then
|
||||
luci.sys.call("/usr/bin/ssr-ad")
|
||||
end
|
||||
icount = luci.sys.exec("cat /tmp/ad.conf | wc -l")
|
||||
if tonumber(icount)>1000 then
|
||||
if nixio.fs.access("/etc/dnsmasq.ssr/ad.conf") then
|
||||
oldcount=luci.sys.exec("cat /etc/dnsmasq.ssr/ad.conf | wc -l")
|
||||
else
|
||||
oldcount=0
|
||||
end
|
||||
|
||||
if tonumber(icount) ~= tonumber(oldcount) then
|
||||
luci.sys.exec("cp -f /tmp/ad.conf /etc/dnsmasq.ssr/ad.conf")
|
||||
retstring=tostring(math.ceil(tonumber(icount)))
|
||||
if oldcount==0 then
|
||||
luci.sys.call("/etc/init.d/dnsmasq restart")
|
||||
end
|
||||
else
|
||||
retstring ="0"
|
||||
end
|
||||
else
|
||||
retstring ="-1"
|
||||
end
|
||||
luci.sys.exec("rm -f /tmp/ad.conf ")
|
||||
else
|
||||
retstring ="-1"
|
||||
retstring ="-1"
|
||||
end
|
||||
end
|
||||
end
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ ret=retstring ,retcount=icount})
|
||||
end
|
||||
@ -181,7 +201,7 @@ uci:foreach(shadowsocksr, "servers", function(s)
|
||||
retstring =retstring .. "<font color='green'>[" .. server_name .. "] OK.</font><br />"
|
||||
else
|
||||
retstring =retstring .. "<font color='red'>[" .. server_name .. "] Error.</font><br />"
|
||||
end
|
||||
end
|
||||
if iret== 0 then
|
||||
luci.sys.call(" ipset del ss_spec_wan_ac " .. s.server)
|
||||
end
|
||||
|
@ -1,6 +1,3 @@
|
||||
local fs = require "nixio.fs"
|
||||
local conffile = "/tmp/ssrpro.log"
|
||||
|
||||
f = SimpleForm("logview")
|
||||
f.reset = false
|
||||
f.submit = false
|
||||
@ -8,8 +5,12 @@ t = f:field(TextValue, "conf")
|
||||
t.rmempty = true
|
||||
t.rows = 20
|
||||
function t.cfgvalue()
|
||||
luci.sys.exec("[ -f /tmp/ssrplus.log ] && sed '1!G;h;$!d' /tmp/ssrplus.log > /tmp/ssrpro.log")
|
||||
return fs.readfile(conffile) or ""
|
||||
local logs = luci.util.execi("cat /tmp/ssrplus.log")
|
||||
local s = ""
|
||||
for line in logs do
|
||||
s = line .. "\n" .. s
|
||||
end
|
||||
return s
|
||||
end
|
||||
t.readonly="readonly"
|
||||
|
||||
|
@ -37,7 +37,7 @@ o.rmempty = true
|
||||
o = s:option(Button,"update_Sub",translate("Update Subscribe List"))
|
||||
o.inputstyle = "reload"
|
||||
o.description = translate("Update subscribe url list first")
|
||||
o.write = function()
|
||||
o.write = function()
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin", "services", "shadowsocksr", "servers"))
|
||||
end
|
||||
|
||||
@ -45,12 +45,18 @@ o = s:option(Flag, "proxy", translate("Through proxy update"))
|
||||
o.rmempty = false
|
||||
o.description = translate("Through proxy update list, Not Recommended ")
|
||||
|
||||
o = s:option(Button,"update",translate("Update All Subscribe Severs"))
|
||||
o.inputstyle = "apply"
|
||||
o.write = function()
|
||||
luci.sys.exec("bash /usr/share/shadowsocksr/subscribe.sh >>/tmp/ssrplus.log 2>&1")
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin", "services", "shadowsocksr", "servers"))
|
||||
end
|
||||
o = s:option(Button,"subscribe", translate("Update All Subscribe Severs"))
|
||||
o.rawhtml = true
|
||||
o.template = "shadowsocksr/subscribe"
|
||||
|
||||
|
||||
-- o.inputstyle = "apply"
|
||||
-- o.write = function()
|
||||
-- luci.sys.call("lua /root/subscribe.lua >>/tmp/ssrplus.log 2>&1")
|
||||
-- -- luci.sys.call("echo 123 >>/tmp/ssrplus.log 2>&1")
|
||||
-- --luci.sys.exec("bash /usr/share/shadowsocksr/subscribe.sh >>/tmp/ssrplus.log 2>&1")
|
||||
-- luci.http.redirect(luci.dispatcher.build_url("admin", "services", "shadowsocksr", "servers"))
|
||||
-- end
|
||||
|
||||
|
||||
o = s:option(Button,"delete",translate("Delete all severs"))
|
||||
@ -58,8 +64,8 @@ o.inputstyle = "reset"
|
||||
o.description = string.format(translate("Server Count") .. ": %d", server_count)
|
||||
o.write = function()
|
||||
uci:delete_all("shadowsocksr", "servers", function(s) return true end)
|
||||
uci:save("shadowsocksr")
|
||||
luci.sys.call("uci commit shadowsocksr && /etc/init.d/shadowsocksr stop")
|
||||
uci:save("shadowsocksr")
|
||||
luci.sys.call("uci commit shadowsocksr && /etc/init.d/shadowsocksr stop")
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin", "services", "shadowsocksr", "servers"))
|
||||
return
|
||||
end
|
||||
@ -113,7 +119,11 @@ function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "0"
|
||||
end
|
||||
|
||||
o = s:option(DummyValue,"server",translate("Ping Latency"))
|
||||
o = s:option(DummyValue, "server_port", translate("Socket Connected"))
|
||||
o.template="shadowsocksr/socket"
|
||||
o.width="10%"
|
||||
|
||||
o = s:option(DummyValue, "server", translate("Ping Latency"))
|
||||
o.template="shadowsocksr/ping"
|
||||
o.width="10%"
|
||||
|
||||
|
@ -9,16 +9,56 @@ local dsp = require "luci.dispatcher"
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
var pings = document.getElementsByClassName('pingtime');
|
||||
for(var i = 0; i < pings.length; i++) {
|
||||
XHR.get('<%=dsp.build_url("admin/services/shadowsocksr/ping")%>', {
|
||||
index: i,
|
||||
domain: pings[i].getAttribute("hint")
|
||||
const doms = document.getElementsByClassName('pingtime');
|
||||
const ports = document.getElementsByClassName("socket-connected")
|
||||
// 这也是卡的原罪 CGI 一下子处理不这么多
|
||||
const xhr = (index) => {
|
||||
return new Promise((res) => {
|
||||
const dom = doms[index];
|
||||
const port = ports[index];
|
||||
if (!dom) res()
|
||||
XHR.get('<%=dsp.build_url("admin/services/shadowsocksr/ping")%>', {
|
||||
index,
|
||||
domain: dom.getAttribute("hint"),
|
||||
port: port.getAttribute("hint")
|
||||
},
|
||||
function(x, result) {
|
||||
pings[result.index].innerHTML = (result.ping ? result.ping : "--") + " ms";
|
||||
}
|
||||
);
|
||||
(x, result) => {
|
||||
let col = '#ff0000';
|
||||
if (result.ping) {
|
||||
if (result.ping < 300) col = '#ff3300';
|
||||
if (result.ping < 200) col = '#ff7700';
|
||||
if (result.ping < 100) col = '#249400';
|
||||
}
|
||||
dom.innerHTML = `<font color="${col}">${(result.ping ? result.ping : "--") + " ms"}</font>`
|
||||
if (result.socket) {
|
||||
port.innerHTML = '<font color="#249400">ok</font>'
|
||||
} else {
|
||||
port.innerHTML = '<font color="#ff0000">fail</font>'
|
||||
}
|
||||
res()
|
||||
});
|
||||
})
|
||||
}
|
||||
(async () => {
|
||||
for (let group = 0; group < Math.ceil(doms.length / 5); group++) {
|
||||
await Promise.all([
|
||||
xhr(group * 5 + 0),
|
||||
xhr(group * 5 + 1),
|
||||
xhr(group * 5 + 2),
|
||||
xhr(group * 5 + 3),
|
||||
xhr(group * 5 + 4),
|
||||
])
|
||||
}
|
||||
})()
|
||||
// for(var i = 0; i < pings.length; i++) {
|
||||
// XHR.get('<%=dsp.build_url("admin/services/shadowsocksr/ping")%>', {
|
||||
// index: i,
|
||||
// domain: pings[i].getAttribute("hint")
|
||||
// },
|
||||
// function(x, result) {
|
||||
// pings[result.index].innerHTML = (result.ping ? result.ping : "--") + " ms";
|
||||
// }
|
||||
// );
|
||||
// }
|
||||
//]]>
|
||||
</script>
|
@ -0,0 +1,3 @@
|
||||
<%+cbi/valueheader%>
|
||||
<span class="socket-connected" hint="<%=self:cfgvalue(section)%>">connecting</:wqspan>
|
||||
<%+cbi/valuefooter%>
|
@ -0,0 +1,23 @@
|
||||
<%+cbi/valueheader%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
function subscribe(btn,dataname) {
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Refresh...%> ';
|
||||
murl=dataname;
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "shadowsocksr","subscribe")%>', { set:murl }, function(x,rv) {
|
||||
// 先简单刷新,后期如果重构会考虑下如何组织lua shell JavaScript之间的代码逻辑和各自的调用逻辑
|
||||
window.location.reload()
|
||||
// btn.disabled = false;
|
||||
// btn.value = '<%:Refresh Data %>';
|
||||
});
|
||||
return false;
|
||||
}
|
||||
//]]></script>
|
||||
|
||||
|
||||
<input type="button" class="cbi-button cbi-input-apply" value="<%:Update All Subscribe Severs%> " onclick="return subscribe(this,'<%=self.option%>')" />
|
||||
<!-- <span id="<%=self.option%>-status"><em><%=self.value%></em></span> -->
|
||||
|
||||
<%+cbi/valuefooter%>
|
@ -512,6 +512,9 @@ msgstr "所有端口(默认)"
|
||||
msgid "Only Common Ports"
|
||||
msgstr "仅常用端口(不走P2P流量到代理)"
|
||||
|
||||
msgid "Socket Connected"
|
||||
msgstr "连接测试"
|
||||
|
||||
msgid "Ping Latency"
|
||||
msgstr "Ping延迟"
|
||||
|
||||
|
@ -45,7 +45,7 @@ add_cron()
|
||||
{
|
||||
sed -i '/shadowsocksr/d' $CRON_FILE
|
||||
sed -i '/ssrplus.log/d' $CRON_FILE && echo '0 1 * * * echo "" > /tmp/ssrplus.log' >> $CRON_FILE
|
||||
[ $(uci_get_by_type server_subscribe auto_update 0) -eq 1 ] && echo "0 $(uci_get_by_type server_subscribe auto_update_time) * * * /usr/share/shadowsocksr/subscribe.sh" >> $CRON_FILE
|
||||
[ $(uci_get_by_type server_subscribe auto_update 0) -eq 1 ] && echo "0 $(uci_get_by_type server_subscribe auto_update_time) * * * /usr/bin/lua /usr/share/shadowsocksr/subscribe.lua" >> $CRON_FILE
|
||||
[ $(uci_get_by_type server_subscribe auto_update 0) -eq 1 ] && echo "0 $(uci_get_by_type server_subscribe auto_update_time) * * * /usr/share/shadowsocksr/update.sh" >> $CRON_FILE
|
||||
crontab $CRON_FILE
|
||||
}
|
||||
@ -61,7 +61,7 @@ run_mode=$(uci_get_by_type global run_mode)
|
||||
|
||||
gen_config_file() {
|
||||
local host=$(uci_get_by_name $1 server)
|
||||
if echo $host|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then
|
||||
if echo $host|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then
|
||||
hostip=${host}
|
||||
elif [ "$host" != "${host#*:[0-9a-fA-F]}" ] ;then
|
||||
hostip=${host}
|
||||
@ -74,7 +74,7 @@ gen_config_file() {
|
||||
fi
|
||||
fi
|
||||
[ $2 = "0" -a $kcp_flag = "1" ] && hostip="127.0.0.1"
|
||||
|
||||
|
||||
if [ $2 = "0" ] ;then
|
||||
config_file=$CONFIG_FILE
|
||||
elif [ $2 = "1" ]; then
|
||||
@ -105,7 +105,7 @@ EOF
|
||||
elif [ "$stype" == "ssr" ] ;then
|
||||
cat <<-EOF >$config_file
|
||||
{
|
||||
|
||||
|
||||
"server": "$hostip",
|
||||
"server_port": $(uci_get_by_name $1 server_port),
|
||||
"local_address": "0.0.0.0",
|
||||
@ -140,7 +140,7 @@ get_arg_out() {
|
||||
start_rules() {
|
||||
local server=$(uci_get_by_name $GLOBAL_SERVER server)
|
||||
#resolve name
|
||||
if echo $server|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then
|
||||
if echo $server|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then
|
||||
server=${server}
|
||||
elif [ "$server" != "${server#*:[0-9a-fA-F]}" ] ;then
|
||||
server=${server}
|
||||
@ -152,14 +152,14 @@ start_rules() {
|
||||
server=`cat /etc/ssr_ip`
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
kcp_server=$server
|
||||
|
||||
|
||||
local kcp_enable=$(uci_get_by_name $GLOBAL_SERVER kcp_enable 0)
|
||||
if [ $kcp_enable = "1" ] ;then
|
||||
kcp_flag=1
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
local local_port=$(uci_get_by_name $GLOBAL_SERVER local_port)
|
||||
local lan_ac_ips=$(uci_get_by_type access_control lan_ac_ips)
|
||||
local lan_ac_mode="b"
|
||||
@ -171,15 +171,15 @@ start_rules() {
|
||||
local udp_server=$(uci_get_by_name $UDP_RELAY_SERVER server)
|
||||
local udp_local_port=$(uci_get_by_name $UDP_RELAY_SERVER local_port)
|
||||
fi
|
||||
|
||||
|
||||
if [ -n "$lan_ac_ips" ]; then
|
||||
case "$lan_ac_mode" in
|
||||
w|W|b|B) local ac_ips="$lan_ac_mode$lan_ac_ips";;
|
||||
esac
|
||||
fi
|
||||
|
||||
|
||||
#deal gfw firewall rule
|
||||
local gfwmode=""
|
||||
local gfwmode=""
|
||||
if [ "$run_mode" = "gfw" ]; then
|
||||
gfwmode="-g"
|
||||
elif [ "$run_mode" = "router" ]; then
|
||||
@ -189,7 +189,7 @@ start_rules() {
|
||||
elif [ "$run_mode" = "all" ]; then
|
||||
gfwmode="-z"
|
||||
fi
|
||||
|
||||
|
||||
local dports=$(uci_get_by_type global dports 1)
|
||||
if [ $dports = "1" ] ;then
|
||||
proxyport=" "
|
||||
@ -210,14 +210,14 @@ start_rules() {
|
||||
-G "$(uci_get_by_type access_control lan_gm_ips)" \
|
||||
-D "$proxyport" \
|
||||
$(get_arg_out) $gfwmode $ARG_UDP
|
||||
|
||||
|
||||
return $?
|
||||
}
|
||||
|
||||
start_pdnsd() {
|
||||
local usr_dns="$1"
|
||||
local usr_port="$2"
|
||||
|
||||
|
||||
local tcp_dns_list="208.67.222.222, 208.67.220.220"
|
||||
[ -z "$usr_dns" ] && usr_dns="8.8.8.8"
|
||||
[ -z "$usr_port" ] && usr_port="53"
|
||||
@ -229,7 +229,7 @@ start_pdnsd() {
|
||||
echo -ne "pd13\000\000\000\000" >/var/pdnsd/pdnsd.cache
|
||||
chown -R nobody:nogroup /var/pdnsd
|
||||
fi
|
||||
|
||||
|
||||
cat > /var/etc/pdnsd.conf <<EOF
|
||||
global {
|
||||
perm_cache=1024;
|
||||
@ -276,12 +276,12 @@ start_redir() {
|
||||
1|on|true|yes|enabled) ARG_OTA="-A";;
|
||||
*) ARG_OTA="";;
|
||||
esac
|
||||
|
||||
|
||||
#deal kcp
|
||||
local kcp_enable=$(uci_get_by_name $GLOBAL_SERVER kcp_enable 0)
|
||||
if [ $kcp_enable = "1" ] ;then
|
||||
[ ! -f "/usr/bin/kcptun-client" ] && return 1
|
||||
|
||||
|
||||
local kcp_str=`/usr/bin/kcptun-client -v |grep kcptun|wc -l`
|
||||
[ "0" = $kcp_str ] && return 1
|
||||
local kcp_port=$(uci_get_by_name $GLOBAL_SERVER kcp_port)
|
||||
@ -291,10 +291,10 @@ start_redir() {
|
||||
[ "$password" != "" ] && password="--key "${password}
|
||||
service_start /usr/bin/kcptun-client \
|
||||
-r $kcp_server:$kcp_port \
|
||||
-l :$server_port $password $kcp_param
|
||||
-l :$server_port $password $kcp_param
|
||||
kcp_enable_flag=1
|
||||
fi
|
||||
|
||||
|
||||
gen_config_file $GLOBAL_SERVER 0
|
||||
local stype=$(uci_get_by_name $GLOBAL_SERVER type)
|
||||
if [ "$stype" == "ss" ] ;then
|
||||
@ -306,7 +306,7 @@ start_redir() {
|
||||
elif [ "$stype" == "trojan" ] ;then
|
||||
sscmd="/usr/sbin/trojan"
|
||||
fi
|
||||
|
||||
|
||||
local utype=$(uci_get_by_name $UDP_RELAY_SERVER type)
|
||||
if [ "$utype" == "ss" ] ;then
|
||||
ucmd="/usr/bin/ss-redir"
|
||||
@ -317,7 +317,7 @@ start_redir() {
|
||||
elif [ "$utype" == "trojan" ] ;then
|
||||
ucmd="/usr/sbin/trojan"
|
||||
fi
|
||||
|
||||
|
||||
if [ "$(uci_get_by_type global threads 0)" = "0" ] ;then
|
||||
threads=$(cat /proc/cpuinfo | grep 'processor' | wc -l)
|
||||
else
|
||||
@ -328,26 +328,26 @@ start_redir() {
|
||||
if [ "$stype" == "ss" -o "$stype" == "ssr" ] ;then
|
||||
local last_config_file=$CONFIG_FILE
|
||||
local pid_file="/var/run/ssr-retcp.pid"
|
||||
for i in $(seq 1 $threads)
|
||||
do
|
||||
for i in $(seq 1 $threads)
|
||||
do
|
||||
$sscmd -c $CONFIG_FILE $ARG_OTA -f /var/run/ssr-retcp_$i.pid >/dev/null 2>&1
|
||||
done
|
||||
echo "$(date "+%Y-%m-%d %H:%M:%S") Shadowsocks/ShadowsocksR $threads Threads Started!" >> /tmp/ssrplus.log
|
||||
echo "$(date "+%Y-%m-%d %H:%M:%S") Shadowsocks/ShadowsocksR $threads Threads Started!" >> /tmp/ssrplus.log
|
||||
elif [ "$stype" == "v2ray" ] ;then
|
||||
$sscmd -config /var/etc/v2-ssr-retcp.json >/dev/null 2>&1 &
|
||||
echo "$(date "+%Y-%m-%d %H:%M:%S") $($sscmd -version | head -1) Started!" >> /tmp/ssrplus.log
|
||||
elif [ "$stype" == "trojan" ] ;then
|
||||
$sscmd --config /var/etc/trojan-ssr-retcp.json >/dev/null 2>&1 &
|
||||
$sscmd --config /var/etc/trojan-ssr-retcp.json >/dev/null 2>&1 &
|
||||
echo "$(date "+%Y-%m-%d %H:%M:%S") $($sscmd --version 2>&1 | head -1) Started!" >> /tmp/ssrplus.log
|
||||
fi
|
||||
|
||||
|
||||
if [ -n "$UDP_RELAY_SERVER" ] ;then
|
||||
redir_udp=1
|
||||
if [ "$utype" == "ss" -o "$utype" == "ssr" ] ;then
|
||||
case "$(uci_get_by_name $UDP_RELAY_SERVER auth_enable)" in
|
||||
1|on|true|yes|enabled) ARG_OTA="-A";;
|
||||
*) ARG_OTA="";;
|
||||
esac
|
||||
esac
|
||||
gen_config_file $UDP_RELAY_SERVER 1
|
||||
last_config_file=$CONFIG_UDP_FILE
|
||||
pid_file="/var/run/ssr-reudp.pid"
|
||||
@ -355,11 +355,11 @@ start_redir() {
|
||||
elif [ "$utype" == "v2ray" ] ; then
|
||||
lua /usr/share/shadowsocksr/genv2config.lua $UDP_RELAY_SERVER udp $(uci_get_by_name $UDP_RELAY_SERVER local_port) > /var/etc/v2-ssr-reudp.json
|
||||
sed -i 's/\\//g' /var/etc/v2-ssr-reudp.json
|
||||
$ucmd -config /var/etc/v2-ssr-reudp.json >/dev/null 2>&1 &
|
||||
$ucmd -config /var/etc/v2-ssr-reudp.json >/dev/null 2>&1 &
|
||||
elif [ "$stype" == "trojan" ] ;then
|
||||
lua /usr/share/shadowsocksr/gentrojanconfig.lua $GLOBAL_SERVER client 10801 > /var/etc/trojan-ssr-reudp.json
|
||||
sed -i 's/\\//g' /var/etc/trojan-ssr-reudp.json
|
||||
$ucmd --config /var/etc/trojan-ssr-reudp.json >/dev/null 2>&1 &
|
||||
$ucmd --config /var/etc/trojan-ssr-reudp.json >/dev/null 2>&1 &
|
||||
ipt2socks -U -4 -b 0.0.0.0 -s 127.0.0.1 -p 10801 -l $(uci_get_by_name $UDP_RELAY_SERVER local_port) >/dev/null 2>&1 &
|
||||
fi
|
||||
fi
|
||||
@ -367,7 +367,7 @@ start_redir() {
|
||||
|
||||
|
||||
#deal with dns
|
||||
|
||||
|
||||
if [ "$(uci_get_by_type global pdnsd_enable)" = "1" ] ;then
|
||||
local dnsstr="$(uci_get_by_type global tunnel_forward 8.8.4.4:53)"
|
||||
local dnsserver=`echo "$dnsstr"|awk -F ':' '{print $1}'`
|
||||
@ -377,12 +377,12 @@ start_redir() {
|
||||
elif [ "$run_mode" = "oversea" ]; then
|
||||
ipset add oversea $dnsserver 2>/dev/null
|
||||
else
|
||||
ipset add ss_spec_wan_ac $dnsserver nomatch 2>/dev/null
|
||||
ipset add ss_spec_wan_ac $dnsserver nomatch 2>/dev/null
|
||||
fi
|
||||
start_pdnsd $dnsserver $dnsport
|
||||
pdnsd_enable_flag=1
|
||||
fi
|
||||
|
||||
|
||||
if [ "$(uci_get_by_type global enable_switch)" = "1" ] ;then
|
||||
if [ "$(uci_get_by_name $GLOBAL_SERVER switch_enable)" = "1" ] ;then
|
||||
if [ -z "$switch_server" ] ;then
|
||||
@ -403,7 +403,7 @@ gen_service_file() {
|
||||
fastopen="true";
|
||||
else
|
||||
fastopen="false";
|
||||
fi
|
||||
fi
|
||||
cat <<-EOF >$2
|
||||
{
|
||||
"server": "0.0.0.0",
|
||||
@ -435,14 +435,14 @@ iptables -t filter -A SSR-SERVER-RULE -p udp --dport $(uci_get_by_name $1 server
|
||||
return 0
|
||||
}
|
||||
gen_serv_include() {
|
||||
FWI=$(uci get firewall.shadowsocksr.path 2>/dev/null)
|
||||
FWI=$(uci get firewall.shadowsocksr.path 2>/dev/null)
|
||||
[ -n "$FWI" ] || return 0
|
||||
if [ ! -f $FWI ] ;then
|
||||
echo '#!/bin/sh' >$FWI
|
||||
fi
|
||||
extract_rules() {
|
||||
echo "*filter"
|
||||
iptables-save -t filter | grep SSR-SERVER-RULE|sed -e "s/^-A INPUT/-I INPUT/"
|
||||
iptables-save -t filter | grep SSR-SERVER-RULE|sed -e "s/^-A INPUT/-I INPUT/"
|
||||
echo 'COMMIT'
|
||||
}
|
||||
cat <<-EOF >>$FWI
|
||||
@ -473,7 +473,7 @@ start_local() {
|
||||
-l $(uci_get_by_type socks5_proxy local_port 1080) \
|
||||
-b $(uci_get_by_type socks5_proxy local_address 0.0.0.0) \
|
||||
-f /var/run/ssr-local.pid >/dev/null 2>&1
|
||||
local_enable=1
|
||||
local_enable=1
|
||||
}
|
||||
|
||||
rules() {
|
||||
@ -488,7 +488,7 @@ rules() {
|
||||
fi
|
||||
}
|
||||
|
||||
start() {
|
||||
start() {
|
||||
if [ -z "$switch_server" ] ;then
|
||||
GLOBAL_SERVER=$(uci_get_by_type global global_server)
|
||||
else
|
||||
@ -498,7 +498,7 @@ start() {
|
||||
|
||||
if rules ;then
|
||||
start_redir
|
||||
|
||||
|
||||
mkdir -p /tmp/dnsmasq.d && cp -a /etc/dnsmasq.ssr /tmp/ && cp -a /etc/dnsmasq.oversea /tmp/
|
||||
if ! [ "$run_mode" = "oversea" ] ;then
|
||||
cat > /tmp/dnsmasq.d/dnsmasq-ssr.conf <<EOF
|
||||
@ -509,15 +509,15 @@ EOF
|
||||
conf-dir=/tmp/dnsmasq.oversea
|
||||
EOF
|
||||
fi
|
||||
|
||||
|
||||
/usr/share/shadowsocksr/gfw2ipset.sh
|
||||
|
||||
|
||||
/etc/init.d/dnsmasq restart >/dev/null 2>&1
|
||||
|
||||
|
||||
fi
|
||||
start_server
|
||||
start_server
|
||||
start_local
|
||||
|
||||
|
||||
if [ $(uci_get_by_type global monitor_enable) = 1 ] ;then
|
||||
let total_count=server_count+redir_tcp+redir_udp+tunnel_enable+kcp_enable_flag+local_enable+pdnsd_enable_flag+switch_enable
|
||||
if [ $total_count -gt 0 ]
|
||||
@ -526,7 +526,7 @@ EOF
|
||||
service_start /usr/bin/ssr-monitor $server_count $redir_tcp $redir_udp $tunnel_enable $kcp_enable_flag $local_enable $pdnsd_enable_flag $switch_enable
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
ENABLE_SERVER=$(uci_get_by_type global global_server)
|
||||
[ "$ENABLE_SERVER" = "nil" ] && return 1
|
||||
}
|
||||
@ -560,10 +560,10 @@ stop() {
|
||||
killall -q -9 ssr-local
|
||||
if [ -f /var/run/pdnsd.pid ] ;then
|
||||
kill $(cat /var/run/pdnsd.pid) >/dev/null 2>&1
|
||||
else
|
||||
kill -9 $(busybox ps -w | grep pdnsd | grep -v grep | awk '{print $1}') >/dev/null 2>&1
|
||||
else
|
||||
kill -9 $(busybox ps -w | grep pdnsd | grep -v grep | awk '{print $1}') >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
|
||||
if [ -f "/tmp/dnsmasq.d/dnsmasq-ssr.conf" ]; then
|
||||
rm -f /tmp/dnsmasq.d/dnsmasq-ssr.conf
|
||||
/etc/init.d/dnsmasq restart >/dev/null 2>&1
|
||||
|
295
package/lean/luci-app-ssr-plus/root/usr/share/shadowsocksr/subscribe.lua
Executable file
295
package/lean/luci-app-ssr-plus/root/usr/share/shadowsocksr/subscribe.lua
Executable file
@ -0,0 +1,295 @@
|
||||
#!/usr/bin/lua
|
||||
------------------------------------------------
|
||||
-- This file is part of the luci-app-ssr-plus subscribe.lua
|
||||
-- @author William Chan <root@williamchan.me>
|
||||
------------------------------------------------
|
||||
require 'nixio'
|
||||
require 'luci.util'
|
||||
require 'luci.jsonc'
|
||||
require 'luci.sys'
|
||||
|
||||
-- these global functions are accessed all the time by the event handler
|
||||
-- so caching them is worth the effort
|
||||
local tinsert = table.insert
|
||||
local ssub, slen, schar, srep, sbyte, sformat, sgsub =
|
||||
string.sub, string.len, string.char, string.rep, string.byte, string.format, string.gsub
|
||||
local cache = {}
|
||||
local nodeResult = setmetatable({}, { __index = cache }) -- update result
|
||||
local name = 'shadowsocksr'
|
||||
local uciType = 'servers'
|
||||
local ucic = luci.model.uci.cursor()
|
||||
local proxy = ucic:get_first(name, 'server_subscribe', 'proxy', '0')
|
||||
local subscribe_url = ucic:get_first(name, 'server_subscribe', 'subscribe_url', {})
|
||||
|
||||
local log = function(...)
|
||||
print(os.date("%Y-%m-%d %H:%M:%S ") .. table.concat({ ... }, " "))
|
||||
end
|
||||
-- 分割字符串
|
||||
local function split(full, sep)
|
||||
full = full:gsub("%z", "") -- 这里不是很清楚 有时候结尾带个\0
|
||||
local off, result = 1, {}
|
||||
while true do
|
||||
local nEnd = full:find(sep, off)
|
||||
if not nEnd then
|
||||
local res = ssub(full, off, slen(full))
|
||||
if #res > 0 then -- 过滤掉 \0
|
||||
tinsert(result, res)
|
||||
end
|
||||
break
|
||||
else
|
||||
tinsert(result, ssub(full, off, nEnd - 1))
|
||||
off = nEnd + slen(sep)
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
-- urlencode
|
||||
local function get_urlencode(c)
|
||||
return sformat("%%%02X", sbyte(c))
|
||||
end
|
||||
|
||||
function urlEncode(szText)
|
||||
local str = szText:gsub("([^0-9a-zA-Z ])", get_urlencode)
|
||||
str = str:gsub(" ", "+")
|
||||
return str
|
||||
end
|
||||
-- trim
|
||||
local function trim(text)
|
||||
if not text or text == "" then
|
||||
return ""
|
||||
end
|
||||
return (sgsub(text, "^%s*(.-)%s*$", "%1"))
|
||||
end
|
||||
-- md5
|
||||
local function md5(content)
|
||||
local stdout = luci.sys.exec('echo \"' .. urlEncode(content) .. '\" | md5sum | cut -d \" \" -f1')
|
||||
-- assert(nixio.errno() == 0)
|
||||
return trim(stdout)
|
||||
end
|
||||
-- base64
|
||||
local function base64Decode(text, safe)
|
||||
if not text then return '' end
|
||||
text = text:gsub("%z", "")
|
||||
if safe then
|
||||
text = text:gsub("_", "/")
|
||||
text = text:gsub("-", "+")
|
||||
local mod4 = #text % 4
|
||||
text = text .. string.sub('====', mod4 + 1)
|
||||
end
|
||||
return nixio.bin.b64decode(text):gsub("%z", "")
|
||||
end
|
||||
-- 处理数据
|
||||
local function processData(szType, content)
|
||||
local result = {
|
||||
auth_enable = '0',
|
||||
switch_enable = '1',
|
||||
type = szType,
|
||||
local_port = 1234,
|
||||
timeout = 60, -- 不太确定 好像是死的
|
||||
fast_open = 0,
|
||||
kcp_enable = 0,
|
||||
kcp_port = 0,
|
||||
kcp_param = '--nocomp'
|
||||
}
|
||||
local hash
|
||||
if type(content) == 'string' then
|
||||
hash = md5(content)
|
||||
else
|
||||
hash = md5(luci.jsonc.stringify(content))
|
||||
end
|
||||
result.hashkey = hash
|
||||
if szType == 'ssr' then
|
||||
local dat = split(content, "/\\?")
|
||||
local hostInfo = split(dat[1], ':')
|
||||
result.server = hostInfo[1]
|
||||
result.server_port = hostInfo[2]
|
||||
result.protocol = hostInfo[3]
|
||||
result.encrypt_method = hostInfo[4]
|
||||
result.obfs = hostInfo[5]
|
||||
result.password = base64Decode(hostInfo[6], true)
|
||||
local params = {}
|
||||
for k, v in pairs(split(dat[2], '&')) do
|
||||
local t = split(v, '=')
|
||||
params[t[1]] = t[2]
|
||||
end
|
||||
result.obfs_param = base64Decode(params.bfsparam, true)
|
||||
result.protocol_param = base64Decode(params.protoparam, true)
|
||||
local group = base64Decode(params.group, true)
|
||||
if group then
|
||||
result.alias = "[" .. group .. "] "
|
||||
end
|
||||
result.alias = result.alias .. base64Decode(params.remarks, true)
|
||||
elseif szType == 'vmess' then
|
||||
local info = luci.jsonc.parse(content)
|
||||
result.type = 'v2ray'
|
||||
result.server = info.add
|
||||
result.server_port = info.port
|
||||
result.tcp_guise = "none"
|
||||
result.transport = info.net
|
||||
result.alter_id = info.aid
|
||||
result.vmess_id = info.id
|
||||
result.alias = info.ps
|
||||
result.ws_host = info.host
|
||||
result.ws_path = info.path
|
||||
result.h2_host = info.host
|
||||
result.h2_path = info.path
|
||||
if not info.security then
|
||||
result.security = 'auto'
|
||||
end
|
||||
if info.tls == 'tls' or info.tls == '1' then
|
||||
result.tls = '1'
|
||||
else
|
||||
result.tls = '0'
|
||||
end
|
||||
elseif szType == 'ssd' then
|
||||
result.type = 'ss'
|
||||
result.server = content.server
|
||||
result.server_port = content.port
|
||||
result.password = content.password
|
||||
result.encrypt_method_ss = content.encryption
|
||||
result.alias = '[' .. content.airport .. '] ' .. content.remarks
|
||||
end
|
||||
return result, hash
|
||||
end
|
||||
-- wget
|
||||
local function wget(url)
|
||||
local stdout = luci.sys.exec('wget-ssl --user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36" --no-check-certificate -t 3 -T 10 -O- ' .. url)
|
||||
return trim(stdout)
|
||||
end
|
||||
|
||||
local execute = function()
|
||||
-- exec
|
||||
do
|
||||
-- subscribe_url = {'https://www.google.comc'}
|
||||
if proxy == '0' then -- 不使用代理更新的话先暂停
|
||||
log('服务正在暂停')
|
||||
luci.sys.init.stop(name)
|
||||
end
|
||||
for k, url in ipairs(subscribe_url) do
|
||||
local raw = wget(url)
|
||||
if #raw > 0 then
|
||||
local node, szType
|
||||
local groupHash = md5(url)
|
||||
cache[groupHash] = {}
|
||||
tinsert(nodeResult, {})
|
||||
local index = #nodeResult
|
||||
-- SSD 似乎是这种格式 ssd:// 开头的 不知道 SS 什么格式 没支持 不清楚其他机场是否这样
|
||||
if raw:find('ssd://') then
|
||||
szType = 'ssd'
|
||||
local nEnd = select(2, raw:find('ssd://'))
|
||||
node = base64Decode(raw:sub(nEnd + 1, #raw), true)
|
||||
node = luci.jsonc.parse(node)
|
||||
local extra = {
|
||||
airport = node.airport,
|
||||
port = node.port,
|
||||
encryption = node.encryption,
|
||||
password = node.password
|
||||
}
|
||||
local servers = {}
|
||||
-- SS里面包着 干脆直接这样
|
||||
for _, server in ipairs(node.servers) do
|
||||
tinsert(servers, setmetatable(server, { __index = extra }))
|
||||
end
|
||||
node = servers
|
||||
else
|
||||
-- ssd 外的格式
|
||||
node = split(base64Decode(raw, true), "\n")
|
||||
end
|
||||
for _, v in ipairs(node) do
|
||||
if v then
|
||||
local result, hash
|
||||
if szType == 'ssd' then
|
||||
result, hash = processData(szType, v)
|
||||
elseif not szType then
|
||||
local dat = split(v, "://")
|
||||
if dat and dat[1] and dat[2] then
|
||||
result, hash = processData(dat[1], base64Decode( dat[2], true))
|
||||
end
|
||||
else
|
||||
log('跳过未知类型: ' .. szType)
|
||||
end
|
||||
-- log(hash, result)
|
||||
if hash and result then
|
||||
if result.alias:find("过期时间") or
|
||||
result.alias:find("剩余流量") or
|
||||
result.alias:find("QQ群") or
|
||||
result.alias:find("官网") or
|
||||
result.server == ''
|
||||
then
|
||||
log('丢弃无效节点: ' .. result.type ..' 节点, ' .. result.alias)
|
||||
else
|
||||
log('成功解析: ' .. result.type ..' 节点, ' .. result.alias)
|
||||
result.grouphashkey = groupHash
|
||||
tinsert(nodeResult[index], result)
|
||||
cache[groupHash][hash] = nodeResult[index][#nodeResult[index]]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
log('成功解析节点数量: ' ..#node)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- diff
|
||||
do
|
||||
assert(next(nodeResult))
|
||||
local add, del = 0, 0
|
||||
ucic:foreach(name, uciType, function(old)
|
||||
if old.grouphashkey or old.hashkey then -- 没有 hash 的不参与删除
|
||||
if not nodeResult[old.grouphashkey] or not nodeResult[old.grouphashkey][old.hashkey] then
|
||||
ucic:delete(name, old['.name'])
|
||||
del = del + 1
|
||||
else
|
||||
local dat = nodeResult[old.grouphashkey][old.hashkey]
|
||||
ucic:tset(name, old['.name'], dat)
|
||||
-- 标记一下
|
||||
setmetatable(nodeResult[old.grouphashkey][old.hashkey], { __index = { _ignore = true } })
|
||||
end
|
||||
else
|
||||
log('忽略手动添加的节点: ' .. old.alias)
|
||||
end
|
||||
end)
|
||||
for k, v in ipairs(nodeResult) do
|
||||
for kk, vv in ipairs(v) do
|
||||
if not vv._ignore then
|
||||
local section = ucic:add(name, uciType)
|
||||
ucic:tset(name, section, vv)
|
||||
add = add + 1
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
ucic:commit(name)
|
||||
-- 如果服务器已经不见了把帮换一个
|
||||
local globalServer = ucic:get_first(name, 'global', 'global_server', '')
|
||||
local firstServer = ucic:get_first(name, uciType)
|
||||
if not ucic:get(name, globalServer) then
|
||||
if firstServer then
|
||||
ucic:set(name, ucic:get_first(name, 'global'), 'global_server', firstServer)
|
||||
ucic:commit(name)
|
||||
log('当前主服务器已更新,正在自动更换。')
|
||||
end
|
||||
end
|
||||
if firstServer then
|
||||
luci.sys.call("/etc/init.d/" .. name .." restart > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
|
||||
else
|
||||
luci.sys.call("/etc/init.d/" .. name .." stop > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
|
||||
end
|
||||
log('新增节点数量: ' ..add, '删除节点数量: ' .. del)
|
||||
log('更新成功服务正在启动')
|
||||
end
|
||||
end
|
||||
|
||||
if subscribe_url and #subscribe_url > 0 then
|
||||
xpcall(execute, function()
|
||||
log('发生错误, 正在恢复服务')
|
||||
local firstServer = ucic:get_first(name, uciType)
|
||||
if firstServer then
|
||||
luci.sys.call("/etc/init.d/" .. name .." restart > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
|
||||
else
|
||||
luci.sys.call("/etc/init.d/" .. name .." stop > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
|
||||
end
|
||||
log('更新失败服务正在恢复')
|
||||
log(debug.traceback())
|
||||
end)
|
||||
end
|
Loading…
Reference in New Issue
Block a user