Files
op-packages/luci-app-openclash/luasrc/model/cbi/openclash/config-subscribe-edit.lua
T

350 lines
11 KiB
Lua

local m, s, o
local openclash = "openclash"
local uci = luci.model.uci.cursor()
local fs = require "luci.openclash"
local sys = require "luci.sys"
local json = require "luci.jsonc"
local HTTP = require "luci.http"
local DISP = require "luci.dispatcher"
local sid = arg[1]
local age_section
local backend_version_status = [[
<div class="oc">
<div id="subconverter-version-status-cbi" class="subconverter-version-status" data-state="idle" hidden>
<span class="subconverter-version-label"></span>
<span class="subconverter-version-text"></span>
</div>
</div>
]]
font_red = [[<b style=color:red>]]
font_off = [[</b>]]
bold_on = [[<strong>]]
bold_off = [[</strong>]]
m = Map(openclash, translate("Config Subscribe Edit"))
m.pageaction = false
m.description=translate("Convert Subscribe function of Online is Supported By subconverter Written By tindy X") ..
"<br/>"..
"<br/>"..translate("Subconverter external configuration (subscription conversion template) Description: https://github.com/tindy2013/subconverter#external-configuration-file")..
"<br/>"..
"<br/>"..translate("If you need to customize the external configuration file (subscription conversion template), please write it according to the instructions, upload it to the accessible location of the external network, and fill in the address correctly when using it")..
"<br/>"..
"<br/>"..translate("If you have a recommended external configuration file (subscription conversion template), you can modify by following The file format of /usr/share/openclash/res/sub_ini.list and pr")
m.redirect = DISP.build_url("admin/services/openclash/config-subscribe")
if m.uci:get(openclash, sid) ~= "config_subscribe" then
HTTP.redirect(m.redirect)
return
end
-- [[ Config Subscribe Setting ]]--
s = m:section(NamedSection, sid, "config_subscribe")
s.anonymous = true
s.addremove = false
---- name
o = s:option(Value, "name", translate("Config Alias"))
o.description = font_red..bold_on..translate("Name For Distinguishing")..bold_off..font_off
o.placeholder = translate("config")
o.rmempty = true
---- address
o = s:option(Value, "address", translate("Subscribe Address"))
o.template = "cbi/tvalue"
o.rows = 10
o.wrap = "off"
o.description = font_red..bold_on..translate("SS/SSR/Vmess or Other Link And Subscription Address is Supported When Online Subscription Conversion is Enabled, Multiple Links Should be One Per Line or Separated By |")..bold_off..font_off
o.placeholder = translate("Not Null")
o.rmempty = false
function o.validate(self, value)
if value then
value = value:gsub("\r\n?", "\n")
value = value:gsub("%c*$", "")
end
return value
end
---- UA
o = s:option(Value, "sub_ua", "User-Agent")
o.default = "clash-verge/v2.4.5"
o.description = font_red..bold_on..translate("Used for Downloading Subscriptions, Defaults to").." "..o.default..bold_off..font_off
o:value("clash-verge/v2.4.5")
o:value("clash.meta/1.19.20")
o:value("Clash")
o.rmempty = true
---- Custom Headers
o = s:option(DynamicList, "sub_headers", translate("Custom Headers"))
o.description = font_red..bold_on..translate("Custom HTTP request headers, one per line, format: Header-Name: value")..bold_off..font_off
o.rmempty = true
o.placeholder = "x-hwid: my-device-id"
o = s:option(ListValue, "config_age_algo", translate("Age Key Type"))
o.description = font_red..bold_on..translate("Age Encryption For Config, Click For More:")..bold_off..font_off.." ".."<a href='javascript:void(0)' onclick='javascript:return winOpen(\"https://wiki.metacubex.one/config/proxy-providers/?age-secret-key#age-secret-key\")'>"..translate("Age Encryption Introduce").."</a>"
o:value("keygen", "x25519")
o:value("pq", "PQ (mlkem768-x25519)")
o.rmempty = true
function o.cfgvalue(self, section)
local name = m.uci:get(openclash, section, "name") or section
local v = ""
m.uci:foreach(openclash, "config_age_secret", function(s)
if s.name == name then
v = s.algo or ""
age_section = s['.name']
return false
end
end)
return v
end
function o.write(self, section, value)
local name = m.uci:get(openclash, section, "name") or section
m.uci:foreach(openclash, "config_age_secret", function(s)
if s.name == name then
age_section = s['.name']
return false
end
end)
if not age_section and value and value ~= "" then
age_section = m.uci:add(openclash, "config_age_secret")
if age_section then m.uci:set(openclash, age_section, "name", name) end
end
if age_section then
if value and value ~= "" then
m.uci:set(openclash, age_section, "algo", value)
else
m.uci:delete(openclash, age_section, "algo")
end
end
end
function o.remove(self, section)
self:write(section, "")
end
o = s:option(Value, "config_age_secret", translate("Secret Key"))
o.rmempty = true
o.placeholder = "AGE-SECRET-KEY-..."
function o.cfgvalue(self, section)
local name = m.uci:get(openclash, section, "name") or section
local v = ""
m.uci:foreach(openclash, "config_age_secret", function(s)
if s.name == name then
v = s.secret or ""
age_section = s['.name']
return false
end
end)
return v
end
function o.write(self, section, value)
local name = m.uci:get(openclash, section, "name") or section
m.uci:foreach(openclash, "config_age_secret", function(s)
if s.name == name then
age_section = s['.name']
return false
end
end)
if not age_section and value and value ~= "" then
age_section = m.uci:add(openclash, "config_age_secret")
if age_section then m.uci:set(openclash, age_section, "name", name) end
end
if age_section then
if value and value ~= "" then
m.uci:set(openclash, age_section, "secret", value)
else
m.uci:delete(openclash, age_section, "secret")
end
end
end
function o.remove(self, section)
self:write(section, "")
end
o = s:option(Value, "config_age_public", translate("Public Key"))
o.rmempty = true
o.placeholder = "age..."
function o.cfgvalue(self, section)
local name = m.uci:get(openclash, section, "name") or section
local v = ""
m.uci:foreach(openclash, "config_age_secret", function(s)
if s.name == name then
v = s.public or ""
age_section = s['.name']
return false
end
end)
return v
end
function o.write(self, section, value)
local name = m.uci:get(openclash, section, "name") or section
m.uci:foreach(openclash, "config_age_secret", function(s)
if s.name == name then
age_section = s['.name']
return false
end
end)
if not age_section and value and value ~= "" then
age_section = m.uci:add(openclash, "config_age_secret")
if age_section then m.uci:set(openclash, age_section, "name", name) end
end
if age_section then
if value and value ~= "" then
m.uci:set(openclash, age_section, "public", value)
else
m.uci:delete(openclash, age_section, "public")
end
end
end
function o.remove(self, section)
self:write(section, "")
end
o = s:option(DummyValue, "_generate_age_btn", "")
o.template = "openclash/generate_age"
---- subconverter
o = s:option(Flag, "sub_convert", translate("Subscribe Convert Online"))
o.description = translate("Convert Subscribe Online With Template")
o.default = 0
---- Convert Address
o = s:option(Value, "convert_address", translate("Convert Address"))
o.rmempty = true
o.description = backend_version_status..font_red..bold_on..translate("Note: There is A Risk of Privacy Leakage in Online Convert")..bold_off..font_off
o:depends("sub_convert", "1")
o:value("https://api.asailor.org/sub", translate("api.asailor.org"))
o:value("https://api.wcc.best/sub", translate("api.wcc.best"))
o.default = "https://api.asailor.org/sub"
o.placeholder = "https://api.asailor.org/sub"
---- Template
o = s:option(ListValue, "template", translate("Template Name"))
o.rmempty = true
o:depends("sub_convert", "1")
file = io.open("/usr/share/openclash/res/sub_ini.list", "r");
for l in file:lines() do
if l ~= "" and l ~= nil then
o:value(string.sub(luci.sys.exec(string.format("echo '%s' |awk -F ',' '{print $1}' 2>/dev/null",l)),1,-2))
end
end
file:close()
o:value("0", translate("Custom Template"))
---- Custom Template
o = s:option(Value, "custom_template_url", translate("Custom Template URL"))
o.rmempty = true
o.placeholder = translate("Not Null")
o.datatype = "or(host, string)"
o:depends("template", "0")
---- emoji
o = s:option(ListValue, "emoji", translate("Emoji"))
o.rmempty = false
o:value("false", translate("Disable"))
o:value("true", translate("Enable"))
o.default = "false"
o:depends("sub_convert", "1")
---- udp
o = s:option(ListValue, "udp", translate("UDP Enable"))
o.rmempty = false
o:value("false", translate("Disable"))
o:value("true", translate("Enable"))
o.default = "false"
o:depends("sub_convert", "1")
---- skip-cert-verify
o = s:option(ListValue, "skip_cert_verify", translate("skip-cert-verify"))
o.rmempty = false
o:value("false", translate("Disable"))
o:value("true", translate("Enable"))
o.default = "false"
o:depends("sub_convert", "1")
---- sort
o = s:option(ListValue, "sort", translate("Sort"))
o.rmempty = false
o:value("false", translate("Disable"))
o:value("true", translate("Enable"))
o.default = "false"
o:depends("sub_convert", "1")
---- node type
o = s:option(ListValue, "node_type", translate("Append Node Type"))
o.rmempty = false
o:value("false", translate("Disable"))
o:value("true", translate("Enable"))
o.default = "false"
o:depends("sub_convert", "1")
---- rule provider
o = s:option(ListValue, "rule_provider", translate("Use Rule Provider"))
o.description = font_red..bold_on..translate("Note: Please Make Sure Backend Service Supports This Feature")..bold_off..font_off
o.rmempty = false
o:value("false", translate("Disable"))
o:value("true", translate("Enable"))
o.default = "false"
o:depends("sub_convert", "1")
---- custom params
o = s:option(DynamicList, "custom_params", translate("Custom Params"))
o.description = font_red..bold_on..translate("eg: \"rename=match@replace\" , \"rename=\\s+([2-9])[xX]@ (HIGH:$1)\"")..bold_off..font_off
o.rmempty = false
o:depends("sub_convert", "1")
---- key
o = s:option(DynamicList, "keyword", font_red..bold_on..translate("Keyword Match")..bold_off..font_off)
o.description = font_red..bold_on..translate("eg: hk or tw&bgp")..bold_off..font_off
o.rmempty = true
---- exkey
o = s:option(DynamicList, "ex_keyword", font_red..bold_on..translate("Exclude Keyword Match")..bold_off..font_off)
o.description = font_red..bold_on..translate("eg: hk or tw&bgp")..bold_off..font_off
o.rmempty = true
---- de_exkey
o = s:option(MultiValue, "de_ex_keyword", font_red..bold_on..translate("Exclude Keyword Match Default")..bold_off..font_off)
o.rmempty = true
o:value(translate("Expire"))
o:value(translate("Traffic"))
o:value(translate("Plan"))
o:value(translate("Official"))
local t = {
{Commit, Back}
}
a = m:section(Table, t)
o = a:option(Button,"Commit", " ")
o.inputtitle = translate("Commit Settings")
o.inputstyle = "apply"
o.write = function()
local to_delete = {}
m.uci:foreach(openclash, "config_age_secret", function(s)
local pub = m.uci:get(openclash, s['.name'], "public") or ""
local sec = m.uci:get(openclash, s['.name'], "secret") or ""
if (pub == "" or pub == nil) and (sec == "" or sec == nil) then
table.insert(to_delete, s['.name'])
end
end)
for _, n in ipairs(to_delete) do
m.uci:delete(openclash, n)
end
m.uci:commit(openclash)
HTTP.redirect(m.redirect)
end
o = a:option(Button,"Back", " ")
o.inputtitle = translate("Back Settings")
o.inputstyle = "reset"
o.write = function()
m.uci:revert(openclash, sid)
m.uci:revert(openclash, age_section)
HTTP.redirect(m.redirect)
end
m:append(Template("openclash/toolbar_show"))
m:append(Template("openclash/subconverter_version"))
return m