mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-09-12 19:34:23 +08:00
update 2026-08-08 16:33:49
This commit is contained in:
+2
-2
@@ -5,12 +5,12 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=dae
|
||||
PKG_VERSION:=2026.08.06
|
||||
PKG_VERSION:=2026.08.08
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_VERSION:=c7547891533d195731507977cb36734a5a18aa14
|
||||
PKG_SOURCE_VERSION:=f52534a912a2f0a1406740384684667c1ece89c0
|
||||
PKG_SOURCE_URL:=https://github.com/olicesx/dae.git
|
||||
PKG_MIRROR_HASH:=skip
|
||||
|
||||
|
||||
+2
-2
@@ -8,12 +8,12 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ddns-go
|
||||
PKG_VERSION:=6.17.4
|
||||
PKG_VERSION:=6.17.5
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/jeessy2/ddns-go/tar.gz/v$(PKG_VERSION)?
|
||||
PKG_HASH:=80f3816d95933949ce7306b988b2612d91b95c6992af8e956378628fde19b615
|
||||
PKG_HASH:=910ba8e64d05fd48043f4c88492f32f459367be022ec08f0aa6e977c5c3419bf
|
||||
|
||||
PKG_LICENSE:=MIT
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
function arraysEqual(a, b) {
|
||||
if (a === b) return true;
|
||||
if (a == null || b == null) return false;
|
||||
if (a.length !== b.length) return false;
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (a[i] !== b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function waitForElement(selector, callback) {
|
||||
const el = document.querySelector(selector);
|
||||
if (el) return callback(el);
|
||||
const observer = new MutationObserver(() => {
|
||||
const el = document.querySelector(selector);
|
||||
if (el) {
|
||||
observer.disconnect();
|
||||
callback(el);
|
||||
}
|
||||
});
|
||||
observer.observe(document.body, { childList: true, subtree: true });
|
||||
}
|
||||
|
||||
function get_current_url() {
|
||||
return window.location.origin + window.location.pathname;
|
||||
}
|
||||
|
||||
function getOption(config, section, opt) {
|
||||
let obj;
|
||||
const id = `cbid.${config}.${section}.${opt}`;
|
||||
obj = document.getElementsByName(id)[0] || document.getElementById(id);
|
||||
if (obj) {
|
||||
const combobox = document.getElementById('cbi.combobox.' + id);
|
||||
if (combobox) {
|
||||
obj.combobox = combobox;
|
||||
}
|
||||
const div = document.getElementById(id);
|
||||
if (div && div.getElementsByTagName("li").length > 0) {
|
||||
obj = div;
|
||||
}
|
||||
return obj;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -79,8 +79,8 @@ function index()
|
||||
entry({"admin", "services", appname, "connect_status"}, call("connect_status")).leaf = true
|
||||
entry({"admin", "services", appname, "ping_node"}, call("ping_node")).leaf = true
|
||||
entry({"admin", "services", appname, "urltest_node"}, call("urltest_node")).leaf = true
|
||||
entry({"admin", "services", appname, "update_config"}, call("update_config")).leaf = true
|
||||
entry({"admin", "services", appname, "add_node"}, call("add_node")).leaf = true
|
||||
entry({"admin", "services", appname, "update_node"}, call("update_node")).leaf = true
|
||||
entry({"admin", "services", appname, "set_node"}, call("set_node")).leaf = true
|
||||
entry({"admin", "services", appname, "copy_node"}, call("copy_node")).leaf = true
|
||||
entry({"admin", "services", appname, "clear_all_nodes"}, call("clear_all_nodes")).leaf = true
|
||||
@@ -96,6 +96,10 @@ function index()
|
||||
entry({"admin", "services", appname, "subscribe_manual"}, call("subscribe_manual")).leaf = true
|
||||
entry({"admin", "services", appname, "subscribe_manual_all"}, call("subscribe_manual_all")).leaf = true
|
||||
entry({"admin", "services", appname, "flush_set"}, call("flush_set")).leaf = true
|
||||
entry({"admin", "services", appname, "get_shunt_rules"}, call("get_shunt_rules")).leaf = true
|
||||
entry({"admin", "services", appname, "add_shunt_rule"}, call("add_shunt_rule")).leaf = true
|
||||
entry({"admin", "services", appname, "delete_select_shunt_rules"}, call("delete_select_shunt_rules")).leaf = true
|
||||
entry({"admin", "services", appname, "save_shunt_rule_order"}, call("save_shunt_rule_order")).leaf = true
|
||||
|
||||
--[[rule_list]]
|
||||
entry({"admin", "services", appname, "read_rulelist"}, call("read_rulelist")).leaf = true
|
||||
@@ -471,6 +475,23 @@ function urltest_node()
|
||||
http_write_json(e)
|
||||
end
|
||||
|
||||
function update_config()
|
||||
local id = http.formvalue("id") -- Node id
|
||||
local data = http.formvalue("data") -- json new Data
|
||||
if id and data then
|
||||
local data_t = jsonParse(data) or {}
|
||||
if next(data_t) then
|
||||
for k, v in pairs(data_t) do
|
||||
uci:set(appname, id, k, v)
|
||||
end
|
||||
api.uci_save(uci, appname)
|
||||
http_write_json_ok()
|
||||
return
|
||||
end
|
||||
end
|
||||
http_write_json_error()
|
||||
end
|
||||
|
||||
function add_node()
|
||||
local redirect = http.formvalue("redirect")
|
||||
|
||||
@@ -493,23 +514,6 @@ function add_node()
|
||||
end
|
||||
end
|
||||
|
||||
function update_node()
|
||||
local id = http.formvalue("id") -- Node id
|
||||
local data = http.formvalue("data") -- json new Data
|
||||
if id and data then
|
||||
local data_t = jsonParse(data) or {}
|
||||
if next(data_t) then
|
||||
for k, v in pairs(data_t) do
|
||||
uci:set(appname, id, k, v)
|
||||
end
|
||||
api.uci_save(uci, appname)
|
||||
http_write_json_ok()
|
||||
return
|
||||
end
|
||||
end
|
||||
http_write_json_error()
|
||||
end
|
||||
|
||||
function set_node()
|
||||
local protocol = http.formvalue("protocol")
|
||||
local section = http.formvalue("section")
|
||||
@@ -1134,3 +1138,87 @@ function fetch_certsha256()
|
||||
local data = api.fetch_cert_sha256(address, port, sni, timeout, h3)
|
||||
http_write_json(data ~= "" and { code = 1, data = data } or { code = 0 })
|
||||
end
|
||||
|
||||
function get_shunt_rules()
|
||||
local id = http.formvalue("id")
|
||||
local result = {}
|
||||
|
||||
if id then
|
||||
result = uci:get_all(appname, id)
|
||||
else
|
||||
local default_items = {}
|
||||
local other_items = {}
|
||||
uci:foreach(appname, "shunt_rules", function(t)
|
||||
if not t.group or t.group == "" then
|
||||
default_items[#default_items + 1] = t
|
||||
else
|
||||
other_items[#other_items + 1] = t
|
||||
end
|
||||
end)
|
||||
for i = 1, #default_items do result[#result + 1] = default_items[i] end
|
||||
for i = 1, #other_items do result[#result + 1] = other_items[i] end
|
||||
end
|
||||
http_write_json(result)
|
||||
end
|
||||
|
||||
function add_shunt_rule()
|
||||
local add_name = http.formvalue("add_name")
|
||||
local redirect = http.formvalue("redirect")
|
||||
|
||||
local uuid = add_name
|
||||
if add_name then
|
||||
local has = uci:get(appname, uuid)
|
||||
if has then
|
||||
http_write_json_error({ message = "This ID already exists." })
|
||||
return
|
||||
end
|
||||
else
|
||||
uuid = api.gen_short_uuid()
|
||||
end
|
||||
uci:section(appname, "shunt_rules", uuid)
|
||||
|
||||
local group = http.formvalue("group")
|
||||
if group and group ~= "default" then
|
||||
uci:set(appname, uuid, "group", group)
|
||||
end
|
||||
|
||||
if redirect == "1" then
|
||||
api.uci_save(uci, appname)
|
||||
http.redirect(api.url("shunt_rules", uuid))
|
||||
else
|
||||
api.uci_save(uci, appname)
|
||||
http_write_json_ok({uuid = uuid, redirect_url = api.url("shunt_rules", uuid)})
|
||||
end
|
||||
end
|
||||
|
||||
function delete_select_shunt_rules()
|
||||
local ids = http.formvalue("ids")
|
||||
local redirect = http.formvalue("redirect")
|
||||
string.gsub(ids, '[^' .. "," .. ']+', function(w)
|
||||
uci:foreach(appname, "nodes", function(s)
|
||||
if s["protocol"] and s["protocol"] == "_shunt" then
|
||||
uci:delete(appname, s[".name"], w)
|
||||
end
|
||||
end)
|
||||
uci:delete(appname, w)
|
||||
end)
|
||||
if redirect == "1" then
|
||||
api.uci_save(uci, appname)
|
||||
http.redirect(api.url("rule"))
|
||||
else
|
||||
api.uci_save(uci, appname, true, true)
|
||||
end
|
||||
end
|
||||
|
||||
function save_shunt_rule_order()
|
||||
local ids = http.formvalue("ids") or ""
|
||||
local new_order = {}
|
||||
for id in ids:gmatch("([^,]+)") do
|
||||
new_order[#new_order + 1] = id
|
||||
end
|
||||
for idx, name in ipairs(new_order) do
|
||||
luci.sys.call(string.format("uci -q reorder %s.%s=%d", appname, name, idx - 1))
|
||||
end
|
||||
api.sh_uci_commit(appname)
|
||||
http_write_json({ status = "ok" })
|
||||
end
|
||||
|
||||
@@ -154,6 +154,7 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
|
||||
if current_node.protocol == "_shunt" then
|
||||
local shunt_lua = loadfile("/usr/lib/lua/luci/model/cbi/passwall/client/include/shunt_options.lua")
|
||||
setfenv(shunt_lua, getfenv(1))(m, s, {
|
||||
s_cfgid = s:cfgsections()[1],
|
||||
node_id = current_node_id,
|
||||
node = current_node,
|
||||
socks_list = socks_list,
|
||||
|
||||
@@ -4,9 +4,17 @@ if not data.node_id or not data.node then
|
||||
return
|
||||
end
|
||||
|
||||
local s_cfgid = data.s_cfgid
|
||||
local current_node_id = data.node_id
|
||||
local node_list = data.node_list or api.get_node_list()
|
||||
|
||||
local groups = {}
|
||||
m.uci:foreach(appname, "shunt_rules", function(s)
|
||||
if s.group and s.group ~= "" then
|
||||
groups[s.group] = true
|
||||
end
|
||||
end)
|
||||
|
||||
local function get_cfgvalue()
|
||||
return function(self, section)
|
||||
return m:get(current_node_id, self.option)
|
||||
@@ -92,15 +100,27 @@ o = add_option(Flag, "fakedns", '<a style="color:#FF8C00">FakeDNS</a>' .. " " ..
|
||||
translate("Suitable scenarios for let the node servers get the target domain names.") .. "<br>" ..
|
||||
translate("Such as: DNS unlocking of streaming media, reducing DNS query latency, etc."))
|
||||
|
||||
shunt_group = add_option(ListValue, "shunt_group", translate("Shunt Rule Group"))
|
||||
shunt_group:value("", translate("default"))
|
||||
for k, v in pairs(groups) do
|
||||
shunt_group:value(k)
|
||||
end
|
||||
|
||||
local shunt_group_val = m:get(current_node_id, "shunt_group") or ""
|
||||
shunt_group_val = shunt_group_val:lower()
|
||||
local shunt_rules = {}
|
||||
m.uci:foreach(appname, "shunt_rules", function(e)
|
||||
e.id = e[".name"]
|
||||
e.remarks = e.remarks or e[".name"]
|
||||
e["_node_option"] = e[".name"]
|
||||
e["_node_default"] = ""
|
||||
e["_fakedns_option"] = e[".name"] .. "_fakedns"
|
||||
e["_proxy_tag_option"] = e[".name"] .. "_proxy_tag"
|
||||
table.insert(shunt_rules, e)
|
||||
local group = e.group or ""
|
||||
group = group:lower()
|
||||
if group == shunt_group_val then
|
||||
e.id = e[".name"]
|
||||
e.remarks = e.remarks or e[".name"]
|
||||
e["_node_option"] = e[".name"]
|
||||
e["_node_default"] = ""
|
||||
e["_fakedns_option"] = e[".name"] .. "_fakedns"
|
||||
e["_proxy_tag_option"] = e[".name"] .. "_proxy_tag"
|
||||
table.insert(shunt_rules, e)
|
||||
end
|
||||
end)
|
||||
table.insert(shunt_rules, {
|
||||
id = ".default",
|
||||
@@ -185,6 +205,8 @@ end
|
||||
|
||||
local footer = Template(appname .. "/include/shunt_options")
|
||||
footer.api = api
|
||||
footer.config = m.config
|
||||
footer.id = current_node_id
|
||||
footer.s_cfgid = s_cfgid or current_node_id
|
||||
footer.normal_list = api.jsonc.stringify(node_list.normal_list)
|
||||
m:append(footer)
|
||||
|
||||
@@ -145,34 +145,8 @@ end
|
||||
|
||||
s:append(Template(appname .. "/rule/rule_version"))
|
||||
|
||||
local cfgname = "shunt_rules"
|
||||
|
||||
if has_xray or has_singbox then
|
||||
s = m:section(TypedSection, cfgname, "Sing-Box/Xray " .. translate("Shunt Rule"), "<a style='color: red'>" .. translate("Please note attention to the priority, the higher the order, the higher the priority.") .. "</a>")
|
||||
s.template = "cbi/tblsection"
|
||||
s.anonymous = false
|
||||
s.addremove = true
|
||||
s.sortable = true
|
||||
s.extedit = api.url("shunt_rules", "%s")
|
||||
function s.create(e, t)
|
||||
TypedSection.create(e, t)
|
||||
luci.http.redirect(e.extedit:format(t))
|
||||
end
|
||||
function s.remove(e, t)
|
||||
m.uci:foreach(appname, "nodes", function(s)
|
||||
if s["protocol"] and s["protocol"] == "_shunt" then
|
||||
m:del(s[".name"], t)
|
||||
end
|
||||
end)
|
||||
TypedSection.remove(e, t)
|
||||
end
|
||||
|
||||
o = s:option(DummyValue, "remarks", translate("Remarks"))
|
||||
m:append(Template(appname .. "/rule/shunt_rule_list"))
|
||||
end
|
||||
|
||||
local sortable = Template(appname .. "/cbi/sortable")
|
||||
sortable.api = api
|
||||
sortable.target_cfgname = cfgname
|
||||
m:append(sortable)
|
||||
|
||||
return api.return_map(m)
|
||||
|
||||
@@ -44,6 +44,19 @@ function clean_text(text)
|
||||
:gsub("[ \t]*\n[ \t]*", "\n")
|
||||
end
|
||||
|
||||
local remarks_lookup = {}
|
||||
local groups = {}
|
||||
m.uci:foreach(appname, "shunt_rules", function(s)
|
||||
if s[".name"] ~= arg[1] then
|
||||
if s.remarks then
|
||||
remarks_lookup[s.remarks] = s[".name"]
|
||||
end
|
||||
if s.group and s.group ~= "" then
|
||||
groups[s.group] = true
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
s = m:section(NamedSection, arg[1], "shunt_rules", "")
|
||||
s.addremove = false
|
||||
s.dynamic = false
|
||||
@@ -56,9 +69,34 @@ remarks.validate = function(self, value, section)
|
||||
if value == "" then
|
||||
return nil, translate("Remark cannot be empty.")
|
||||
end
|
||||
if remarks_lookup[value] then
|
||||
return nil, translate("This remark already exists, please change a new remark.")
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
o = s:option(Value, "group", translate("Shunt Rule Group"))
|
||||
o.default = ""
|
||||
o:value("", translate("default"))
|
||||
for k, v in pairs(groups) do
|
||||
o:value(k)
|
||||
end
|
||||
o.write = function(self, section, value)
|
||||
value = api.trim(value)
|
||||
local lower = value:lower()
|
||||
|
||||
if lower == "" or lower == "default" then
|
||||
return m:del(section, self.option)
|
||||
end
|
||||
|
||||
for _, v in ipairs(self.keylist or {}) do
|
||||
if v:lower() == lower then
|
||||
return m:set(section, self.option, v)
|
||||
end
|
||||
end
|
||||
m:set(section, self.option, value)
|
||||
end
|
||||
|
||||
protocol = s:option(MultiValue, "protocol", translate("Protocol"))
|
||||
protocol:value("http")
|
||||
protocol:value("tls")
|
||||
|
||||
@@ -1594,11 +1594,15 @@ function gen_config(var)
|
||||
[".name"] = "GFW_Mode_List",
|
||||
remarks = "GFW_Mode_List",
|
||||
domain_list = (domain_list ~= "") and domain_list or nil,
|
||||
ip_list = (ip_list ~= "") and ip_list or nil
|
||||
ip_list = (ip_list ~= "") and ip_list or nil,
|
||||
group = node["shunt_group"]
|
||||
})
|
||||
end
|
||||
end
|
||||
foreach_shunt_rule(function(e)
|
||||
if node["shunt_group"] ~= e.group then
|
||||
return
|
||||
end
|
||||
local outboundTag = gen_shunt_node(e[".name"])
|
||||
if outboundTag and e.remarks then
|
||||
if outboundTag == "default" then
|
||||
|
||||
@@ -1405,11 +1405,15 @@ function gen_config(var)
|
||||
[".name"] = "GFW_Mode_List",
|
||||
remarks = "GFW_Mode_List",
|
||||
domain_list = (domain_list ~= "") and domain_list or nil,
|
||||
ip_list = (ip_list ~= "") and ip_list or nil
|
||||
ip_list = (ip_list ~= "") and ip_list or nil,
|
||||
group = node["shunt_group"]
|
||||
})
|
||||
end
|
||||
end
|
||||
foreach_shunt_rule(function(e)
|
||||
if node["shunt_group"] ~= e.group then
|
||||
return
|
||||
end
|
||||
local outbound_tag = gen_shunt_node(e[".name"])
|
||||
if outbound_tag and e.remarks then
|
||||
if outbound_tag == "default" then
|
||||
|
||||
@@ -1,2 +1,24 @@
|
||||
<!-- map header -->
|
||||
<script src="<%=resource%>/view/<%=self.api.appname%>/cbi.js"></script>
|
||||
<script src="<%=resource%>/view/<%=self.api.appname%>/func.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
function update_config(cfgid, data, redirect_url) {
|
||||
XHR.get('<%=self.api.url("update_config")%>', {
|
||||
id: cfgid,
|
||||
data: JSON.stringify(data)
|
||||
},
|
||||
function(x, data) {
|
||||
if (x && x.status == 200 && data.code == 1) {
|
||||
if (redirect_url) {
|
||||
window.location.href = redirect_url;
|
||||
}
|
||||
}
|
||||
else {
|
||||
alert("<%:Error%>");
|
||||
}
|
||||
});
|
||||
}
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
@@ -256,7 +256,7 @@ local appname = api.appname
|
||||
let new_val = el.target.value
|
||||
const new_hasItem = shunt_list.find(element => element.id == new_val);
|
||||
if (new_hasItem) {
|
||||
XHR.get('<%=api.url("update_node")%>', {
|
||||
XHR.get('<%=api.url("update_config")%>', {
|
||||
id: "<%=self.global_cfgid%>",
|
||||
data: JSON.stringify({
|
||||
tcp_node: new_val
|
||||
|
||||
@@ -53,6 +53,22 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
waitForElement('select[name*="<%=self.config%>"][name*="shunt_group"]', function(el) {
|
||||
let o_val = el.value;
|
||||
el.addEventListener("change", () => {
|
||||
el.blur();
|
||||
if (o_val != el.value) {
|
||||
let save = true;
|
||||
if (save) {
|
||||
update_config("<%=self.id%>", {
|
||||
shunt_group: getOption("<%=self.config%>", "<%=self.s_cfgid%>", "shunt_group").value,
|
||||
}, get_current_url());
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
document.addEventListener("DOMContentLoaded", () => setTimeout(() => {
|
||||
refresh_depends();
|
||||
const table_dom = document.getElementById("cbi-passwall-shunt_option_list");
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<%
|
||||
local api = self.api
|
||||
-%>
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
let node_id = "<%=self.section%>";
|
||||
let node_config_url = '<%=self.api.url("node_config")%>/' + node_id;
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
waitForElement('select[name*="<%=self.config%>"][name*="type"]', function(el) {
|
||||
let o_val = el.value;
|
||||
@@ -11,13 +11,18 @@ local api = self.api
|
||||
if (o_val != el.value) {
|
||||
let save = true;
|
||||
if (save) {
|
||||
//document.getElementsByClassName('cbi-button-save')[0].click();
|
||||
update_node({
|
||||
remarks: getOption("remarks").value,
|
||||
group: getOption("group").value,
|
||||
type: getOption("type").value,
|
||||
/*
|
||||
const saveBtn = document.getElementsByClassName('cbi-button-save');
|
||||
if (saveBtn && saveBtn.length > 0) {
|
||||
saveBtn[saveBtn.length - 1].click();
|
||||
}
|
||||
*/
|
||||
update_config(node_id, {
|
||||
remarks: getOption("<%=self.config%>", "<%=self.section%>", "remarks").value,
|
||||
group: getOption("<%=self.config%>", "<%=self.section%>", "group").value,
|
||||
type: getOption("<%=self.config%>", "<%=self.section%>", "type").value,
|
||||
//protocol: ''
|
||||
});
|
||||
}, node_config_url);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -31,12 +36,17 @@ local api = self.api
|
||||
let name = name_split[name_split.length - 1];
|
||||
let save = true;
|
||||
if (save) {
|
||||
//document.getElementsByClassName('cbi-button-save')[0].click();
|
||||
update_node({
|
||||
remarks: getOption("remarks").value,
|
||||
group: getOption("group").value,
|
||||
protocol: getOption(name).value
|
||||
});
|
||||
/*
|
||||
const saveBtn = document.getElementsByClassName('cbi-button-save');
|
||||
if (saveBtn && saveBtn.length > 0) {
|
||||
saveBtn[saveBtn.length - 1].click();
|
||||
}
|
||||
*/
|
||||
update_config(node_id, {
|
||||
remarks: getOption("<%=self.config%>", "<%=self.section%>", "remarks").value,
|
||||
group: getOption("<%=self.config%>", "<%=self.section%>", "group").value,
|
||||
protocol: getOption("<%=self.config%>", "<%=self.section%>", name).value,
|
||||
}, node_config_url);
|
||||
} else {
|
||||
window.location.href = node_config_url + "?select_proto=" + el.value;
|
||||
}
|
||||
|
||||
@@ -1,64 +1,11 @@
|
||||
<%
|
||||
local api = self.api
|
||||
-%>
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
let node_id = "<%=self.section%>";
|
||||
let node_config_url = '<%=api.url("node_config")%>/' + node_id;
|
||||
|
||||
function waitForElement(selector, callback) {
|
||||
const el = document.querySelector(selector);
|
||||
if (el) return callback(el);
|
||||
const observer = new MutationObserver(() => {
|
||||
const el = document.querySelector(selector);
|
||||
if (el) {
|
||||
observer.disconnect();
|
||||
callback(el);
|
||||
}
|
||||
});
|
||||
observer.observe(document.body, { childList: true, subtree: true });
|
||||
}
|
||||
|
||||
function getOption(opt) {
|
||||
var obj;
|
||||
var id = 'cbid.<%=self.config%>.' + node_id + '.' + opt;
|
||||
obj = document.getElementsByName(id)[0] || document.getElementById(id);
|
||||
if (obj) {
|
||||
var combobox = document.getElementById('cbi.combobox.' + id);
|
||||
if (combobox) {
|
||||
obj.combobox = combobox;
|
||||
}
|
||||
var div = document.getElementById(id);
|
||||
if (div && div.getElementsByTagName("li").length > 0) {
|
||||
obj = div;
|
||||
}
|
||||
return obj;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function update_node(data) {
|
||||
XHR.get('<%=api.url("update_node")%>', {
|
||||
id: node_id,
|
||||
data: JSON.stringify(data)
|
||||
},
|
||||
function(x, data) {
|
||||
if (x && x.status == 200 && data.code == 1) {
|
||||
window.location.href = node_config_url;
|
||||
}
|
||||
else {
|
||||
alert("<%:Error%>");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function fetchCertSha256(el) {
|
||||
if (el.getAttribute("data-loading") === "1") return;
|
||||
el.setAttribute("data-loading", "1");
|
||||
el.style.pointerEvents = "none";
|
||||
el.style.color = "red";
|
||||
XHR.get('<%=api.url("fetch_certsha256")%>', { id: node_id }, function(x, res) {
|
||||
XHR.get('<%=self.api.url("fetch_certsha256")%>', { id: "<%=self.section%>" }, function(x, res) {
|
||||
el.setAttribute("data-loading", "0");
|
||||
el.style.pointerEvents = "";
|
||||
el.style.color = "";
|
||||
|
||||
@@ -0,0 +1,475 @@
|
||||
<%
|
||||
local api = require "luci.passwall.api"
|
||||
local appname = api.appname
|
||||
local uci = api.uci
|
||||
-%>
|
||||
<script src="<%=resource%>/view/<%=appname%>/Sortable.min.js"></script>
|
||||
|
||||
<style>
|
||||
table th, .table .th {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
table td, .table .td {
|
||||
text-align: center;
|
||||
/* white-space: nowrap; */
|
||||
word-break: keep-all;
|
||||
}
|
||||
|
||||
.td.cbi-section-actions {
|
||||
text-align: right !important;
|
||||
}
|
||||
|
||||
.shunt_rule-wrapper {
|
||||
align-items: center;
|
||||
display: inline-flex !important;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.cbi-tabmenu > li {
|
||||
margin-right: 2px !important;
|
||||
}
|
||||
|
||||
.cbi-tabmenu > li:last-child {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
|
||||
.shunt_rule-wrapper .drag-handle {
|
||||
cursor: grab !important;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
font-weight: 100;
|
||||
padding: 0 !important;
|
||||
line-height: inherit;
|
||||
user-select: none;
|
||||
align-self: stretch;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.shunt_rule-wrapper .drag-handle:hover {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* enable flex for small screens*/
|
||||
@media screen and (max-width: 1152px) {
|
||||
.cbi-section-table-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.cbi-section-table-titles {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.td-actions {
|
||||
padding-top: 0 !important;
|
||||
border-top-width: 0 !important;
|
||||
flex: 1 1 350px;
|
||||
}
|
||||
}
|
||||
|
||||
/* shrink actionbar even further for mobile devices */
|
||||
@media screen and (max-width: 500px) {
|
||||
.shunt_rule-wrapper {
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.cbi-button {
|
||||
margin-left: 0 !important;
|
||||
margin-right: 1px !important;
|
||||
}
|
||||
|
||||
.td-actions {
|
||||
padding-left: 5px!important;
|
||||
padding-right: 5px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.sortable-chosen {
|
||||
background-color: rgba(220, 235, 245, 0.4) !important;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.sortable-ghost {
|
||||
background: #cce5ff !important;
|
||||
height: 3px !important;
|
||||
}
|
||||
|
||||
.dragging-row {
|
||||
background-color: rgba(131, 191, 255, 0.7) !important;
|
||||
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
||||
}
|
||||
</style>
|
||||
|
||||
<% if api.is_js_luci() then -%>
|
||||
<script type="text/javascript">
|
||||
var cbi_t = [];
|
||||
function cbi_t_add(section, tab) {
|
||||
var t = document.getElementById('tab.' + section + '.' + tab);
|
||||
var c = document.getElementById('container.' + section + '.' + tab);
|
||||
|
||||
if( t && c ) {
|
||||
cbi_t[section] = (cbi_t[section] || [ ]);
|
||||
cbi_t[section][tab] = { 'tab': t, 'container': c, 'cid': c.id };
|
||||
}
|
||||
}
|
||||
|
||||
function cbi_t_switch(section, tab) {
|
||||
if( cbi_t[section] && cbi_t[section][tab] ) {
|
||||
// Before switching tabs, first deselect all currently active tabs.
|
||||
var o = cbi_t[section][tab];
|
||||
var h = document.getElementById('tab.' + section);
|
||||
for( var tid in cbi_t[section] ) {
|
||||
var o2 = cbi_t[section][tid];
|
||||
if( o.tab.id != o2.tab.id ) {
|
||||
o2.tab.className = o2.tab.className.replace(/(^| )cbi-tab( |$)/, " cbi-tab-disabled ");
|
||||
o2.container.style.display = 'none';
|
||||
}
|
||||
else {
|
||||
if(h) h.value = tab;
|
||||
o2.tab.className = o2.tab.className.replace(/(^| )cbi-tab-disabled( |$)/, " cbi-tab ");
|
||||
o2.container.style.display = 'block';
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
</script>
|
||||
<%- end %>
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
function toPage(action, cbi_id) {
|
||||
if (action == "add") {
|
||||
const dom = document.getElementsByClassName("cbi-tab")[0];
|
||||
const current_group = dom ? (dom.getAttribute("group_name") || "default") : "default";
|
||||
const add_name_val = document.getElementById("add_name_" + current_group).value;
|
||||
if (add_name_val.length > 1) {
|
||||
XHR.get('<%=api.url("add_shunt_rule")%>', {
|
||||
add_name: add_name_val,
|
||||
group: current_group
|
||||
},
|
||||
function(x, result) {
|
||||
if (x && x.status === 200) {
|
||||
if (result.code == 1) {
|
||||
window.location.href = result.data.redirect_url;
|
||||
} else {
|
||||
alert(result.data.message);
|
||||
}
|
||||
} else {
|
||||
alert("<%:Save failed!%>");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
if (action == "edit") {
|
||||
window.location.href='<%=api.url("shunt_rules")%>/' + cbi_id;
|
||||
}
|
||||
if (action == "del") {
|
||||
window.location.href = '<%=api.url("delete_select_shunt_rules")%>' + "?redirect=1&ids=" + cbi_id;
|
||||
}
|
||||
}
|
||||
|
||||
function row_top(btn, group) {
|
||||
const row = btn.closest("tr");
|
||||
if (!row) return;
|
||||
const parent = row.parentNode;
|
||||
let firstDataRow = parent.querySelector("tr:not(.cbi-section-table-titles)");
|
||||
if (firstDataRow && firstDataRow !== row) {
|
||||
parent.insertBefore(row, firstDataRow);
|
||||
let save_order_btn = document.getElementById("save_order_btn_" + group);
|
||||
if (save_order_btn) {
|
||||
const new_order = get_shunt_rule_order(group);
|
||||
if (!arraysEqual(new_order, origin_group_shunt_rule_order[group])) {
|
||||
save_order_btn.style.display = null;
|
||||
} else {
|
||||
save_order_btn.style.display = "none";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function get_shunt_rule_order(group) {
|
||||
let table = document.getElementById("cbi-<%=appname%>-shunt_rules-" + group + "-table");
|
||||
if (!table) {
|
||||
return;
|
||||
}
|
||||
let rows = table.querySelectorAll("tr.cbi-section-table-row");
|
||||
if (!rows || rows.length === 0) {
|
||||
return;
|
||||
}
|
||||
var ids = [];
|
||||
rows.forEach(function(row) {
|
||||
var id = row.id.replace("cbi-<%=appname%>-", "");
|
||||
ids.push(id);
|
||||
});
|
||||
return ids;
|
||||
}
|
||||
|
||||
function save_current_page_order(group) {
|
||||
var table = document.getElementById("cbi-<%=appname%>-shunt_rules-" + group + "-table");
|
||||
if (!table) {
|
||||
alert("<%:No table!%>");
|
||||
return;
|
||||
}
|
||||
var rows = table.querySelectorAll("tr.cbi-section-table-row");
|
||||
if (!rows || rows.length === 0) {
|
||||
alert("<%:No shunt_rules!%>");
|
||||
return;
|
||||
}
|
||||
var btn = document.getElementById("save_order_btn_" + group);
|
||||
if (btn) {
|
||||
btn.style.display = "none";
|
||||
btn.disabled = true;
|
||||
}
|
||||
var ids = [];
|
||||
rows.forEach(function(row) {
|
||||
var id = row.id.replace("cbi-<%=appname%>-", "");
|
||||
ids.push(id);
|
||||
});
|
||||
XHR.get('<%=api.url("save_shunt_rule_order")%>', {
|
||||
group: group,
|
||||
ids: ids.join(",")
|
||||
},
|
||||
function(x, result) {
|
||||
if (btn) {
|
||||
btn.style.display = null;
|
||||
btn.disabled = false;
|
||||
}
|
||||
if (x && x.status === 200) {
|
||||
origin_group_shunt_rule_order[group] = get_shunt_rule_order(group);
|
||||
alert("<%:Saved current page order successfully.%>");
|
||||
if (btn) {
|
||||
btn.style.display = "none";
|
||||
}
|
||||
} else {
|
||||
alert("<%:Save failed!%>");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function arraysEqual(a, b) {
|
||||
if (a === b) return true;
|
||||
if (a == null || b == null) return false;
|
||||
if (a.length !== b.length) return false;
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (a[i] !== b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// List drag and rearrange
|
||||
function initSortableForTable(table) {
|
||||
if (!table) return null;
|
||||
let group = table.id.replace("cbi-<%=appname%>-shunt_rules-", "").replace("-table", "")
|
||||
var root = table.querySelector('tbody') || table;
|
||||
if (root._sortable_initialized) return root._sortable_instance;
|
||||
root._sortable_initialized = true;
|
||||
var opts = {
|
||||
handle: ".drag-handle",
|
||||
draggable: "tr.cbi-section-table-row",
|
||||
animation: 150,
|
||||
ghostClass: "dragging-row",
|
||||
fallbackOnBody: true,
|
||||
forceFallback: false,
|
||||
swapThreshold: 0.65,
|
||||
onEnd: function (evt) {
|
||||
//save_current_page_order(group); // Auto save
|
||||
let save_order_btn = document.getElementById("save_order_btn_" + group);
|
||||
if (save_order_btn) {
|
||||
const new_order = get_shunt_rule_order(group);
|
||||
if (!arraysEqual(new_order, origin_group_shunt_rule_order[group])) {
|
||||
save_order_btn.style.display = null;
|
||||
} else {
|
||||
save_order_btn.style.display = "none";
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
try {
|
||||
var instance = Sortable.create(root, opts);
|
||||
root._sortable_instance = instance;
|
||||
return instance;
|
||||
} catch (err) {
|
||||
root._sortable_initialized = false;
|
||||
console.error("Sortable init failed:", err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function initAllSortable(group_shunt_rules) {
|
||||
if (typeof Sortable === 'undefined') {
|
||||
var retries = 0;
|
||||
var maxRetries = 25;
|
||||
var t = setInterval(function () {
|
||||
retries++;
|
||||
if (typeof Sortable !== 'undefined') {
|
||||
clearInterval(t);
|
||||
for (var group in group_shunt_rules) {
|
||||
var table = document.getElementById("cbi-<%=appname%>-shunt_rules-" + group + "-table");
|
||||
initSortableForTable(table);
|
||||
}
|
||||
} else if (retries >= maxRetries) {
|
||||
clearInterval(t);
|
||||
}
|
||||
}, 200);
|
||||
} else {
|
||||
for (var group in group_shunt_rules) {
|
||||
var table = document.getElementById("cbi-<%=appname%>-shunt_rules-" + group + "-table");
|
||||
initSortableForTable(table);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function escape_html(s) {
|
||||
return s.replace(/[&<>"']/g, c => ({
|
||||
"&":"&", "<":"<", ">":">", '"':""", "'":"'"
|
||||
}[c]));
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/template" id="shunt_rules-table-template">
|
||||
<fieldset class="cbi-section cbi-tblsection" id="cbi-<%=appname%>-shunt_rules-{{group}}-fieldset">
|
||||
<table class="table cbi-section-table" id="cbi-<%=appname%>-shunt_rules-{{group}}-table" style="">
|
||||
<tr class="tr cbi-section-table-titles anonymous">
|
||||
<th class="th cbi-section-table-cell" style="width:30%">ID</th>
|
||||
<th class="th cbi-section-table-cell" style="width:30%"><%:Remarks%></th>
|
||||
<th class="th cbi-section-table-cell cbi-section-actions"></th>
|
||||
</tr>
|
||||
{{shunt_rule-tr}}
|
||||
</table>
|
||||
<div class="cbi-section-create cbi-tblsection-create">
|
||||
<input type="text" id="add_name_{{group}}">
|
||||
<input class="cbi-button cbi-button-add" type="button" value="<%:Add%>" onclick="toPage('add')">
|
||||
<input class="cbi-button cbi-button-apply" style="display: none" type="button" id="save_order_btn_{{group}}" value="<%:Save Order%>" onclick="save_current_page_order('{{group}}')">
|
||||
</div>
|
||||
</fieldset>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="shunt_rule-tr-template">
|
||||
<tr class="tr cbi-section-table-row" id="cbi-<%=appname%>-{{id}}">
|
||||
<td class="td cbi-value-field"><b>{{id}}</b></td>
|
||||
<td class="td cbi-value-field">{{remarks}}</td>
|
||||
<td class="td cbi-section-table-cell nowrap cbi-section-actions td-actions">
|
||||
<div class="shunt_rule-wrapper">
|
||||
<input class="btn cbi-button cbi-button-edit" type="button" value="<%:To Top%>" onclick="row_top(this, '{{group}}')" title="<%:To Top%>"/>
|
||||
<input class="btn cbi-button cbi-button-edit" type="button" value="<%:Edit%>" onclick="toPage('edit', '{{id}}')" alt="<%:Edit%>" title="<%:Edit%>">
|
||||
<input class="btn cbi-button cbi-button-remove" type="button" value="<%:Delete%>" onclick="toPage('del', '{{id}}')" alt="<%:Delete%>" title="<%:Delete%>">
|
||||
<span class="drag-handle center" title="<%:Drag to reorder%>">⠿</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
<div class="cbi-section">
|
||||
<h3>Sing-Box/Xray <%:Shunt Rule%></h3>
|
||||
<div class="cbi-section-descr"><a style="color: red"><%:Please note attention to the priority, the higher the order, the higher the priority.%></a></div>
|
||||
<div id="shunt_rule_list"></div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
function loadNodeList() {
|
||||
XHR.get('<%=api.url("get_shunt_rules")%>', null, function(x, result) {
|
||||
var shunt_rule_list = result
|
||||
|
||||
var group_shunt_rules = {}
|
||||
for (let i = 0; i < shunt_rule_list.length; i++) {
|
||||
let _shunt_rule = shunt_rule_list[i]
|
||||
if (!_shunt_rule.group || _shunt_rule.group === "") {
|
||||
_shunt_rule.group = "default"
|
||||
}
|
||||
if (!group_shunt_rules[_shunt_rule.group]) {
|
||||
group_shunt_rules[_shunt_rule.group] = []
|
||||
}
|
||||
group_shunt_rules[_shunt_rule.group].push(_shunt_rule)
|
||||
}
|
||||
|
||||
var tab_ul_li_html = '';
|
||||
var tab_content_html = '';
|
||||
var shunt_rules_table_template = document.getElementById("shunt_rules-table-template");
|
||||
var shunt_rule_template = document.getElementById("shunt_rule-tr-template");
|
||||
var default_group = null
|
||||
for (let group in group_shunt_rules) {
|
||||
if (default_group == null)
|
||||
default_group = group
|
||||
|
||||
var table_html = "";
|
||||
if (true) {
|
||||
var new_shunt_rules_table_dom = shunt_rules_table_template.cloneNode(true);
|
||||
var _html = new_shunt_rules_table_dom.innerHTML;
|
||||
_html = _html.split("{{group}}").join(group);
|
||||
var shunt_rule_tr_html = "";
|
||||
for (var i = 0; i < group_shunt_rules[group].length; i++) {
|
||||
let o = group_shunt_rules[group][i]
|
||||
var newDom = shunt_rule_template.cloneNode(true);
|
||||
newDom.classList.add("cbi-rowstyle-" + (i % 2 + 1));
|
||||
var innerHTML = newDom.innerHTML;
|
||||
innerHTML = innerHTML.split("{{id}}").join(o[".name"]);
|
||||
innerHTML = innerHTML.split("{{group}}").join(o["group"] || "");
|
||||
innerHTML = innerHTML.split("{{remarks}}").join(o["remarks"] || "");
|
||||
|
||||
shunt_rule_tr_html += innerHTML
|
||||
}
|
||||
_html = _html.split("{{shunt_rule-tr}}").join(shunt_rule_tr_html);
|
||||
table_html = _html;
|
||||
}
|
||||
|
||||
var group_name = group
|
||||
if (group === "default") {
|
||||
group_name = "<%:default%>"
|
||||
}
|
||||
|
||||
tab_ul_li_html +=
|
||||
'<li group_name="' + group + '" id="tab.<%=appname%>.shunt_rules.' + group + '" class="cbi-tab">' +
|
||||
'<a onclick="this.blur(); return cbi_t_switch(\'<%=appname%>.shunt_rules\', \'' + group + '\')" href="<%=REQUEST_URI%>?tab.<%=appname%>.shunt_rules=' + group + '">' + escape_html(group_name) + " | " + "<font style='color: red'>" + group_shunt_rules[group].length + '</font></a>' +
|
||||
'</li>'
|
||||
tab_content_html +=
|
||||
'<div class="cbi-tabcontainer" id="container.<%=appname%>.shunt_rules.' + group + '" style="display: none;">' +
|
||||
'' + table_html +
|
||||
'</div>'
|
||||
}
|
||||
|
||||
function addTabDOM(li, content) {
|
||||
let tab_ul_html = '<ul class="cbi-tabmenu">';
|
||||
let tab_content_html = '<fieldset class="cbi-section-shunt_rule cbi-section-shunt_rule-tabbed" id="cbi-<%=appname%>-shunt_rules">';
|
||||
if (li) {
|
||||
tab_ul_html += li;
|
||||
}
|
||||
if (content) {
|
||||
tab_content_html += content;
|
||||
}
|
||||
tab_ul_html += '</ul>';
|
||||
tab_content_html += '</fieldset>';
|
||||
return tab_ul_html + tab_content_html;
|
||||
}
|
||||
|
||||
document.getElementById("shunt_rule_list").innerHTML = addTabDOM(tab_ul_li_html, tab_content_html);
|
||||
|
||||
for (let group in group_shunt_rules) {
|
||||
cbi_t_add("<%=appname%>.shunt_rules", group)
|
||||
}
|
||||
|
||||
if (default_group) {
|
||||
cbi_t_switch("<%=appname%>.shunt_rules", default_group)
|
||||
}
|
||||
|
||||
origin_group_shunt_rule_order = {};
|
||||
for (let group in group_shunt_rules) {
|
||||
origin_group_shunt_rule_order[group] = get_shunt_rule_order(group);
|
||||
}
|
||||
|
||||
initAllSortable(group_shunt_rules);
|
||||
});
|
||||
}
|
||||
|
||||
loadNodeList();
|
||||
|
||||
//]]>
|
||||
</script>
|
||||
@@ -1094,6 +1094,9 @@ msgstr "启用后,规则列表可以支持 GeoIP/Geosite 规则。"
|
||||
msgid "Shunt Rule"
|
||||
msgstr "分流规则"
|
||||
|
||||
msgid "Shunt Rule Group"
|
||||
msgstr "分流规则组"
|
||||
|
||||
msgid "Please note attention to the priority, the higher the order, the higher the priority."
|
||||
msgstr "请注意优先级问题,排序越上面优先级越高。"
|
||||
|
||||
|
||||
@@ -391,7 +391,7 @@ if IS_SHUNT_NODE then
|
||||
local default_node_id = t["default_node"] or "_direct"
|
||||
uci:foreach(appname, "shunt_rules", function(s)
|
||||
local _node_id = t[s[".name"]]
|
||||
if _node_id and _node_id ~= "_blackhole" then
|
||||
if _node_id and _node_id ~= "_blackhole" and t["shunt_group"] == s.group then
|
||||
if _node_id == "_default" then
|
||||
_node_id = default_node_id
|
||||
end
|
||||
|
||||
@@ -619,7 +619,7 @@ function add_rule(var)
|
||||
local default_node_id = t["default_node"] or "_direct"
|
||||
uci:foreach(appname, "shunt_rules", function(s)
|
||||
local _node_id = t[s[".name"]]
|
||||
if _node_id and _node_id ~= "_blackhole" then
|
||||
if _node_id and _node_id ~= "_blackhole" and t["shunt_group"] == s.group then
|
||||
if _node_id == "_default" then
|
||||
_node_id = default_node_id
|
||||
end
|
||||
|
||||
@@ -559,7 +559,7 @@ if IS_SHUNT_NODE then
|
||||
local default_node_id = t["default_node"] or "_direct"
|
||||
uci:foreach(appname, "shunt_rules", function(s)
|
||||
local _node_id = t[s[".name"]]
|
||||
if _node_id and _node_id ~= "_blackhole" then
|
||||
if _node_id and _node_id ~= "_blackhole" and t["shunt_group"] == s.group then
|
||||
if _node_id == "_default" then
|
||||
_node_id = default_node_id
|
||||
end
|
||||
|
||||
@@ -952,7 +952,14 @@ add_firewall_rule() {
|
||||
[ "$USE_SHUNT_NODE" = "1" ] && {
|
||||
local GEOIP_CODE=""
|
||||
local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
|
||||
local shunt_group
|
||||
if [ "${USE_SHUNT_TCP}" = "1" ]; then
|
||||
shunt_group=$(config_n_get $_TCP_NODE shunt_group)
|
||||
elif [ "${USE_SHUNT_UDP}" = "1" ]; then
|
||||
shunt_group=$(config_n_get $_UDP_NODE shunt_group)
|
||||
fi
|
||||
for shunt_id in $shunt_ids; do
|
||||
[ "${shunt_group}" != "$(config_n_get ${shunt_id} group)" ] && continue
|
||||
config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | grep -v "^#" | sed -e "/^$/d" | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $IPSET_SHUNT &/g" -e "s/$/ timeout 0/g" | ipset -! -R
|
||||
config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | grep -v "^#" | sed -e "/^$/d" | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $IPSET_SHUNT6 &/g" -e "s/$/ timeout 0/g" | ipset -! -R
|
||||
[ "$USE_GEOVIEW" = "1" ] && {
|
||||
|
||||
@@ -1054,7 +1054,14 @@ add_firewall_rule() {
|
||||
[ "$USE_SHUNT_NODE" = "1" ] && {
|
||||
local GEOIP_CODE=""
|
||||
local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
|
||||
local shunt_group
|
||||
if [ "${USE_SHUNT_TCP}" = "1" ]; then
|
||||
shunt_group=$(config_n_get $_TCP_NODE shunt_group)
|
||||
elif [ "${USE_SHUNT_UDP}" = "1" ]; then
|
||||
shunt_group=$(config_n_get $_UDP_NODE shunt_group)
|
||||
fi
|
||||
for shunt_id in $shunt_ids; do
|
||||
[ "${shunt_group}" != "$(config_n_get ${shunt_id} group)" ] && continue
|
||||
config_n_get $shunt_id ip_list | sed 's/#.*//' | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | insert_nftset $NFTSET_SHUNT_STATIC
|
||||
config_n_get $shunt_id ip_list | sed 's/#.*//' | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | insert_nftset $NFTSET_SHUNT6_STATIC
|
||||
[ "$USE_GEOVIEW" = "1" ] && {
|
||||
|
||||
Reference in New Issue
Block a user