luci-app-ssr-plus: optimize subscribe script and fix ssd subscribe (#2846)

This commit is contained in:
William Chan 2020-01-24 00:19:39 +08:00 committed by coolsnowwolf
parent 89b72b7ad9
commit 2194a78deb

View File

@ -10,8 +10,11 @@ require 'luci.sys'
-- these global functions are accessed all the time by the event handler
-- so caching them is worth the effort
local luci = luci
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 ssub, slen, schar, sbyte, sformat, sgsub = string.sub, string.len, string.char, string.byte, string.format, string.gsub
local jsonParse, jsonStringify = luci.jsonc.parse, luci.jsonc.stringify
local b64decode = nixio.bin.b64decode
local cache = {}
local nodeResult = setmetatable({}, { __index = cache }) -- update result
local name = 'shadowsocksr'
@ -74,17 +77,15 @@ local function md5(content)
return trim(stdout)
end
-- base64
local function base64Decode(text, safe)
local function base64Decode(text)
local raw = text
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
local result = nixio.bin.b64decode(text)
text = text:gsub("_", "/")
text = text:gsub("-", "+")
local mod4 = #text % 4
text = text .. string.sub('====', mod4 + 1)
local result = b64decode(text)
if result then
return result:gsub("%z", "")
else
@ -104,13 +105,7 @@ local function processData(szType, content)
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
result.hashkey = type(content) == 'string' and md5(content) or md5(jsonStringify(content))
if szType == 'ssr' then
local dat = split(content, "/\\?")
local hostInfo = split(dat[1], ':')
@ -119,21 +114,21 @@ local function processData(szType, content)
result.protocol = hostInfo[3]
result.encrypt_method = hostInfo[4]
result.obfs = hostInfo[5]
result.password = base64Decode(hostInfo[6], true)
result.password = base64Decode(hostInfo[6])
local params = {}
for k, v in pairs(split(dat[2], '&')) do
for _, 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)
result.obfs_param = base64Decode(params.bfsparam)
result.protocol_param = base64Decode(params.protoparam)
local group = base64Decode(params.group)
if group then
result.alias = "[" .. group .. "] "
end
result.alias = result.alias .. base64Decode(params.remarks, true)
result.alias = result.alias .. base64Decode(params.remarks)
elseif szType == 'vmess' then
local info = luci.jsonc.parse(content)
local info = jsonParse(content)
result.type = 'v2ray'
result.server = info.add
result.server_port = info.port
@ -143,32 +138,32 @@ local function processData(szType, content)
result.alias = info.ps
result.mux = 1
result.concurrency = 8
if info.net == 'ws'then
result.ws_host = info.host
result.ws_path = info.path
if info.net == 'ws' then
result.ws_host = info.host
result.ws_path = info.path
end
if info.net == 'h2'then
result.h2_host = info.host
result.h2_path = info.path
if info.net == 'h2' then
result.h2_host = info.host
result.h2_path = info.path
end
if info.net == 'tcp'then
result.tcp_guise = info.type
result.http_host = info.host
result.http_path = info.path
if info.net == 'tcp' then
result.tcp_guise = info.type
result.http_host = info.host
result.http_path = info.path
end
if info.net == 'kcp'then
result.kcp_guise = info.type
result.mtu = 1350
result.tti = 50
result.uplink_capacity = 5
result.downlink_capacity = 20
result.read_buffer_size = 2
result.write_buffer_size = 2
if info.net == 'kcp' then
result.kcp_guise = info.type
result.mtu = 1350
result.tti = 50
result.uplink_capacity = 5
result.downlink_capacity = 20
result.read_buffer_size = 2
result.write_buffer_size = 2
end
if info.net == 'quic'then
result.quic_guise = info.type
result.quic_key = info.key
result.quic_security = info.securty
if info.net == 'quic' then
result.quic_guise = info.type
result.quic_key = info.key
result.quic_security = info.securty
end
if not info.security then
result.security = "auto"
@ -187,9 +182,9 @@ local function processData(szType, content)
alias = content:sub(idx_sp + 1, -1)
end
local info = content:sub(1, idx_sp - 1)
local hostInfo = split(base64Decode(info, true), "@")
local hostInfo = split(base64Decode(info), "@")
local host = split(hostInfo[2], ":")
local userinfo = base64Decode(hostInfo[1], true)
local userinfo = base64Decode(hostInfo[1])
local method = userinfo:sub(1, userinfo:find(":") - 1)
local password = userinfo:sub(userinfo:find(":") + 1, #userinfo)
result.alias = UrlDecode(alias)
@ -199,7 +194,7 @@ local function processData(szType, content)
local query = split(host[2], "/\\?")
result.server_port = query[1]
-- local params = {}
-- for k, v in pairs(split(query[2], '&')) do
-- for _, v in pairs(split(query[2], '&')) do
-- local t = split(v, '=')
-- params[t[1]] = t[2]
-- end
@ -217,8 +212,10 @@ local function processData(szType, content)
result.encrypt_method_ss = content.encryption
result.alias = "[" .. content.airport .. "] " .. content.remarks
end
if result.alias == ''then result.alias = result.server ..':'.. result.server_port end
return result, hash
if not result.alias then
result.alias = result.server .. ':' .. result.server_port
end
return result
end
-- wget
local function wget(url)
@ -229,7 +226,6 @@ end
local execute = function()
-- exec
do
-- subscribe_url = {'https://www.google.comc'}
if proxy == '0' then -- 不使用代理更新的话先暂停
log('服务正在暂停')
luci.sys.init.stop(name)
@ -237,7 +233,7 @@ local execute = function()
for k, url in ipairs(subscribe_url) do
local raw = wget(url)
if #raw > 0 then
local node, szType
local nodes, szType
local groupHash = md5(url)
cache[groupHash] = {}
tinsert(nodeResult, {})
@ -246,61 +242,61 @@ local execute = function()
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)
nodes = base64Decode(raw:sub(nEnd + 1, #raw))
nodes = jsonParse(nodes)
local extra = {
airport = node.airport,
port = node.port,
encryption = node.encryption,
password = node.password
airport = nodes.airport,
port = nodes.port,
encryption = nodes.encryption,
password = nodes.password
}
local servers = {}
-- SS里面包着 干脆直接这样
for _, server in ipairs(node.servers) do
for _, server in ipairs(nodes.servers) do
tinsert(servers, setmetatable(server, { __index = extra }))
end
node = servers
nodes = servers
else
-- ssd 外的格式
node = split(base64Decode(raw, true):gsub(" ", "\n"), "\n")
nodes = split(base64Decode(raw):gsub(" ", "\n"), "\n")
end
for _, v in ipairs(node) do
for _, v in ipairs(nodes) do
if v then
v = trim(v)
local result, hash
local result
if szType == 'ssd' then
result, hash = processData(szType, v)
result = processData(szType, v)
elseif not szType then
local dat = split(v, "://")
local node = trim(v)
local dat = split(node, "://")
if dat and dat[1] and dat[2] then
if dat[1] == 'ss' then
result, hash = processData(dat[1], dat[2])
result = processData(dat[1], dat[2])
else
result, hash = processData(dat[1], base64Decode(dat[2], true))
result = processData(dat[1], base64Decode(dat[2]))
end
end
else
log('跳过未知类型: ' .. szType)
end
-- log(hash, result)
if hash or result then
-- log(result)
if result then
if result.alias:find("过期时间") or
result.alias:find("剩余流量") or
result.alias:find("QQ群") or
result.alias:find("官网") or
result.server == ''
not 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]]
cache[groupHash][result.hashkey] = nodeResult[index][#nodeResult[index]]
end
end
end
end
log('成功解析节点数量: ' ..#node)
log('成功解析节点数量: ' ..#nodes)
end
end
end
@ -345,9 +341,9 @@ local execute = function()
end
end
if firstServer then
luci.sys.call("/etc/init.d/" .. name .." restart > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
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 &") -- 不加&的话日志会出现的更早
luci.sys.call("/etc/init.d/" .. name .. " stop > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
end
log('新增节点数量: ' ..add, '删除节点数量: ' .. del)
log('更新成功服务正在启动')