mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-16 04:13:31 +00:00
luci-app-ssr-plus:revert subscribe.lua (#4282)
* luci-app-ssr-plus:Code optimization and Fix Bug * luci-app-ssr-plus:Adjust reference data location * luci-app-ssr-plus:revert subscribe.lua
This commit is contained in:
parent
00d40a40ac
commit
66e6e853be
@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-ssr-plus
|
||||
PKG_VERSION:=176
|
||||
PKG_RELEASE:=1
|
||||
PKG_RELEASE:=2
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
||||
|
||||
|
@ -46,7 +46,7 @@ if nixio.fs.access("/etc/dnsmasq.ssr/ad.conf") then
|
||||
end
|
||||
|
||||
if nixio.fs.access("/etc/ssr/china_ssr.txt") then
|
||||
ip_count = tonumber(luci.sys.exec("cat /etc/china_ssr.txt | wc -l"))
|
||||
ip_count = tonumber(luci.sys.exec("cat /etc/ssr/china_ssr.txt | wc -l"))
|
||||
end
|
||||
|
||||
if nixio.fs.access("/etc/ssr/netflixip.list") then
|
||||
|
@ -20,7 +20,6 @@ config global
|
||||
option netflix_proxy '0'
|
||||
|
||||
config access_control
|
||||
option wan_bp_list '/etc/ssr/china_ssr.txt'
|
||||
option lan_ac_mode 'b'
|
||||
option router_proxy '1'
|
||||
list wan_fw_ips '149.154.160.0/20'
|
||||
|
@ -644,7 +644,7 @@ start_rules() {
|
||||
-S "$udp_server" \
|
||||
-L "$udp_local_port" \
|
||||
-a "$ac_ips" \
|
||||
-i "$(uci_get_by_type access_control wan_bp_list)" \
|
||||
-i "/etc/ssr/china_ssr.txt" \
|
||||
-b "$(uci_get_by_type access_control wan_bp_ips)" \
|
||||
-w "$(uci_get_by_type access_control wan_fw_ips)" \
|
||||
-B "$(uci_get_by_type access_control lan_bp_ips)" \
|
||||
|
@ -3,60 +3,30 @@
|
||||
-- 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'
|
||||
require 'uci'
|
||||
require "luci.model.uci"
|
||||
require "nixio"
|
||||
require "luci.util"
|
||||
require "luci.sys"
|
||||
require "luci.jsonc"
|
||||
-- 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, 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 nodeResult = {} -- update result
|
||||
local application = 'shadowsocksr'
|
||||
local cache = {}
|
||||
local nodeResult = setmetatable({}, { __index = cache }) -- update result
|
||||
local name = 'shadowsocksr'
|
||||
local uciType = 'servers'
|
||||
local ucic2 = uci.cursor()
|
||||
local proxy = ucic2:get(application, '@server_subscribe[0]', 'proxy') or '0'
|
||||
local switch = ucic2:get(application, '@server_subscribe[0]', 'switch') or '1'
|
||||
local subscribe_url = ucic2:get(application, '@server_subscribe[0]', 'subscribe_url') or {}
|
||||
local filter_words = ucic2:get(application, '@server_subscribe[0]', 'filter_words') or '过期时间/剩余流量'
|
||||
ucic2:revert(application)
|
||||
local ucic = luci.model.uci.cursor()
|
||||
local proxy = ucic:get_first(name, 'server_subscribe', 'proxy', '0')
|
||||
local switch = ucic:get_first(name, 'server_subscribe', 'switch', '1')
|
||||
local subscribe_url = ucic:get_first(name, 'server_subscribe', 'subscribe_url', {})
|
||||
local filter_words = ucic:get_first(name, 'server_subscribe', 'filter_words', '过期时间/剩余流量')
|
||||
|
||||
local log = function(...)
|
||||
print(os.date("%Y-%m-%d %H:%M:%S ") .. table.concat({ ... }, " "))
|
||||
end
|
||||
|
||||
-- 获取各项动态配置的当前服务器,可以用 get 和 set, get必须要获取到节点表
|
||||
local CONFIG = {
|
||||
GLOBAL_SERVER = {
|
||||
remarks = '主节点',
|
||||
type = "global", option = "global_server",
|
||||
set = function(server)
|
||||
ucic2:set(application, '@global[0]', "global_server", server)
|
||||
end
|
||||
}
|
||||
}
|
||||
do
|
||||
for k, v in pairs(CONFIG) do
|
||||
local currentNode
|
||||
if v.get then
|
||||
currentNode = v.get()
|
||||
else
|
||||
local cfgid = ucic2:get(application, '@' .. v.type .. '[0]', v.option)
|
||||
if cfgid then
|
||||
currentNode = ucic2:get_all(application, cfgid)
|
||||
end
|
||||
end
|
||||
if currentNode then
|
||||
CONFIG[k].currentNode = currentNode
|
||||
else
|
||||
CONFIG[k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- 分割字符串
|
||||
local function split(full, sep)
|
||||
full = full:gsub("%z", "") -- 这里不是很清楚 有时候结尾带个\0
|
||||
@ -77,15 +47,15 @@ local function split(full, sep)
|
||||
return result
|
||||
end
|
||||
-- urlencode
|
||||
-- local function get_urlencode(c)
|
||||
-- return sformat("%%%02X", sbyte(c))
|
||||
-- end
|
||||
local function get_urlencode(c)
|
||||
return sformat("%%%02X", sbyte(c))
|
||||
end
|
||||
|
||||
-- local function urlEncode(szText)
|
||||
-- local str = szText:gsub("([^0-9a-zA-Z ])", get_urlencode)
|
||||
-- str = str:gsub(" ", "+")
|
||||
-- return str
|
||||
-- end
|
||||
local function urlEncode(szText)
|
||||
local str = szText:gsub("([^0-9a-zA-Z ])", get_urlencode)
|
||||
str = str:gsub(" ", "+")
|
||||
return str
|
||||
end
|
||||
|
||||
local function get_urldecode(h)
|
||||
return schar(tonumber(h, 16))
|
||||
@ -101,7 +71,12 @@ local function trim(text)
|
||||
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)
|
||||
local raw = text
|
||||
@ -123,8 +98,7 @@ local function processData(szType, content)
|
||||
local result = {
|
||||
type = szType,
|
||||
local_port = 1234,
|
||||
kcp_param = '--nocomp',
|
||||
isSubscribe = 1,
|
||||
kcp_param = '--nocomp'
|
||||
}
|
||||
if szType == 'ssr' then
|
||||
local dat = split(content, "/%?")
|
||||
@ -288,6 +262,14 @@ local function processData(szType, content)
|
||||
if not result.alias then
|
||||
result.alias = result.server .. ':' .. result.server_port
|
||||
end
|
||||
-- alias 不参与 hashkey 计算
|
||||
local alias = result.alias
|
||||
result.alias = nil
|
||||
local switch_enable = result.switch_enable
|
||||
result.switch_enable = nil
|
||||
result.hashkey = md5(jsonStringify(result))
|
||||
result.alias = alias
|
||||
result.switch_enable = switch_enable
|
||||
return result
|
||||
end
|
||||
-- wget
|
||||
@ -308,71 +290,20 @@ local function check_filer(result)
|
||||
end
|
||||
end
|
||||
|
||||
local function select_node(nodes, config)
|
||||
local server
|
||||
-- 第一优先级 IP + 端口
|
||||
for id, node in pairs(nodes) do
|
||||
if node.server .. ':' .. node.server_port == config.currentNode.server .. ':' .. config.currentNode.server_port then
|
||||
log('选择【' .. config.remarks .. '】第一匹配节点:' .. node.alias)
|
||||
server = id
|
||||
break
|
||||
end
|
||||
end
|
||||
-- 第二优先级 IP
|
||||
if not server then
|
||||
for id, node in pairs(nodes) do
|
||||
if node.server == config.currentNode.server then
|
||||
log('选择【' .. config.remarks .. '】第二匹配节点:' .. node.alias)
|
||||
server = id
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
-- 第三优先级备注
|
||||
if not server then
|
||||
for id, node in pairs(nodes) do
|
||||
if node.alias == config.currentNode.alias then
|
||||
log('选择【' .. config.remarks .. '】第三匹配节点:' .. node.alias)
|
||||
server = id
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
-- 第四 cfgid
|
||||
if not server then
|
||||
for id, node in pairs(nodes) do
|
||||
if id == config.currentNode['.name'] then
|
||||
log('选择【' .. config.remarks .. '】第四匹配节点:' .. node.alias)
|
||||
server = id
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
-- 还不行 随便找一个
|
||||
if not server then
|
||||
server = ucic2:get(application, '@'.. uciType .. '[0]')
|
||||
if server then
|
||||
log('无法找到最匹配的节点,当前已更换为' .. ucic2:get_all(application, server).alias)
|
||||
end
|
||||
end
|
||||
if server then
|
||||
config.set(server)
|
||||
end
|
||||
end
|
||||
|
||||
local execute = function()
|
||||
-- exec
|
||||
do
|
||||
if proxy == '0' then -- 不使用代理更新的话先暂停
|
||||
log('服务正在暂停')
|
||||
luci.sys.init.stop(application)
|
||||
luci.sys.init.stop(name)
|
||||
end
|
||||
for k, url in ipairs(subscribe_url) do
|
||||
local raw = wget(url)
|
||||
if #raw > 0 then
|
||||
local nodes, szType
|
||||
local all_odes = {}
|
||||
tinsert(nodeResult, all_odes)
|
||||
local groupHash = md5(url)
|
||||
cache[groupHash] = {}
|
||||
tinsert(nodeResult, {})
|
||||
local index = #nodeResult
|
||||
-- SSD 似乎是这种格式 ssd:// 开头的
|
||||
if raw:find('ssd://') then
|
||||
@ -425,7 +356,9 @@ local execute = function()
|
||||
log('丢弃无效节点: ' .. result.type ..' 节点, ' .. result.alias)
|
||||
else
|
||||
log('成功解析: ' .. result.type ..' 节点, ' .. result.alias)
|
||||
tinsert(all_odes, result)
|
||||
result.grouphashkey = groupHash
|
||||
tinsert(nodeResult[index], result)
|
||||
cache[groupHash][result.hashkey] = nodeResult[index][#nodeResult[index]]
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -438,45 +371,60 @@ local execute = function()
|
||||
end
|
||||
-- diff
|
||||
do
|
||||
assert(next(nodeResult), '更新失败,没有可用的节点信息')
|
||||
-- delete all for subscribe nodes
|
||||
ucic2:foreach(application, uciType, function(node)
|
||||
if node.isSubscribe or node.hashkey then -- 兼容之前的hashkey
|
||||
ucic2:delete(application, node['.name'])
|
||||
if next(nodeResult) == nil then
|
||||
log("更新失败,没有可用的节点信息")
|
||||
return
|
||||
end
|
||||
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
|
||||
if not old.alias then
|
||||
old.alias = old.server .. ':' .. old.server_port
|
||||
end
|
||||
log('忽略手动添加的节点: ' .. old.alias)
|
||||
end
|
||||
end)
|
||||
for _, v in ipairs(nodeResult) do
|
||||
for _, vv in ipairs(v) do
|
||||
vv.switch_enable = switch
|
||||
local cfgid = ucic2:add(application, uciType)
|
||||
for kkk, vvv in pairs(vv) do
|
||||
ucic2:set(application, cfgid, kkk, vvv)
|
||||
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)
|
||||
ucic:set(name, section, "switch_enable", switch)
|
||||
add = add + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
ucic2:commit(application)
|
||||
local ucic3 = uci.cursor()
|
||||
-- repair configuration
|
||||
if next(CONFIG) then
|
||||
local nodes = {}
|
||||
ucic3:foreach(application, uciType, function(node)
|
||||
if node.server and node.server_port and node.alias then
|
||||
nodes[node['.name']] = node
|
||||
ucic:commit(name)
|
||||
-- 如果原有服务器节点已经不见了就尝试换为第一个节点
|
||||
local globalServer = ucic:get_first(name, 'global', 'global_server', '')
|
||||
local firstServer = ucic:get_first(name, uciType)
|
||||
if firstServer then
|
||||
if not ucic:get(name, globalServer) then
|
||||
luci.sys.call("/etc/init.d/" .. name .. " stop > /dev/null 2>&1 &")
|
||||
ucic:commit(name)
|
||||
ucic:set(name, ucic:get_first(name, 'global'), 'global_server', ucic:get_first(name, uciType))
|
||||
ucic:commit(name)
|
||||
log('当前主服务器节点已被删除,正在自动更换为第一个节点。')
|
||||
luci.sys.call("/etc/init.d/" .. name .. " start > /dev/null 2>&1 &")
|
||||
else
|
||||
log('维持当前主服务器节点。')
|
||||
luci.sys.call("/etc/init.d/" .. name .." restart > /dev/null 2>&1 &")
|
||||
end
|
||||
end)
|
||||
for _, config in pairs(CONFIG) do
|
||||
select_node(nodes, config)
|
||||
else
|
||||
log('没有服务器节点了,停止服务')
|
||||
luci.sys.call("/etc/init.d/" .. name .. " stop > /dev/null 2>&1 &")
|
||||
end
|
||||
ucic3:commit(application)
|
||||
end
|
||||
-- select first server
|
||||
local globalServer = ucic3:get(application, '@global[0]', 'global_server') or ''
|
||||
if not globalServer or not ucic3:get_all(application, globalServer) then
|
||||
ucic3:set(application, '@global[0]', 'global_server', select(2, ucic3:get(application, '@' .. uciType .. '[0]')))
|
||||
ucic3:commit(application)
|
||||
log('当前没有主节点,自动选择第一个节点开启服务。')
|
||||
end
|
||||
luci.sys.call("/etc/init.d/" .. application .." restart > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
|
||||
log('新增节点数量: ' ..add, '删除节点数量: ' .. del)
|
||||
log('订阅更新成功')
|
||||
end
|
||||
end
|
||||
@ -486,11 +434,12 @@ if subscribe_url and #subscribe_url > 0 then
|
||||
log(e)
|
||||
log(debug.traceback())
|
||||
log('发生错误, 正在恢复服务')
|
||||
if CONFIG.GLOBAL_SERVER and CONFIG.GLOBAL_SERVER.currentNode then
|
||||
luci.sys.call("/etc/init.d/" .. application .." restart > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
|
||||
local firstServer = ucic:get_first(name, uciType)
|
||||
if firstServer then
|
||||
luci.sys.call("/etc/init.d/" .. name .." restart > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
|
||||
log('重启服务成功')
|
||||
else
|
||||
luci.sys.call("/etc/init.d/" .. application .." stop > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
|
||||
luci.sys.call("/etc/init.d/" .. name .." stop > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
|
||||
log('停止服务成功')
|
||||
end
|
||||
end)
|
||||
|
Loading…
Reference in New Issue
Block a user