luci-app-vssr: bump to v1.22
Signed-off-by: CN_SZTL <cnsztl@project-openwrt.eu.org>
This commit is contained in:
parent
77f6cfb52d
commit
296e65d890
@ -1,8 +1,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-vssr
|
||||
PKG_VERSION:=1.21
|
||||
PKG_RELEASE:=20210114
|
||||
PKG_VERSION:=1.22
|
||||
PKG_RELEASE:=20210119
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
@ -46,7 +46,7 @@ define Package/luci-app-vssr
|
||||
SUBMENU:=3. Applications
|
||||
TITLE:=A New SS/SSR/V2Ray/Trojan LuCI interface
|
||||
PKGARCH:=all
|
||||
DEPENDS:=+shadowsocksr-libev-alt +ipset +ip-full +iptables-mod-tproxy +dnsmasq-full +coreutils +coreutils-base64 +bash +pdnsd-alt +wget-ssl +luasocket +lua-maxminddb \
|
||||
DEPENDS:=+shadowsocksr-libev-alt +ipset +ip-full +iptables-mod-tproxy +dnsmasq-full +coreutils +coreutils-base64 +bash +pdnsd-alt +wget-ssl +lua +luasocket +lua-maxminddb \
|
||||
+shadowsocks-libev-ss-local +shadowsocksr-libev-ssr-local +shadowsocks-libev-ss-redir +simple-obfs \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_plugin:v2ray-plugin \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray:v2ray \
|
||||
|
||||
@ -12,12 +12,13 @@ function index()
|
||||
entry({'admin', 'services', 'vssr', 'client'}, cbi('vssr/client'), _('SSR Client'), 10).leaf = true -- 基本设置
|
||||
entry({'admin', 'services', 'vssr', 'servers'}, cbi('vssr/servers'), _('Severs Nodes'), 11).leaf = true -- 服务器节点
|
||||
entry({'admin', 'services', 'vssr', 'servers'}, arcombine(cbi('vssr/servers'), cbi('vssr/client-config')), _('Severs Nodes'), 11).leaf = true -- 编辑节点
|
||||
entry({'admin', 'services', 'vssr', 'control'}, cbi('vssr/control'), _('Access Control'), 12).leaf = true -- 访问控制
|
||||
entry({'admin', 'services', 'vssr', 'router'}, cbi('vssr/router'), _('Router Config'), 13).leaf = true -- 访问控制
|
||||
entry({'admin', 'services', 'vssr', 'subscribe_config'}, cbi('vssr/subscribe-config', {hideapplybtn = true, hidesavebtn = true, hideresetbtn = true}), _('Subscribe'), 12).leaf = true -- 订阅设置
|
||||
entry({'admin', 'services', 'vssr', 'control'}, cbi('vssr/control'), _('Access Control'), 13).leaf = true -- 访问控制
|
||||
entry({'admin', 'services', 'vssr', 'router'}, cbi('vssr/router'), _('Router Config'), 14).leaf = true -- 访问控制
|
||||
if nixio.fs.access('/usr/bin/v2ray/v2ray') or nixio.fs.access('/usr/bin/v2ray') or nixio.fs.access('/usr/bin/xray') or nixio.fs.access('/usr/bin/xray/xray') then
|
||||
entry({'admin', 'services', 'vssr', 'socks5'}, cbi('vssr/socks5'), _('Socks5'), 14).leaf = true -- Socks5代理
|
||||
entry({'admin', 'services', 'vssr', 'socks5'}, cbi('vssr/socks5'), _('Local Proxy'), 15).leaf = true -- Socks5代理
|
||||
end
|
||||
entry({'admin', 'services', 'vssr', 'advanced'}, cbi('vssr/advanced'), _('Advanced Settings'), 15).leaf = true -- 高级设置
|
||||
entry({'admin', 'services', 'vssr', 'advanced'}, cbi('vssr/advanced'), _('Advanced Settings'), 16).leaf = true -- 高级设置
|
||||
elseif nixio.fs.access('/usr/bin/ssr-server') then
|
||||
entry({'admin', 'services', 'vssr'}, alias('admin', 'services', 'vssr', 'server'), _('vssr'), 10).dependent = true
|
||||
else
|
||||
@ -240,11 +241,7 @@ function refresh_data()
|
||||
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'
|
||||
else
|
||||
refresh_cmd = 'wget -O /tmp/gfw.b64 http://iytc.net/tools/list.b64'
|
||||
end
|
||||
refresh_cmd = 'wget-ssl --no-check-certificate https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt -O /tmp/gfw.b64'
|
||||
sret = luci.sys.call(refresh_cmd .. ' 2>/dev/null')
|
||||
if sret == 0 then
|
||||
luci.sys.call('/usr/bin/vssr-gfw')
|
||||
@ -265,7 +262,7 @@ function refresh_data()
|
||||
retstring = '-1'
|
||||
end
|
||||
elseif set == 'ip_data' then
|
||||
refresh_cmd ="wget -O- 'https://ispip.clang.cn/all_cn.txt' > /tmp/china_ssr.txt 2>/dev/null"
|
||||
refresh_cmd = "wget-ssl -O- 'https://ispip.clang.cn/all_cn.txt' > /tmp/china_ssr.txt 2>/dev/null"
|
||||
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
|
||||
@ -282,12 +279,8 @@ function refresh_data()
|
||||
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
|
||||
else
|
||||
refresh_cmd = 'wget -O /tmp/ad.conf http://iytc.net/tools/ad.conf'
|
||||
end
|
||||
refresh_cmd = 'wget-ssl --no-check-certificate -O - https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt > /tmp/adnew.conf'
|
||||
need_process = 1
|
||||
sret = luci.sys.call(refresh_cmd .. ' 2>/dev/null')
|
||||
if sret == 0 then
|
||||
if need_process == 1 then
|
||||
@ -319,4 +312,4 @@ function refresh_data()
|
||||
end
|
||||
luci.http.prepare_content('application/json')
|
||||
luci.http.write_json({ret = retstring, retcount = icount})
|
||||
end
|
||||
end
|
||||
|
||||
@ -61,59 +61,6 @@ o.datatype = 'uinteger'
|
||||
o:depends('enable_switch', '1')
|
||||
o.default = 3
|
||||
|
||||
-- [[ 节点订阅 ]]--
|
||||
|
||||
s = m:section(TypedSection, 'server_subscribe', translate('Servers subscription and manage'))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(Flag, 'auto_update', translate('Auto Update'))
|
||||
o.rmempty = false
|
||||
o.description = translate('Auto Update Server subscription, GFW list and CHN route')
|
||||
|
||||
o = s:option(ListValue, 'auto_update_time', translate('Update time (every day)'))
|
||||
for t = 0, 23 do
|
||||
o:value(t, t .. ':00')
|
||||
end
|
||||
o.default = 2
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(DynamicList, 'subscribe_url', translate('Subscribe URL'))
|
||||
o.rmempty = true
|
||||
o.description = translate('You can manually add group names in front of the URL, splited by ,')
|
||||
|
||||
o = s:option(Value, "filter_words", translate("Subscribe Filter Words"))
|
||||
o.rmempty = true
|
||||
o.description = translate("Filter Words splited by /")
|
||||
|
||||
o = s:option(Flag, 'proxy', translate('Through proxy update'))
|
||||
o.rmempty = false
|
||||
o.description = translate('Through proxy update list, Not Recommended ')
|
||||
|
||||
o = s:option(DummyValue, '', '')
|
||||
o.rawhtml = true
|
||||
o.template = 'vssr/update_subscribe'
|
||||
|
||||
o = s:option(Button, 'delete', translate('Delete All Subscribe Severs'))
|
||||
o.inputstyle = 'reset'
|
||||
o.description = string.format(translate('Server Count') .. ': %d', server_count)
|
||||
o.write = function()
|
||||
uci:delete_all(
|
||||
'vssr',
|
||||
'servers',
|
||||
function(s)
|
||||
if s.hashkey or s.isSubscribe then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
)
|
||||
uci:save('vssr')
|
||||
uci:commit('vssr')
|
||||
luci.sys.exec('/etc/init.d/vssr restart')
|
||||
luci.http.redirect(luci.dispatcher.build_url('admin', 'services', 'vssr', 'servers'))
|
||||
return
|
||||
end
|
||||
|
||||
-- [[ adblock ]]--
|
||||
s = m:section(TypedSection, 'global', translate('adblock settings'))
|
||||
|
||||
@ -93,15 +93,7 @@ for i, v in pairs(route_name) do
|
||||
o = s:option(ListValue, v, translate(route_label[i]))
|
||||
o:value('nil', translate('Same as Main Server'))
|
||||
for _, key in pairs(server_table) do
|
||||
if(v == 'tw_video_server' and key.flag == "tw") then
|
||||
o:value(key.name, key.gname)
|
||||
end
|
||||
if(v == 'tvb_server' and key.flag == "hk") then
|
||||
o:value(key.name, key.gname)
|
||||
end
|
||||
if(v ~= 'tvb_server' and v ~= 'tw_video_server') then
|
||||
o:value(key.name, key.gname)
|
||||
end
|
||||
o:value(key.name, key.gname)
|
||||
end
|
||||
o:depends('v2ray_flow', '1')
|
||||
o.default = 'nil'
|
||||
|
||||
@ -2,7 +2,8 @@ local fs = require 'nixio.fs'
|
||||
local conffile = '/tmp/ssrpro.log'
|
||||
|
||||
f = SimpleForm('logview')
|
||||
|
||||
f.submit = false
|
||||
f.reset = false
|
||||
t = f:field(TextValue, 'conf')
|
||||
t.rmempty = true
|
||||
t.rows = 20
|
||||
|
||||
@ -1,31 +1,31 @@
|
||||
local m, s, o
|
||||
local NXFS = require 'nixio.fs'
|
||||
local router_table = {
|
||||
yotube = {
|
||||
a1 = {
|
||||
name = 'youtube',
|
||||
des = 'Youtube Domain'
|
||||
},
|
||||
tw_video = {
|
||||
a2 = {
|
||||
name = 'tw_video',
|
||||
des = 'Tw Video Domain'
|
||||
},
|
||||
netflix = {
|
||||
a3 = {
|
||||
name = 'netflix',
|
||||
des = 'Netflix Domain'
|
||||
},
|
||||
disney = {
|
||||
a4 = {
|
||||
name = 'disney',
|
||||
des = 'Disney+ Domain'
|
||||
},
|
||||
prime = {
|
||||
a5 = {
|
||||
name = 'prime',
|
||||
des = 'Prime Video Domain'
|
||||
},
|
||||
tvb = {
|
||||
a6 = {
|
||||
name = 'tvb',
|
||||
des = 'TVB Domain'
|
||||
},
|
||||
custom = {
|
||||
a7 = {
|
||||
name = 'custom',
|
||||
des = 'Custom Domain'
|
||||
}
|
||||
@ -39,6 +39,7 @@ for _, v in pairs(router_table) do
|
||||
local conf = '/etc/vssr/'.. v.name ..'_domain.list'
|
||||
o = s:taboption(v.name, TextValue, v.name ..'conf')
|
||||
o.rows = 13
|
||||
o.description = translate('↑ Put your domain list here')
|
||||
o.wrap = 'off'
|
||||
o.rmempty = true
|
||||
o.cfgvalue = function(self, section)
|
||||
@ -50,6 +51,23 @@ for _, v in pairs(router_table) do
|
||||
o.remove = function(self, section, value)
|
||||
NXFS.writefile(conf, '')
|
||||
end
|
||||
|
||||
|
||||
local conf1 = '/etc/vssr/'.. v.name ..'_ip.list'
|
||||
o = s:taboption(v.name, TextValue, v.name ..'conf1')
|
||||
o.rows = 13
|
||||
o.wrap = 'off'
|
||||
o.description = translate('↑ Put your IP list here')
|
||||
o.rmempty = true
|
||||
o.cfgvalue = function(self, section)
|
||||
return NXFS.readfile(conf1) or ' '
|
||||
end
|
||||
o.write = function(self, section, value)
|
||||
NXFS.writefile(conf1, value:gsub('\r\n', '\n'))
|
||||
end
|
||||
o.remove = function(self, section, value)
|
||||
NXFS.writefile(conf1, '')
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
||||
|
||||
@ -0,0 +1,77 @@
|
||||
local vssr = 'vssr'
|
||||
local uci = luci.model.uci.cursor()
|
||||
local server_table = {}
|
||||
|
||||
local gfwmode = 0
|
||||
local gfw_count = 0
|
||||
local ip_count = 0
|
||||
local ad_count = 0
|
||||
local server_count = 0
|
||||
|
||||
local sys = require 'luci.sys'
|
||||
|
||||
uci:foreach(
|
||||
'vssr',
|
||||
'servers',
|
||||
function(s)
|
||||
server_count = server_count + 1
|
||||
end
|
||||
)
|
||||
|
||||
m = Map(vssr)
|
||||
|
||||
-- [[ 节点订阅 ]]--
|
||||
|
||||
s = m:section(TypedSection, 'server_subscribe', translate('Servers subscription and manage'))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(Flag, 'auto_update', translate('Auto Update'))
|
||||
o.rmempty = false
|
||||
o.description = translate('Auto Update Server subscription, GFW list and CHN route')
|
||||
|
||||
o = s:option(ListValue, 'auto_update_time', translate('Update time (every day)'))
|
||||
for t = 0, 23 do
|
||||
o:value(t, t .. ':00')
|
||||
end
|
||||
o.default = 2
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(DynamicList, 'subscribe_url', translate('Subscribe URL'))
|
||||
o.rmempty = true
|
||||
o.description = translate('You can manually add group names in front of the URL, splited by ,')
|
||||
|
||||
o = s:option(Value, 'filter_words', translate('Subscribe Filter Words'))
|
||||
o.rmempty = true
|
||||
o.description = translate('Filter Words splited by /')
|
||||
|
||||
o = s:option(Flag, 'proxy', translate('Through proxy update'))
|
||||
o.rmempty = false
|
||||
o.description = translate('Through proxy update list, Not Recommended ')
|
||||
|
||||
o = s:option(DummyValue, '', '')
|
||||
o.rawhtml = true
|
||||
o.template = 'vssr/update_subscribe'
|
||||
|
||||
o = s:option(Button, 'delete', translate('Delete All Subscribe Severs'))
|
||||
o.inputstyle = 'reset'
|
||||
o.description = string.format(translate('Server Count') .. ': %d', server_count)
|
||||
o.write = function()
|
||||
uci:delete_all(
|
||||
'vssr',
|
||||
'servers',
|
||||
function(s)
|
||||
if s.hashkey or s.isSubscribe then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
)
|
||||
uci:save('vssr')
|
||||
uci:commit('vssr')
|
||||
luci.sys.exec('/etc/init.d/vssr restart')
|
||||
luci.http.redirect(luci.dispatcher.build_url('admin', 'services', 'vssr', 'servers'))
|
||||
return
|
||||
end
|
||||
|
||||
return m
|
||||
@ -2,304 +2,305 @@
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
const GET_FLAG_URL = '<%=luci.dispatcher.build_url("admin", "services", "vssr","flag")%>';
|
||||
var sid;
|
||||
const GET_FLAG_URL = '<%=luci.dispatcher.build_url("admin", "services", "vssr","flag")%>';
|
||||
var sid;
|
||||
|
||||
function getFlag(remark, hosts, sid) {
|
||||
XHR.get(GET_FLAG_URL,
|
||||
{ host: hosts, remark: remark },
|
||||
function (x, rv) {
|
||||
el('.flag').value = rv.flag.replace(/[\r\n]/g, "");
|
||||
function getFlag(remark, hosts, sid) {
|
||||
XHR.get(GET_FLAG_URL,
|
||||
{ host: hosts, remark: remark },
|
||||
function (x, rv) {
|
||||
el('.flag').value = rv.flag.replace(/[\r\n]/g, "");
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
function padright(str, cnt, pad) {
|
||||
return str + Array(cnt + 1).join(pad);
|
||||
}
|
||||
function b64EncodeUnicode(str) {
|
||||
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
|
||||
return String.fromCharCode('0x' + p1);
|
||||
}));
|
||||
}
|
||||
function b64encutf8safe(str) {
|
||||
return b64EncodeUnicode(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, '');
|
||||
}
|
||||
function b64DecodeUnicode(str) {
|
||||
return decodeURIComponent(Array.prototype.map.call(atob(str), function (c) {
|
||||
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
|
||||
}).join(''));
|
||||
}
|
||||
function b64decutf8safe(str) {
|
||||
var l;
|
||||
str = str.replace(/-/g, "+").replace(/_/g, "/");
|
||||
l = str.length;
|
||||
l = (4 - l % 4) % 4;
|
||||
if (l)
|
||||
str = padright(str, l, "=");
|
||||
return b64DecodeUnicode(str);
|
||||
}
|
||||
function b64encsafe(str) {
|
||||
return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, '')
|
||||
}
|
||||
function b64decsafe(str) {
|
||||
var l;
|
||||
str = str.replace(/-/g, "+").replace(/_/g, "/");
|
||||
l = str.length;
|
||||
l = (4 - l % 4) % 4;
|
||||
if (l)
|
||||
str = padright(str, l, "=");
|
||||
try {
|
||||
return atob(str);
|
||||
} catch (err) {
|
||||
return str;
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
function padright(str, cnt, pad) {
|
||||
return str + Array(cnt + 1).join(pad);
|
||||
}
|
||||
function b64EncodeUnicode(str) {
|
||||
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
|
||||
return String.fromCharCode('0x' + p1);
|
||||
}));
|
||||
}
|
||||
function b64encutf8safe(str) {
|
||||
return b64EncodeUnicode(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, '');
|
||||
}
|
||||
function b64DecodeUnicode(str) {
|
||||
return decodeURIComponent(Array.prototype.map.call(atob(str), function (c) {
|
||||
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
|
||||
}).join(''));
|
||||
}
|
||||
function b64decutf8safe(str) {
|
||||
var l;
|
||||
str = str.replace(/-/g, "+").replace(/_/g, "/");
|
||||
l = str.length;
|
||||
l = (4 - l % 4) % 4;
|
||||
if (l)
|
||||
str = padright(str, l, "=");
|
||||
return b64DecodeUnicode(str);
|
||||
}
|
||||
function b64encsafe(str) {
|
||||
return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, '')
|
||||
}
|
||||
function b64decsafe(str) {
|
||||
var l;
|
||||
str = str.replace(/-/g, "+").replace(/_/g, "/");
|
||||
l = str.length;
|
||||
l = (4 - l % 4) % 4;
|
||||
if (l)
|
||||
str = padright(str, l, "=");
|
||||
try {
|
||||
return atob(str);
|
||||
} catch (err) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
function dictvalue(d, key) {
|
||||
var v = d[key];
|
||||
if (typeof (v) == 'undefined' || v == '')
|
||||
return '';
|
||||
return b64decsafe(v);
|
||||
}
|
||||
|
||||
function el(id) {
|
||||
return document.getElementById('cbid.vssr.' + sid + id);
|
||||
}
|
||||
|
||||
function import_ssr_url(btn, urlname, sids) {
|
||||
sid = sids;
|
||||
var s = document.getElementById(urlname + '-status');
|
||||
if (!s)
|
||||
return false;
|
||||
var ssrurl = prompt("<%:Paste Node Link Here%> ssr:// | ss:// | vmess:// | trojan://", "");
|
||||
if (ssrurl == null || ssrurl == "") {
|
||||
s.innerHTML = "<font color='red'><%:User Cancel%></font>";
|
||||
return false;
|
||||
}
|
||||
s.innerHTML = "";
|
||||
//var ssu = ssrurl.match(/ssr:\/\/([A-Za-z0-9_-]+)/i);
|
||||
var ssu = ssrurl.split('://');
|
||||
console.log(ssu.length);
|
||||
if ((ssu[0] != "ssr" && ssu[0] != "ss" && ssu[0] != "vmess" && ssu[0] != "trojan") || ssu[1] == "") {
|
||||
s.innerHTML = "<font color='red'><%:Invalid Format%></font>";
|
||||
return false;
|
||||
function dictvalue(d, key) {
|
||||
var v = d[key];
|
||||
if (typeof (v) == 'undefined' || v == '')
|
||||
return '';
|
||||
return b64decsafe(v);
|
||||
}
|
||||
|
||||
function el(id) {
|
||||
return document.getElementById('cbid.vssr.' + sid + id);
|
||||
}
|
||||
|
||||
var event = document.createEvent("HTMLEvents");
|
||||
event.initEvent("change", true, true);
|
||||
var rema = "";
|
||||
if (ssu[0] == "ssr") {
|
||||
var sstr = b64decsafe(ssu[1]);
|
||||
var ploc = sstr.indexOf("/?");
|
||||
|
||||
el('.type').value = "ssr";
|
||||
el('.type').dispatchEvent(event);
|
||||
var url0, param = "";
|
||||
if (ploc > 0) {
|
||||
url0 = sstr.substr(0, ploc);
|
||||
param = sstr.substr(ploc + 2);
|
||||
}
|
||||
var ssm = url0.match(/^(.+):([^:]+):([^:]*):([^:]+):([^:]*):([^:]+)/);
|
||||
if (!ssm || ssm.length < 7)
|
||||
function import_ssr_url(btn, urlname, sids) {
|
||||
sid = sids;
|
||||
var s = document.getElementById(urlname + '-status');
|
||||
if (!s)
|
||||
return false;
|
||||
var ssrurl = prompt("<%:Paste Node Link Here%> ssr:// | ss:// | vmess:// | trojan://", "");
|
||||
if (ssrurl == null || ssrurl == "") {
|
||||
s.innerHTML = "<font color='red'><%:User Cancel%></font>";
|
||||
return false;
|
||||
var pdict = {};
|
||||
if (param.length > 2) {
|
||||
var a = param.split('&');
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
var b = a[i].split('=');
|
||||
pdict[decodeURIComponent(b[0])] = decodeURIComponent(b[1] || '');
|
||||
}
|
||||
}
|
||||
el('.server').value = ssm[1];
|
||||
el('.server_port').value = ssm[2];
|
||||
el('.protocol').value = ssm[3];
|
||||
el('.encrypt_method').value = ssm[4];
|
||||
el('.obfs').value = ssm[5];
|
||||
el('.password').value = b64decsafe(ssm[6]);
|
||||
el('.obfs_param').value = dictvalue(pdict, 'obfsparam');
|
||||
el('.protocol_param').value = dictvalue(pdict, 'protoparam');
|
||||
s.innerHTML = "";
|
||||
//var ssu = ssrurl.match(/ssr:\/\/([A-Za-z0-9_-]+)/i);
|
||||
var ssu = ssrurl.split('://');
|
||||
console.log(ssu.length);
|
||||
|
||||
var rem = pdict['remarks'];
|
||||
if (typeof (rem) != 'undefined' && rem != '' && rem.length > 0)
|
||||
rema = b64decutf8safe(rem);
|
||||
el('.alias').value = b64decutf8safe(rem);
|
||||
getFlag(rema, ssm[1], sid); //get flag iso code
|
||||
s.innerHTML = "<font color='green'><%:Import%>ShadowsocksR<%:Configuration Succeeded%></font>";
|
||||
return false;
|
||||
} else if (ssu[0] == "ss") {
|
||||
var url0, param = "";
|
||||
var sipIndex = ssu[1].indexOf("@");
|
||||
var ploc = ssu[1].indexOf("#");
|
||||
if (ploc > 0) {
|
||||
url0 = ssu[1].substr(0, ploc);
|
||||
param = ssu[1].substr(ploc + 1);
|
||||
} else {
|
||||
url0 = ssu[1];
|
||||
}
|
||||
var event = document.createEvent("HTMLEvents");
|
||||
event.initEvent("change", true, true);
|
||||
var rema = "";
|
||||
switch (ssu[0]) {
|
||||
case "ssr":
|
||||
var sstr = b64decsafe(ssu[1]);
|
||||
var ploc = sstr.indexOf("/?");
|
||||
el('.type').value = "ssr";
|
||||
el('.type').dispatchEvent(event);
|
||||
var url0, param = "";
|
||||
if (ploc > 0) {
|
||||
url0 = sstr.substr(0, ploc);
|
||||
param = sstr.substr(ploc + 2);
|
||||
}
|
||||
var ssm = url0.match(/^(.+):([^:]+):([^:]*):([^:]+):([^:]*):([^:]+)/);
|
||||
if (!ssm || ssm.length < 7)
|
||||
return false;
|
||||
var pdict = {};
|
||||
if (param.length > 2) {
|
||||
var a = param.split('&');
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
var b = a[i].split('=');
|
||||
pdict[decodeURIComponent(b[0])] = decodeURIComponent(b[1] || '');
|
||||
}
|
||||
}
|
||||
el('.server').value = ssm[1];
|
||||
el('.server_port').value = ssm[2];
|
||||
el('.protocol').value = ssm[3];
|
||||
el('.encrypt_method').value = ssm[4];
|
||||
el('.obfs').value = ssm[5];
|
||||
el('.password').value = b64decsafe(ssm[6]);
|
||||
el('.obfs_param').value = dictvalue(pdict, 'obfsparam');
|
||||
el('.protocol_param').value = dictvalue(pdict, 'protoparam');
|
||||
|
||||
if (sipIndex != -1) {
|
||||
// SIP002
|
||||
var userInfo = b64decsafe(url0.substr(0, sipIndex));
|
||||
var temp = url0.substr(sipIndex + 1).split("/?");
|
||||
var serverInfo = temp[0].split(":");
|
||||
var server = serverInfo[0];
|
||||
var port = serverInfo[1];
|
||||
var method, password, plugin, pluginOpts;
|
||||
if (temp[1]) {
|
||||
var pluginInfo = decodeURIComponent(temp[1]);
|
||||
var pluginIndex = pluginInfo.indexOf(";");
|
||||
var pluginNameInfo = pluginInfo.substr(0, pluginIndex);
|
||||
plugin = pluginNameInfo.substr(pluginNameInfo.indexOf("=") + 1)
|
||||
pluginOpts = pluginInfo.substr(pluginIndex + 1);
|
||||
}
|
||||
var rem = pdict['remarks'];
|
||||
if (typeof (rem) != 'undefined' && rem != '' && rem.length > 0)
|
||||
rema = b64decutf8safe(rem);
|
||||
el('.alias').value = b64decutf8safe(rem);
|
||||
getFlag(rema, ssm[1], sid); //get flag iso code
|
||||
s.innerHTML = "<font color='green'><%:Import%>ShadowsocksR<%:Configuration Succeeded%></font>";
|
||||
break;
|
||||
case "ss":
|
||||
var url0, param = "";
|
||||
var sipIndex = ssu[1].indexOf("@");
|
||||
var ploc = ssu[1].indexOf("#");
|
||||
if (ploc > 0) {
|
||||
url0 = ssu[1].substr(0, ploc);
|
||||
param = ssu[1].substr(ploc + 1);
|
||||
} else {
|
||||
url0 = ssu[1];
|
||||
}
|
||||
|
||||
var userInfoSplitIndex = userInfo.indexOf(":");
|
||||
if (userInfoSplitIndex != -1) {
|
||||
method = userInfo.substr(0, userInfoSplitIndex);
|
||||
password = userInfo.substr(userInfoSplitIndex + 1);
|
||||
}
|
||||
el('.type').value = "ss";
|
||||
el('.type').dispatchEvent(event);
|
||||
el('.server').value = server;
|
||||
el('.server_port').value = port;
|
||||
el('.password').value = password || "";
|
||||
el('.encrypt_method_ss').value = method || "";
|
||||
el('.plugin').value = plugin || "";
|
||||
el('.plugin_opts').value = pluginOpts || "";
|
||||
} else {
|
||||
var sstr = b64decsafe(url0);
|
||||
el('.type').value = "ss";
|
||||
el('.type').dispatchEvent(event);
|
||||
var team = sstr.split('@');
|
||||
console.log(param);
|
||||
var part1 = team[0].split(':');
|
||||
var part2 = team[1].split(':');
|
||||
el('.server').value = part2[0];
|
||||
el('.server_port').value = part2[1];
|
||||
el('.password').value = part1[1];
|
||||
el('.encrypt_method_ss').value = part1[0];
|
||||
el('.plugin').value = "";
|
||||
el('.plugin_opts').value = "";
|
||||
}
|
||||
if (sipIndex != -1) {
|
||||
// SIP002
|
||||
var userInfo = b64decsafe(url0.substr(0, sipIndex));
|
||||
var temp = url0.substr(sipIndex + 1).split("/?");
|
||||
if(temp.length == 1){
|
||||
temp = url0.substr(sipIndex + 1).split("?");
|
||||
}
|
||||
var serverInfo = temp[0].split(":");
|
||||
var server = serverInfo[0];
|
||||
var port = serverInfo[1];
|
||||
var method, password, plugin, pluginOpts;
|
||||
if (temp[1]) {
|
||||
var pluginInfo = decodeURIComponent(temp[1]);
|
||||
var pluginIndex = pluginInfo.indexOf(";");
|
||||
var pluginNameInfo = pluginInfo.substr(0, pluginIndex);
|
||||
plugin = pluginNameInfo.substr(pluginNameInfo.indexOf("=") + 1)
|
||||
pluginOpts = pluginInfo.substr(pluginIndex + 1);
|
||||
}
|
||||
|
||||
if (param != undefined) {
|
||||
rema = decodeURI(param)
|
||||
el('.alias').value = decodeURI(param);
|
||||
}
|
||||
getFlag(rema, server, sid); //get flag iso code
|
||||
s.innerHTML = "<font color='green'><%:Import%>Shadowsocks<%:Configuration Succeeded%></font>";
|
||||
return false;
|
||||
} else if (ssu[0] == "trojan") {
|
||||
var ploc = ssu[1].indexOf("#");
|
||||
if (ploc > 0) {
|
||||
url0 = ssu[1].substr(0, ploc);
|
||||
param = ssu[1].substr(ploc + 1);
|
||||
} else {
|
||||
url0 = ssu[1]
|
||||
}
|
||||
var sstr = b64decsafe(url0);
|
||||
el('.type').value = "trojan";
|
||||
el('.type').dispatchEvent(event);
|
||||
var team = sstr.split('@');
|
||||
console.log(team);
|
||||
var part1 = team[0].split(':');
|
||||
var part2 = team[1].split(':');
|
||||
var others = part2[1].split('?');
|
||||
var queryParam = {}
|
||||
if (others.length > 1) {
|
||||
var queryParams = others[1]
|
||||
var queryArray = queryParams.split('&')
|
||||
for (i = 0; i < queryArray.length; i++) {
|
||||
var params = queryArray[i].split('=');
|
||||
queryParam[decodeURIComponent(params[0])] = decodeURIComponent(params[1] || '');
|
||||
}
|
||||
}
|
||||
el('.server').value = part2[0];
|
||||
el('.server_port').value = others[0];
|
||||
el('.password').value = part1[0];
|
||||
if (queryParam.peer || queryParam.sni) {
|
||||
el('.tls').checked = true;
|
||||
el('.peer').value = queryParam.peer || queryParam.sni;
|
||||
}
|
||||
var userInfoSplitIndex = userInfo.indexOf(":");
|
||||
if (userInfoSplitIndex != -1) {
|
||||
method = userInfo.substr(0, userInfoSplitIndex);
|
||||
password = userInfo.substr(userInfoSplitIndex + 1);
|
||||
}
|
||||
el('.type').value = "ss";
|
||||
el('.type').dispatchEvent(event);
|
||||
el('.server').value = server;
|
||||
el('.server_port').value = port;
|
||||
el('.password').value = password || "";
|
||||
el('.encrypt_method_ss').value = method || "";
|
||||
el('.plugin').value = plugin || "";
|
||||
el('.plugin_opts').value = pluginOpts || "";
|
||||
} else {
|
||||
var sstr = b64decsafe(url0);
|
||||
el('.type').value = "ss";
|
||||
el('.type').dispatchEvent(event);
|
||||
var team = sstr.split('@');
|
||||
console.log(param);
|
||||
var part1 = team[0].split(':');
|
||||
var part2 = team[1].split(':');
|
||||
el('.server').value = part2[0];
|
||||
el('.server_port').value = part2[1];
|
||||
el('.password').value = part1[1];
|
||||
el('.encrypt_method_ss').value = part1[0];
|
||||
el('.plugin').value = "";
|
||||
el('.plugin_opts').value = "";
|
||||
}
|
||||
|
||||
if (param != undefined) {
|
||||
rema = decodeURI(param)
|
||||
el('.alias').value = decodeURI(param);
|
||||
}
|
||||
getFlag(rema, part2[0], sid); //get flag iso code
|
||||
if (param != undefined) {
|
||||
rema = decodeURI(param)
|
||||
el('.alias').value = decodeURI(param);
|
||||
}
|
||||
getFlag(rema, server, sid); //get flag iso code
|
||||
s.innerHTML = "<font color='green'><%:Import%>Shadowsocks<%:Configuration Succeeded%></font>";
|
||||
break;
|
||||
case "trojan":
|
||||
var ploc = ssu[1].indexOf("#");
|
||||
if (ploc > 0) {
|
||||
url0 = ssu[1].substr(0, ploc);
|
||||
param = ssu[1].substr(ploc + 1);
|
||||
} else {
|
||||
url0 = ssu[1]
|
||||
}
|
||||
var sstr = b64decsafe(url0);
|
||||
el('.type').value = "trojan";
|
||||
el('.type').dispatchEvent(event);
|
||||
var team = sstr.split('@');
|
||||
console.log(team);
|
||||
var part1 = team[0].split(':');
|
||||
var part2 = team[1].split(':');
|
||||
var others = part2[1].split('?');
|
||||
var queryParam = {}
|
||||
if (others.length > 1) {
|
||||
var queryParams = others[1]
|
||||
var queryArray = queryParams.split('&')
|
||||
for (i = 0; i < queryArray.length; i++) {
|
||||
var params = queryArray[i].split('=');
|
||||
queryParam[decodeURIComponent(params[0])] = decodeURIComponent(params[1] || '');
|
||||
}
|
||||
}
|
||||
el('.server').value = part2[0];
|
||||
el('.server_port').value = others[0];
|
||||
el('.password').value = part1[0];
|
||||
if (queryParam.peer || queryParam.sni) {
|
||||
el('.tls').checked = true;
|
||||
el('.peer').value = queryParam.peer || queryParam.sni;
|
||||
}
|
||||
|
||||
s.innerHTML = "<font color='green'>导入Trojan<%:Configuration Succeeded%></font>";
|
||||
return false;
|
||||
} else if (ssu[0] == "vmess") {
|
||||
var sstr = b64DecodeUnicode(ssu[1]);
|
||||
var ploc = sstr.indexOf("/?");
|
||||
el('.type').value = "v2ray";
|
||||
el('.type').dispatchEvent(event);
|
||||
var url0, param = "";
|
||||
if (ploc > 0) {
|
||||
url0 = sstr.substr(0, ploc);
|
||||
param = sstr.substr(ploc + 2);
|
||||
}
|
||||
var ssm = JSON.parse(sstr);
|
||||
el('.alias').value = ssm.ps;
|
||||
el('.server').value = ssm.add;
|
||||
el('.server_port').value = ssm.port;
|
||||
el('.alter_id').value = ssm.aid;
|
||||
el('.vmess_id').value = ssm.id;
|
||||
el('.transport').value = ssm.net;
|
||||
el('.transport').dispatchEvent(event);
|
||||
if (ssm.net == "tcp") {
|
||||
try {
|
||||
el('.http_host').value = ssm.host;
|
||||
el('.http_path').value = ssm.path;
|
||||
} catch (err) { }
|
||||
if (param != undefined) {
|
||||
rema = decodeURI(param)
|
||||
el('.alias').value = decodeURI(param);
|
||||
}
|
||||
getFlag(rema, part2[0], sid); //get flag iso code
|
||||
|
||||
s.innerHTML = "<font color='green'>导入Trojan<%:Configuration Succeeded%></font>";
|
||||
break;
|
||||
case "vmess":
|
||||
var sstr = b64DecodeUnicode(ssu[1]);
|
||||
var ploc = sstr.indexOf("/?");
|
||||
el('.type').value = "v2ray";
|
||||
el('.type').dispatchEvent(event);
|
||||
var url0, param = "";
|
||||
if (ploc > 0) {
|
||||
url0 = sstr.substr(0, ploc);
|
||||
param = sstr.substr(ploc + 2);
|
||||
}
|
||||
var ssm = JSON.parse(sstr);
|
||||
el('.alias').value = ssm.ps;
|
||||
el('.server').value = ssm.add;
|
||||
el('.server_port').value = ssm.port;
|
||||
el('.alter_id').value = ssm.aid;
|
||||
el('.vmess_id').value = ssm.id;
|
||||
el('.transport').value = ssm.net;
|
||||
el('.transport').dispatchEvent(event);
|
||||
if (ssm.net == "tcp") {
|
||||
try {
|
||||
el('.http_host').value = ssm.host;
|
||||
el('.http_path').value = ssm.path;
|
||||
} catch (err) { }
|
||||
|
||||
}
|
||||
if (ssm.net == "ws") {
|
||||
try {
|
||||
el('.ws_host').value = ssm.host;
|
||||
el('.ws_path').value = ssm.path;
|
||||
} catch (err) { }
|
||||
}
|
||||
if (ssm.net == "h2") {
|
||||
try {
|
||||
el('.h2_host').value = ssm.host;
|
||||
el('.h2_path').value = ssm.path;
|
||||
} catch (err) { }
|
||||
}
|
||||
if (ssm.net == "quic") {
|
||||
try {
|
||||
el('.quic_security').value = ssm.securty;
|
||||
el('.quic_key').value = ssm.key;
|
||||
} catch (err) { }
|
||||
}
|
||||
if (ssm.net == "kcp") {
|
||||
try {
|
||||
el('.kcp_guise').value = ssm.type;
|
||||
} catch (err) { }
|
||||
try {
|
||||
el('.seed').value = ssm.seed;
|
||||
} catch (err) { }
|
||||
}
|
||||
if (ssm.tls == "tls") {
|
||||
try {
|
||||
el('.tls').checked = true;
|
||||
el('.tls').dispatchEvent(event);
|
||||
el('.tls_host').value = ssm.host;
|
||||
} catch (err) { }
|
||||
}
|
||||
el('.mux').checked = true;
|
||||
el('.mux').dispatchEvent(event);
|
||||
|
||||
getFlag(ssm.ps, ssm.add, sid); //get flag iso code
|
||||
|
||||
s.innerHTML = "<font color='green'><%:Import%>V2ray<%:Configuration Succeeded%></font>";
|
||||
break;
|
||||
default:
|
||||
s.innerHTML = "<font color='red'><%:Invalid Format%></font>";
|
||||
|
||||
}
|
||||
if (ssm.net == "ws") {
|
||||
try {
|
||||
el('.ws_host').value = ssm.host;
|
||||
el('.ws_path').value = ssm.path;
|
||||
} catch (err) { }
|
||||
}
|
||||
if (ssm.net == "h2") {
|
||||
try {
|
||||
el('.h2_host').value = ssm.host;
|
||||
el('.h2_path').value = ssm.path;
|
||||
} catch (err) { }
|
||||
}
|
||||
if (ssm.net == "quic") {
|
||||
try {
|
||||
el('.quic_security').value = ssm.securty;
|
||||
el('.quic_key').value = ssm.key;
|
||||
} catch (err) { }
|
||||
}
|
||||
if (ssm.net == "kcp") {
|
||||
try {
|
||||
el('.kcp_guise').value = ssm.type;
|
||||
} catch (err) { }
|
||||
try {
|
||||
el('.seed').value = ssm.seed;
|
||||
} catch (err) { }
|
||||
}
|
||||
if (ssm.tls == "tls") {
|
||||
try {
|
||||
el('.tls').checked = true;
|
||||
el('.tls').dispatchEvent(event);
|
||||
el('.tls_host').value = ssm.host;
|
||||
} catch (err) { }
|
||||
}
|
||||
el('.mux').checked = true;
|
||||
el('.mux').dispatchEvent(event);
|
||||
|
||||
getFlag(ssm.ps, ssm.add, sid); //get flag iso code
|
||||
|
||||
s.innerHTML = "<font color='green'><%:Import%>V2ray<%:Configuration Succeeded%></font>";
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//]]></script>
|
||||
|
||||
<input type="button" class="cbi-button cbi-button-apply" value="<%:Import Configuration%>"
|
||||
|
||||
@ -26,6 +26,9 @@
|
||||
function resize() {
|
||||
wW = $(window).width();
|
||||
lw = $(".main-left").width()
|
||||
if(lw == undefined){
|
||||
lw = 0;
|
||||
}
|
||||
$(".status-bar").width(wW - lw);
|
||||
$(".status-bar .flag").width($(".status-bar .flag").height() / 3 * 4);
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<% math.randomseed(os.time()) %>
|
||||
<link rel="stylesheet" href="/luci-static/vssr/css/vssr.css?v=<%=math.random(1,100000)%>">
|
||||
|
||||
<script src="<%=media%>/js/jquery.min.js"></script>
|
||||
<script src="/luci-static/vssr/jquery.min.js"></script>
|
||||
|
||||
<div class="pure-g status">
|
||||
<div class="pure-u-1-4">
|
||||
|
||||
@ -3,87 +3,113 @@
|
||||
<script type="text/javascript" src="/luci-static/vssr/polyfill.js?v=1.16"></script>
|
||||
<!-- tblsection -->
|
||||
<fieldset class="cbi-section" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
|
||||
<button class="cbi-button cbi-button-check "><%:Ping All Servers%></button><span class="panel-title">总计
|
||||
<%- print(self.des)-%>个节点</span>
|
||||
<div class="ssr-title">
|
||||
<button class="cbi-button cbi-button-check ">
|
||||
<%:Ping All Servers%>
|
||||
</button><span class="panel-title">总计
|
||||
<%- print(self.des)-%>个节点
|
||||
</span>
|
||||
<div style="clear:both;"></div>
|
||||
</div>
|
||||
|
||||
<div class="cbi-section-node">
|
||||
<%- local count = 0 -%>
|
||||
<div class="cbi-section-table pure-g p-in5">
|
||||
<%- local count=0 -%>
|
||||
|
||||
<div class="cbi-section-table pure-g p-in5">
|
||||
|
||||
<%- local isempty=true for i, k in ipairs(self.serverTable) do section=k isempty=false local
|
||||
fc=(section.name==self.current) and "fast" or "" local flag_icon=(section.flag ~=nil)
|
||||
and "flag-icon-" .. section.flag or "flag-icon-un" local switch_enable=(section.switch_enable=="1" )
|
||||
and "" or "hidden" scope={ valueheader="cbi/cell_valueheader" , valuefooter="cbi/cell_valuefooter" }
|
||||
-%>
|
||||
|
||||
<%- local isempty = true
|
||||
for i, k in ipairs(self.serverTable) do
|
||||
section = k
|
||||
isempty = false
|
||||
local fc = (section.name == self.current) and "fast" or ""
|
||||
local flag_icon = (section.flag ~= nil) and "flag-icon-" .. section.flag or "flag-icon-un"
|
||||
local switch_enable = (section.switch_enable == "1") and "" or "hidden"
|
||||
scope = { valueheader = "cbi/cell_valueheader", valuefooter = "cbi/cell_valuefooter" }
|
||||
-%>
|
||||
|
||||
<div class="pure-u-1-5">
|
||||
<div class="cbi-section-table-row <%=fc %> " id="cbi-<%=self.config%>-<%=section.name%>" data-flag="<%=section.flag%>" server="<%=section.server%>" server_port="<%=section.server_port%>">
|
||||
<div class="loadings hide"></div>
|
||||
<div class="incon type flag-icon <%=flag_icon %>" data-setction="<%=section.name%>">
|
||||
<img class="pure-imgw <%=switch_enable %>" src="/luci-static/vssr/img/switch.png">
|
||||
<div class="tp"><%=section.type%></div>
|
||||
</div>
|
||||
<div class="incon alias"><%=section.alias%></div>
|
||||
<%- if self.extedit or self.addremove then -%>
|
||||
<div class="cbi-section-table-cell">
|
||||
<div class="host_con"></div>
|
||||
<a class="cbi-button ssr-button" type="button" value="" onclick="apply_node('<%=section.name%>')"
|
||||
alt="<%:Apply%>" title="<%:Apply%>"><span class="icon-use"></span> <%:Apply%></a>
|
||||
<%- if self.extedit then -%>
|
||||
<a class="cbi-button ssr-button " type="button" value="" <%- if type(self.extedit) == "string" then
|
||||
%> onclick="location.href='<%=self.extedit:format(section.name)%>'" <%- elseif type(self.extedit) == "function" then
|
||||
%> onclick="location.href='<%=self:extedit(section.name)%>'" <%- end
|
||||
%> alt="<%:Edit%>" title="<%:Edit%>"><span class="icon-edit"></span> <%:Edit%></a>
|
||||
<%- end; if self.addremove then %>
|
||||
<a class="cbi-button ssr-button" type="button" value="" onclick="delete_node('<%=section.name%>')"
|
||||
alt="<%:Delete%>" title="<%:Delete%>" /><span
|
||||
class="icon-delete"></span> <%:Delete%></a>
|
||||
<%- end -%>
|
||||
<div class="pure-u-1-5">
|
||||
<div class="cbi-section-table-row <%=fc %> " id="cbi-<%=self.config%>-<%=section.name%>"
|
||||
data-flag="<%=section.flag%>" server="<%=section.server%>"
|
||||
server_port="<%=section.server_port%>">
|
||||
<div class="loadings hide"></div>
|
||||
<div class="incon type flag-icon <%=flag_icon %>" data-setction="<%=section.name%>">
|
||||
<img class="pure-imgw <%=switch_enable %>" src="/luci-static/vssr/img/switch.png">
|
||||
<div class="tp">
|
||||
<%=section.type%>
|
||||
</div>
|
||||
</div>
|
||||
<div class=" alias">
|
||||
<%=section.alias%>
|
||||
</div>
|
||||
<%- if self.extedit or self.addremove then -%>
|
||||
<div class="cbi-section-table-cell">
|
||||
<div class="host_con"></div>
|
||||
<a class="cbi-button ssr-button" type="button" value=""
|
||||
onclick="apply_node('<%=section.name%>')" alt="<%:Apply%>"
|
||||
title="<%:Apply%>"><span class="icon-use"></span>
|
||||
<%:Apply%>
|
||||
</a>
|
||||
<%- if self.extedit then -%>
|
||||
<a class="cbi-button ssr-button " type="button" value="" <%- if type(self.extedit) == "string" then
|
||||
%> onclick="location.href='<%=self.extedit:format(section.name)%>'" <%- elseif type(self.extedit) == "function" then
|
||||
%> onclick="location.href='<%=self:extedit(section.name)%>'" <%- end
|
||||
%> alt="<%:Edit%>" title="<%:Edit%>"><span class="icon-edit"></span> <%:Edit%></a>
|
||||
<%- end; if self.addremove then %>
|
||||
<a class="cbi-button ssr-button" type="button" value=""
|
||||
onclick="delete_node('<%=section.name%>')" alt="<%:Delete%>"
|
||||
title="<%:Delete%>" /><span class="icon-delete"></span>
|
||||
<%:Delete%></a>
|
||||
<%- end -%>
|
||||
</div>
|
||||
<%- end -%>
|
||||
</div>
|
||||
</div>
|
||||
<%- end -%>
|
||||
|
||||
<%- if isempty then -%>
|
||||
<div class="cbi-section-table-row">
|
||||
<div colspan="<%=count%>"><em><br />
|
||||
<%:This section contains no values yet%>
|
||||
</em></div>
|
||||
</div>
|
||||
<%- end -%>
|
||||
</div>
|
||||
|
||||
<% if self.error then %>
|
||||
<div class="cbi-section-error">
|
||||
<ul>
|
||||
<% for _, c in pairs(self.error) do for _, e in ipairs(c) do -%>
|
||||
<li>
|
||||
<%=pcdata(e):gsub("\n","<br />")%>
|
||||
</li>
|
||||
<%- end end %>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<%- end -%>
|
||||
<% end %>
|
||||
|
||||
<%- if isempty then -%>
|
||||
<div class="cbi-section-table-row">
|
||||
<div colspan="<%=count%>"><em><br /><%:This section contains no values yet%></em></div>
|
||||
</div>
|
||||
<%- end -%>
|
||||
</div>
|
||||
|
||||
<% if self.error then %>
|
||||
<div class="cbi-section-error">
|
||||
<ul><% for _, c in pairs(self.error) do for _, e in ipairs(c) do -%>
|
||||
<li><%=pcdata(e):gsub("\n","<br />")%></li>
|
||||
<%- end end %></ul>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%- if self.addremove then -%>
|
||||
<% if self.template_addremove then include(self.template_addremove) else -%>
|
||||
<div class="cbi-section-create cbi-tblsection-create">
|
||||
<% if self.anonymous then %>
|
||||
<input class="cbi-button cbi-button-add" type="submit" value="<%:Add%>"
|
||||
name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" title="<%:Add%>" />
|
||||
<% else %>
|
||||
<% if self.invalid_cts then -%><div class="cbi-section-error"><% end %>
|
||||
<input type="text" class="cbi-section-create-name"
|
||||
id="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>"
|
||||
name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" data-type="uciname"
|
||||
data-optional="true" />
|
||||
<input class="cbi-button cbi-button-add" type="submit"
|
||||
onclick="this.form.cbi_state = 'add-section'; return true" value="<%:Add%>" title="<%:Add%>" />
|
||||
<% if self.invalid_cts then -%>
|
||||
<br /><%:Invalid%></div>
|
||||
<%- end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<%- end %>
|
||||
<%- end -%>
|
||||
<%- if self.addremove then -%>
|
||||
<% if self.template_addremove then include(self.template_addremove) else -%>
|
||||
<div class="cbi-section-create cbi-tblsection-create">
|
||||
<% if self.anonymous then %>
|
||||
<input class="cbi-button cbi-button-add" type="submit" value="<%:Add%>"
|
||||
name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>"
|
||||
title="<%:Add%>" />
|
||||
<% else %>
|
||||
<% if self.invalid_cts then -%>
|
||||
<div class="cbi-section-error">
|
||||
<% end %>
|
||||
<input type="text" class="cbi-section-create-name"
|
||||
id="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>"
|
||||
name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>"
|
||||
data-type="uciname" data-optional="true" />
|
||||
<input class="cbi-button cbi-button-add" type="submit"
|
||||
onclick="this.form.cbi_state = 'add-section'; return true"
|
||||
value="<%:Add%>" title="<%:Add%>" />
|
||||
<% if self.invalid_cts then -%>
|
||||
<br />
|
||||
<%:Invalid%>
|
||||
</div>
|
||||
<%- end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<%- end %>
|
||||
<%- end -%>
|
||||
</div>
|
||||
</fieldset>
|
||||
<!-- /tblsection -->
|
||||
@ -120,15 +146,15 @@
|
||||
$html += '<div class="pure-u-1-2"><div class="gap"><button class="cbi-button cbi-button-apply change-node" data-server="global" data-node="' + node + '"> 主服务器 </button></div></div>';
|
||||
$html += '<div class="pure-u-1-2"><div class="gap"><button class="cbi-button cbi-button-apply change-node" data-server="udp_relay" data-node="' + node + '"> UDP游戏模式 </button></div></div>';
|
||||
$html += '<div class="pure-u-1-2"><div class="gap"><button class="cbi-button cbi-button-apply change-node" data-server="youtube" data-node="' + node + '"> Youtube </button></div></div>';
|
||||
if ($('#cbi-' + CONFIG + '-' + node).attr("data-flag") == "tw") {
|
||||
//if ($('#cbi-' + CONFIG + '-' + node).attr("data-flag") == "tw") {
|
||||
$html += '<div class="pure-u-1-2"><div class="gap"><button class="cbi-button cbi-button-apply change-node" data-server="tw_video" data-node="' + node + '"> TW Video </button></div></div>';
|
||||
}
|
||||
//}
|
||||
$html += '<div class="pure-u-1-2"><div class="gap"><button class="cbi-button cbi-button-apply change-node" data-server="netflix" data-node="' + node + '"> Netflix </button></div></div>';
|
||||
$html += '<div class="pure-u-1-2"><div class="gap"><button class="cbi-button cbi-button-apply change-node" data-server="disney" data-node="' + node + '"> Diseny+ </button></div></div>';
|
||||
$html += '<div class="pure-u-1-2"><div class="gap"><button class="cbi-button cbi-button-apply change-node" data-server="prime" data-node="' + node + '"> Prime Video </button></div></div>';
|
||||
if ($('#cbi-' + CONFIG + '-' + node).attr("data-flag") == "hk") {
|
||||
//if ($('#cbi-' + CONFIG + '-' + node).attr("data-flag") == "hk") {
|
||||
$html += '<div class="pure-u-1-2"><div class="gap"><button class="cbi-button cbi-button-apply change-node" data-server="tvb" data-node="' + node + '"> TVB Video </button></div></div>';
|
||||
}
|
||||
//}
|
||||
$html += '<div class="pure-u-1-2"><div class="gap"><button class="cbi-button cbi-button-apply change-node" data-server="custom" data-node="' + node + '"> 自定义 </button></div></div>';
|
||||
$html += '</div>';
|
||||
Swal.fire({
|
||||
@ -165,9 +191,9 @@
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//删除节点
|
||||
function delete_node(node){
|
||||
function delete_node(node) {
|
||||
XHR.halt();
|
||||
$.each(ajaxArray, function (n, value) { value.abort(); }) //中断所有的ajax请求
|
||||
$.get(DELETE_NODE_URL, { node: node },
|
||||
@ -223,10 +249,7 @@
|
||||
function (data, status) {
|
||||
currentCheckCount++
|
||||
var host_con = $(target).find(".host_con");
|
||||
host_con.removeClass("fast");
|
||||
host_con.removeClass("middle");
|
||||
host_con.removeClass("slow");
|
||||
host_con.removeClass("nopass");
|
||||
host_con.removeClass("fast middle slow nopass");
|
||||
if (data.ret == 1) {
|
||||
if (data.used == "") {
|
||||
host_con.addClass("nopass");
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
<%+cbi/valueheader%>
|
||||
<link rel="stylesheet" href="/luci-static/vssr/css/vssr.css?v=<%=math.random(1,100000)%>">
|
||||
<script src="/luci-static/vssr/jquery.min.js"></script>
|
||||
<label class="cbi-value-title"><%= translate("Update") %></label>
|
||||
<div class="cbi-value-field">
|
||||
<input class="cbi-button cbi-button-reload" id="update_subscribe" type="button" size="0"
|
||||
@ -7,7 +8,7 @@
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
|
||||
const SAVE_SUBSCRIBE_URL = '<%=luci.dispatcher.build_url("admin", "services", "vssr","subscribe")%>';
|
||||
const SERVERS_URL = '<%=luci.dispatcher.build_url("admin", "services", "vssr","servers")%>';
|
||||
|
||||
@ -20,14 +21,14 @@
|
||||
'<textarea cols="63" rows="28" wrap="on" readonly="readonly" id="log_content3" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
|
||||
$(document).ready(function () {
|
||||
//显示并开始刷新订阅
|
||||
function update_subscribe() {
|
||||
$("body").append(modal);
|
||||
$(".modals-bg").removeClass("hide");
|
||||
setTimeout(function(){
|
||||
$(".modals").removeClass("hide");
|
||||
}, 200);
|
||||
}, 100);
|
||||
setTimeout("get_realtime_log();", 500);
|
||||
}
|
||||
//保存订阅按钮
|
||||
@ -76,7 +77,7 @@
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function get_realtime_log() {
|
||||
$.ajax({
|
||||
@ -106,7 +107,7 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<%+cbi/valuefooter%>
|
||||
|
||||
@ -128,13 +128,13 @@ msgid "SSR Server"
|
||||
msgstr "服务端"
|
||||
|
||||
msgid "vssr Server"
|
||||
msgstr "vssr 服务端"
|
||||
msgstr "Hello World 服务端"
|
||||
|
||||
msgid "vssr Server is running"
|
||||
msgstr "vssr 服务端运行中"
|
||||
msgstr "Hello World 服务端运行中"
|
||||
|
||||
msgid "vssr Server is not running"
|
||||
msgstr "vssr 服务端未运行"
|
||||
msgstr "Hello World 服务端未运行"
|
||||
|
||||
msgid "Enable Server"
|
||||
msgstr "启动服务端"
|
||||
@ -710,3 +710,15 @@ msgstr "TVB 域名"
|
||||
|
||||
msgid "Custom Domain"
|
||||
msgstr "自定义域名"
|
||||
|
||||
msgid "Subscribe"
|
||||
msgstr "订阅设置"
|
||||
|
||||
msgid "Local Proxy"
|
||||
msgstr "本地代理"
|
||||
|
||||
msgid "↑ Put your IP list here"
|
||||
msgstr "↑ 在上面放置你需要分流的IP列表"
|
||||
|
||||
msgid "↑ Put your domain list here"
|
||||
msgstr "↑ 在上面放置你需要分流的域名列表"
|
||||
|
||||
@ -609,6 +609,7 @@ EOF
|
||||
/etc/init.d/dnsmasq restart >/dev/null 2>&1
|
||||
start_server
|
||||
start_local
|
||||
scount=$(count_shunt)
|
||||
if [ $scount != "0" ]; then
|
||||
start_shunt
|
||||
fi
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
local ucursor = require 'luci.model.uci'.cursor()
|
||||
local name = 'vssr'
|
||||
local json = require 'luci.jsonc'
|
||||
local nixio = require 'nixio'
|
||||
local server_section = arg[1]
|
||||
local proto = arg[2]
|
||||
local local_port = arg[3]
|
||||
@ -8,6 +9,9 @@ local outbounds_table = {}
|
||||
local rules_table = {}
|
||||
|
||||
function read_conf(file)
|
||||
if not nixio.fs.access(file) then
|
||||
return nil
|
||||
end
|
||||
local rfile = io.open(file, "r")
|
||||
local ltable = {}
|
||||
for line in rfile:lines() do
|
||||
@ -18,15 +22,30 @@ function read_conf(file)
|
||||
return rtable
|
||||
end
|
||||
|
||||
|
||||
local v2ray_flow = ucursor:get_first(name, 'global', 'v2ray_flow', '0')
|
||||
|
||||
local custom_domain = read_conf("/etc/vssr/custom_domain.list")
|
||||
local custom_ip = read_conf("/etc/vssr/custom_ip.list")
|
||||
|
||||
local youtube_domain = read_conf("/etc/vssr/youtube_domain.list")
|
||||
local youtube_ip = read_conf("/etc/vssr/youtube_ip.list")
|
||||
|
||||
local tw_video_domain = read_conf("/etc/vssr/tw_video_domain.list")
|
||||
local tw_video_ip = read_conf("/etc/vssr/tw_video_ip.list")
|
||||
|
||||
local netflix_domain = read_conf("/etc/vssr/netflix_domain.list")
|
||||
local netflix_ip = read_conf("/etc/vssr/netflix_ip.list")
|
||||
|
||||
local disney_domain = read_conf("/etc/vssr/disney_domain.list")
|
||||
local disney_ip = read_conf("/etc/vssr/disney_ip.list")
|
||||
|
||||
local prime_domain = read_conf("/etc/vssr/prime_domain.list")
|
||||
local prime_ip = read_conf("/etc/vssr/prime_ip.list")
|
||||
|
||||
local tvb_domain = read_conf("/etc/vssr/tvb_domain.list")
|
||||
local tvb_ip = read_conf("/etc/vssr/tvb_ip.list")
|
||||
|
||||
|
||||
local flow_table = {
|
||||
yotube = {
|
||||
@ -35,6 +54,7 @@ local flow_table = {
|
||||
rules = {
|
||||
type = 'field',
|
||||
domain = youtube_domain,
|
||||
ip = youtube_ip,
|
||||
outboundTag = 'youtube'
|
||||
}
|
||||
},
|
||||
@ -44,6 +64,7 @@ local flow_table = {
|
||||
rules = {
|
||||
type = 'field',
|
||||
domain = tw_video_domain,
|
||||
ip = tw_video_ip,
|
||||
outboundTag = 'tw_video'
|
||||
}
|
||||
},
|
||||
@ -53,6 +74,7 @@ local flow_table = {
|
||||
rules = {
|
||||
type = 'field',
|
||||
domain = netflix_domain,
|
||||
ip = netflix_ip,
|
||||
outboundTag = 'netflix'
|
||||
}
|
||||
},
|
||||
@ -62,6 +84,7 @@ local flow_table = {
|
||||
rules = {
|
||||
type = 'field',
|
||||
domain = disney_domain,
|
||||
ip = disney_ip,
|
||||
outboundTag = 'disney'
|
||||
}
|
||||
},
|
||||
@ -71,6 +94,7 @@ local flow_table = {
|
||||
rules = {
|
||||
type = 'field',
|
||||
domain = prime_domain,
|
||||
ip = prime_ip,
|
||||
outboundTag = 'prime'
|
||||
}
|
||||
},
|
||||
@ -80,6 +104,7 @@ local flow_table = {
|
||||
rules = {
|
||||
type = 'field',
|
||||
domain = tvb_domain,
|
||||
ip = tvb_ip,
|
||||
outboundTag = 'tvb'
|
||||
}
|
||||
},
|
||||
@ -89,6 +114,7 @@ local flow_table = {
|
||||
rules = {
|
||||
type = 'field',
|
||||
domain = custom_domain,
|
||||
ip = custom_ip,
|
||||
outboundTag = 'custom'
|
||||
}
|
||||
}
|
||||
@ -113,7 +139,7 @@ local bt_rules1 = {
|
||||
'BitTorrent',
|
||||
'announce_peer',
|
||||
'announce.php?passkey='
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function gen_outbound(server_node, tags, local_ports)
|
||||
@ -210,12 +236,30 @@ function gen_bt_outbounds()
|
||||
end
|
||||
|
||||
if v2ray_flow == '1' then
|
||||
|
||||
table.insert(outbounds_table, gen_outbound(server_section, 'global', 2080))
|
||||
for _, v in pairs(flow_table) do
|
||||
if(v.rules.domain ~= nil) then
|
||||
if(v.rules.domain ~= nil or v.rules.ip ~= nil) then
|
||||
local server = ucursor:get_first(name, 'global', v.name .. '_server')
|
||||
table.insert(outbounds_table, gen_outbound(server, v.name, v.port))
|
||||
table.insert(rules_table, (server ~= nil and server ~= 'nil' ) and v.rules or nil)
|
||||
|
||||
if(v.rules.domain ~= nil) then
|
||||
domain_rules = {
|
||||
type = 'field',
|
||||
domain = v.rules.domain,
|
||||
outboundTag = v.rules.outboundTag
|
||||
}
|
||||
table.insert(rules_table, (server ~= nil and server ~= 'nil' ) and domain_rules or nil)
|
||||
end
|
||||
|
||||
if(v.rules.ip ~= nil) then
|
||||
ip_rules = {
|
||||
type = 'field',
|
||||
ip = v.rules.ip,
|
||||
outboundTag = v.rules.outboundTag
|
||||
}
|
||||
table.insert(rules_table, (server ~= nil and server ~= 'nil' ) and ip_rules or nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
@ -246,6 +290,6 @@ local v2ray = {
|
||||
},
|
||||
-- 传出连接
|
||||
outbounds = outbounds_table,
|
||||
routing = {domainStrategy = 'AsIs', rules = rules_table}
|
||||
routing = {domainStrategy = 'IPIfNonMatch', rules = rules_table}
|
||||
}
|
||||
print(json.stringify(v2ray, 1))
|
||||
|
||||
@ -33,6 +33,40 @@ local switch = '0'
|
||||
local subscribe_url = ucic:get_first(name, 'server_subscribe', 'subscribe_url', {})
|
||||
local filter_words = ucic:get_first(name, 'server_subscribe', 'filter_words', '过期时间/剩余流量')
|
||||
|
||||
function print_r ( t )
|
||||
local print_r_cache={}
|
||||
local function sub_print_r(t,indent)
|
||||
if (print_r_cache[tostring(t)]) then
|
||||
print(indent.."*"..tostring(t))
|
||||
else
|
||||
print_r_cache[tostring(t)]=true
|
||||
if (type(t)=="table") then
|
||||
for pos,val in pairs(t) do
|
||||
if (type(val)=="table") then
|
||||
print(indent.."["..pos.."] => "..tostring(t).." {")
|
||||
sub_print_r(val,indent..string.rep(" ",string.len(pos)+8))
|
||||
print(indent..string.rep(" ",string.len(pos)+6).."}")
|
||||
elseif (type(val)=="string") then
|
||||
print(indent.."["..pos..'] => "'..val..'"')
|
||||
else
|
||||
print(indent.."["..pos.."] => "..tostring(val))
|
||||
end
|
||||
end
|
||||
else
|
||||
print(indent..tostring(t))
|
||||
end
|
||||
end
|
||||
end
|
||||
if (type(t)=="table") then
|
||||
print(tostring(t).." {")
|
||||
sub_print_r(t," ")
|
||||
print("}")
|
||||
else
|
||||
sub_print_r(t," ")
|
||||
end
|
||||
print()
|
||||
end
|
||||
|
||||
local log = function(...)
|
||||
print(os.date('%Y-%m-%d %H:%M:%S ') .. table.concat({...}, ' '))
|
||||
end
|
||||
@ -55,6 +89,43 @@ local function split(full, sep)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
--table去重
|
||||
|
||||
local function clone( object )
|
||||
local lookup_table = {}
|
||||
local function copyObj( object )
|
||||
if type( object ) ~= "table" then
|
||||
return object
|
||||
elseif lookup_table[object] then
|
||||
return lookup_table[object]
|
||||
end
|
||||
|
||||
local new_table = {}
|
||||
lookup_table[object] = new_table
|
||||
for key, value in pairs( object ) do
|
||||
new_table[copyObj( key )] = copyObj( value )
|
||||
end
|
||||
return setmetatable( new_table, getmetatable( object ) )
|
||||
end
|
||||
return copyObj( object )
|
||||
end
|
||||
|
||||
local function table_unique(list)
|
||||
local temp1 = clone(list)
|
||||
local temp2 = clone(list)
|
||||
for k1, v1 in ipairs(temp1) do
|
||||
for k2, v2 in ipairs(temp2) do
|
||||
if v1.alias ~= v2.alias and v1.hashkey == v2.hashkey then
|
||||
table.remove(temp1, k1)
|
||||
table.remove(temp2, k1)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
return temp1
|
||||
end
|
||||
|
||||
-- urlencode
|
||||
local function get_urlencode(c)
|
||||
return sformat('%%%02X', sbyte(c))
|
||||
@ -385,12 +456,21 @@ local execute = function()
|
||||
end
|
||||
end
|
||||
log('成功解析节点数量: ' .. #nodes)
|
||||
end
|
||||
else
|
||||
log(url .. ': 获取内容为空')
|
||||
end
|
||||
end
|
||||
end
|
||||
-- diff
|
||||
do
|
||||
assert(next(nodeResult), '获取不到节点信息,请检查路由器是否能够访问网络,或者订阅链接是否正确')
|
||||
if next(nodeResult) == nil then
|
||||
log("更新失败,没有可用的节点信息")
|
||||
if proxy == '0' then
|
||||
luci.sys.init.start(name)
|
||||
log('订阅失败, 恢复服务')
|
||||
end
|
||||
return
|
||||
end
|
||||
local add, del = 0, 0
|
||||
ucic:foreach(
|
||||
name,
|
||||
@ -407,17 +487,24 @@ local execute = function()
|
||||
setmetatable(nodeResult[old.grouphashkey][old.hashkey], {__index = {_ignore = true}})
|
||||
end
|
||||
else
|
||||
if (old.alias ~= nil) then
|
||||
log('忽略手动添加的节点: ' .. old.alias)
|
||||
if not old.alias then
|
||||
if not old.server or old.server_port then
|
||||
ucic:delete(name, old['.name'])
|
||||
else
|
||||
old.alias = old.server .. ':' .. old.server_port
|
||||
log('忽略手动添加的节点: ' .. old.alias)
|
||||
end
|
||||
else
|
||||
log('忽略手动添加的无效节点')
|
||||
log('忽略手动添加的节点: ' .. old.alias)
|
||||
end
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
|
||||
for k, v in ipairs(nodeResult) do
|
||||
for kk, vv in ipairs(v) do
|
||||
-- 如果订阅节点中有相同的节点信息 需要先去重。
|
||||
new_nodes = table_unique(v)
|
||||
for kk, vv in ipairs(new_nodes) do
|
||||
if not vv._ignore then
|
||||
local section = ucic:add(name, uciType)
|
||||
ucic:tset(name, section, vv)
|
||||
|
||||
@ -16,11 +16,7 @@ local log = function(...)
|
||||
end
|
||||
|
||||
log('正在更新【GFW列表】数据库')
|
||||
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'
|
||||
else
|
||||
refresh_cmd = 'wget -O /tmp/gfw.b64 http://iytc.net/tools/list.b64'
|
||||
end
|
||||
refresh_cmd = 'wget-ssl --no-check-certificate https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt -O /tmp/gfw.b64'
|
||||
sret = luci.sys.call(refresh_cmd .. ' 2>/dev/null')
|
||||
if sret == 0 then
|
||||
luci.sys.call('/usr/bin/vssr-gfw')
|
||||
@ -43,7 +39,7 @@ else
|
||||
end
|
||||
|
||||
log('正在更新【国内IP段】数据库')
|
||||
refresh_cmd ="wget -O- 'https://ispip.clang.cn/all_cn.txt' > /tmp/china_ssr.txt 2>/dev/null"
|
||||
refresh_cmd ="wget-ssl -O- 'https://ispip.clang.cn/all_cn.txt' > /tmp/china_ssr.txt 2>/dev/null"
|
||||
sret = luci.sys.call(refresh_cmd)
|
||||
icount = luci.sys.exec('cat /tmp/china_ssr.txt | wc -l')
|
||||
if sret == 0 then
|
||||
@ -69,12 +65,8 @@ end
|
||||
if ucic:get_first('vssr', 'global', 'adblock', '') == '1' then
|
||||
log('正在更新【广告屏蔽】数据库')
|
||||
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'
|
||||
end
|
||||
refresh_cmd = 'wget-ssl --no-check-certificate -O - https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt > /tmp/adnew.conf'
|
||||
need_process = 1
|
||||
sret = luci.sys.call(refresh_cmd .. ' 2>/dev/null')
|
||||
if sret == 0 then
|
||||
if need_process == 1 then
|
||||
|
||||
@ -0,0 +1,232 @@
|
||||
/*!
|
||||
Pure v1.0.1
|
||||
Copyright 2013 Yahoo!
|
||||
Licensed under the BSD License.
|
||||
https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
*/
|
||||
.pure-g {
|
||||
letter-spacing: -.31em;
|
||||
text-rendering: optimizespeed;
|
||||
font-family: FreeSans, Arimo, "Droid Sans", Helvetica, Arial, sans-serif;
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-box-direction: normal;
|
||||
-webkit-flex-flow: row wrap;
|
||||
-ms-flex-flow: row wrap;
|
||||
flex-flow: row wrap;
|
||||
-webkit-align-content: flex-start;
|
||||
-ms-flex-line-pack: start;
|
||||
align-content: flex-start
|
||||
}
|
||||
|
||||
@media all and (-ms-high-contrast:none),
|
||||
(-ms-high-contrast:active) {
|
||||
table .pure-g {
|
||||
display: block
|
||||
}
|
||||
}
|
||||
|
||||
.opera-only :-o-prefocus,
|
||||
.pure-g {
|
||||
word-spacing: -.43em
|
||||
}
|
||||
|
||||
.pure-u {
|
||||
display: inline-block;
|
||||
zoom: 1;
|
||||
letter-spacing: normal;
|
||||
word-spacing: normal;
|
||||
vertical-align: top;
|
||||
text-rendering: auto
|
||||
}
|
||||
|
||||
.pure-g [class*=pure-u] {
|
||||
font-family: sans-serif
|
||||
}
|
||||
|
||||
.pure-u-1,
|
||||
.pure-u-1-1,
|
||||
.pure-u-1-12,
|
||||
.pure-u-1-2,
|
||||
.pure-u-1-24,
|
||||
.pure-u-1-3,
|
||||
.pure-u-1-4,
|
||||
.pure-u-1-5,
|
||||
.pure-u-1-6,
|
||||
.pure-u-1-8,
|
||||
.pure-u-10-24,
|
||||
.pure-u-11-12,
|
||||
.pure-u-11-24,
|
||||
.pure-u-12-24,
|
||||
.pure-u-13-24,
|
||||
.pure-u-14-24,
|
||||
.pure-u-15-24,
|
||||
.pure-u-16-24,
|
||||
.pure-u-17-24,
|
||||
.pure-u-18-24,
|
||||
.pure-u-19-24,
|
||||
.pure-u-2-24,
|
||||
.pure-u-2-3,
|
||||
.pure-u-2-5,
|
||||
.pure-u-20-24,
|
||||
.pure-u-21-24,
|
||||
.pure-u-22-24,
|
||||
.pure-u-23-24,
|
||||
.pure-u-24-24,
|
||||
.pure-u-3-24,
|
||||
.pure-u-3-4,
|
||||
.pure-u-3-5,
|
||||
.pure-u-3-8,
|
||||
.pure-u-4-24,
|
||||
.pure-u-4-5,
|
||||
.pure-u-5-12,
|
||||
.pure-u-5-24,
|
||||
.pure-u-5-5,
|
||||
.pure-u-5-6,
|
||||
.pure-u-5-8,
|
||||
.pure-u-6-24,
|
||||
.pure-u-7-12,
|
||||
.pure-u-7-24,
|
||||
.pure-u-7-8,
|
||||
.pure-u-8-24,
|
||||
.pure-u-9-24 {
|
||||
display: inline-block;
|
||||
zoom: 1;
|
||||
letter-spacing: normal;
|
||||
word-spacing: normal;
|
||||
vertical-align: top;
|
||||
text-rendering: auto
|
||||
}
|
||||
|
||||
.pure-u-1-24 {
|
||||
width: 4.1667%
|
||||
}
|
||||
|
||||
.pure-u-1-12,
|
||||
.pure-u-2-24 {
|
||||
width: 8.3333%
|
||||
}
|
||||
|
||||
.pure-u-1-8,
|
||||
.pure-u-3-24 {
|
||||
width: 12.5%
|
||||
}
|
||||
|
||||
.pure-u-1-6,
|
||||
.pure-u-4-24 {
|
||||
width: 16.6667%
|
||||
}
|
||||
|
||||
.pure-u-1-5 {
|
||||
width: 20%
|
||||
}
|
||||
|
||||
.pure-u-5-24 {
|
||||
width: 20.8333%
|
||||
}
|
||||
|
||||
.pure-u-1-4,
|
||||
.pure-u-6-24 {
|
||||
width: 25%
|
||||
}
|
||||
|
||||
.pure-u-7-24 {
|
||||
width: 29.1667%
|
||||
}
|
||||
|
||||
.pure-u-1-3,
|
||||
.pure-u-8-24 {
|
||||
width: 33.3333%
|
||||
}
|
||||
|
||||
.pure-u-3-8,
|
||||
.pure-u-9-24 {
|
||||
width: 37.5%
|
||||
}
|
||||
|
||||
.pure-u-2-5 {
|
||||
width: 40%
|
||||
}
|
||||
|
||||
.pure-u-10-24,
|
||||
.pure-u-5-12 {
|
||||
width: 41.6667%
|
||||
}
|
||||
|
||||
.pure-u-11-24 {
|
||||
width: 45.8333%
|
||||
}
|
||||
|
||||
.pure-u-1-2,
|
||||
.pure-u-12-24 {
|
||||
width: 50%
|
||||
}
|
||||
|
||||
.pure-u-13-24 {
|
||||
width: 54.1667%
|
||||
}
|
||||
|
||||
.pure-u-14-24,
|
||||
.pure-u-7-12 {
|
||||
width: 58.3333%
|
||||
}
|
||||
|
||||
.pure-u-3-5 {
|
||||
width: 60%
|
||||
}
|
||||
|
||||
.pure-u-15-24,
|
||||
.pure-u-5-8 {
|
||||
width: 62.5%
|
||||
}
|
||||
|
||||
.pure-u-16-24,
|
||||
.pure-u-2-3 {
|
||||
width: 66.6667%
|
||||
}
|
||||
|
||||
.pure-u-17-24 {
|
||||
width: 70.8333%
|
||||
}
|
||||
|
||||
.pure-u-18-24,
|
||||
.pure-u-3-4 {
|
||||
width: 75%
|
||||
}
|
||||
|
||||
.pure-u-19-24 {
|
||||
width: 79.1667%
|
||||
}
|
||||
|
||||
.pure-u-4-5 {
|
||||
width: 80%
|
||||
}
|
||||
|
||||
.pure-u-20-24,
|
||||
.pure-u-5-6 {
|
||||
width: 83.3333%
|
||||
}
|
||||
|
||||
.pure-u-21-24,
|
||||
.pure-u-7-8 {
|
||||
width: 87.5%
|
||||
}
|
||||
|
||||
.pure-u-11-12,
|
||||
.pure-u-22-24 {
|
||||
width: 91.6667%
|
||||
}
|
||||
|
||||
.pure-u-23-24 {
|
||||
width: 95.8333%
|
||||
}
|
||||
|
||||
.pure-u-1,
|
||||
.pure-u-1-1,
|
||||
.pure-u-24-24,
|
||||
.pure-u-5-5 {
|
||||
width: 100%
|
||||
}
|
||||
@ -1,245 +1,73 @@
|
||||
@import url("flag-icon.min.css?v=1.16");
|
||||
@import url("sweetalert2.css?v=1.16");
|
||||
/*!
|
||||
Pure v1.0.1
|
||||
Copyright 2013 Yahoo!
|
||||
Licensed under the BSD License.
|
||||
https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
*/
|
||||
@import url("pure.css?v=1.16");
|
||||
|
||||
|
||||
.pure-g {
|
||||
letter-spacing: -.31em;
|
||||
text-rendering: optimizespeed;
|
||||
font-family: FreeSans, Arimo, "Droid Sans", Helvetica, Arial, sans-serif;
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-box-direction: normal;
|
||||
-webkit-flex-flow: row wrap;
|
||||
-ms-flex-flow: row wrap;
|
||||
flex-flow: row wrap;
|
||||
-webkit-align-content: flex-start;
|
||||
-ms-flex-line-pack: start;
|
||||
align-content: flex-start
|
||||
/** Common **/
|
||||
.pure-img {
|
||||
max-height: 100%;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
@media all and (-ms-high-contrast:none),
|
||||
(-ms-high-contrast:active) {
|
||||
table .pure-g {
|
||||
display: block
|
||||
}
|
||||
.pure-imgw {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.opera-only :-o-prefocus,
|
||||
.pure-g {
|
||||
word-spacing: -.43em
|
||||
}
|
||||
|
||||
.pure-u {
|
||||
display: inline-block;
|
||||
zoom: 1;
|
||||
letter-spacing: normal;
|
||||
word-spacing: normal;
|
||||
vertical-align: top;
|
||||
text-rendering: auto
|
||||
}
|
||||
|
||||
.pure-g [class*=pure-u] {
|
||||
font-family: sans-serif
|
||||
}
|
||||
|
||||
.pure-u-1,
|
||||
.pure-u-1-1,
|
||||
.pure-u-1-12,
|
||||
.pure-u-1-2,
|
||||
.pure-u-1-24,
|
||||
.pure-u-1-3,
|
||||
.pure-u-1-4,
|
||||
.pure-u-1-5,
|
||||
.pure-u-1-6,
|
||||
.pure-u-1-8,
|
||||
.pure-u-10-24,
|
||||
.pure-u-11-12,
|
||||
.pure-u-11-24,
|
||||
.pure-u-12-24,
|
||||
.pure-u-13-24,
|
||||
.pure-u-14-24,
|
||||
.pure-u-15-24,
|
||||
.pure-u-16-24,
|
||||
.pure-u-17-24,
|
||||
.pure-u-18-24,
|
||||
.pure-u-19-24,
|
||||
.pure-u-2-24,
|
||||
.pure-u-2-3,
|
||||
.pure-u-2-5,
|
||||
.pure-u-20-24,
|
||||
.pure-u-21-24,
|
||||
.pure-u-22-24,
|
||||
.pure-u-23-24,
|
||||
.pure-u-24-24,
|
||||
.pure-u-3-24,
|
||||
.pure-u-3-4,
|
||||
.pure-u-3-5,
|
||||
.pure-u-3-8,
|
||||
.pure-u-4-24,
|
||||
.pure-u-4-5,
|
||||
.pure-u-5-12,
|
||||
.pure-u-5-24,
|
||||
.pure-u-5-5,
|
||||
.pure-u-5-6,
|
||||
.pure-u-5-8,
|
||||
.pure-u-6-24,
|
||||
.pure-u-7-12,
|
||||
.pure-u-7-24,
|
||||
.pure-u-7-8,
|
||||
.pure-u-8-24,
|
||||
.pure-u-9-24 {
|
||||
display: inline-block;
|
||||
zoom: 1;
|
||||
letter-spacing: normal;
|
||||
word-spacing: normal;
|
||||
vertical-align: top;
|
||||
text-rendering: auto
|
||||
}
|
||||
|
||||
.pure-u-1-24 {
|
||||
width: 4.1667%
|
||||
}
|
||||
|
||||
.pure-u-1-12,
|
||||
.pure-u-2-24 {
|
||||
width: 8.3333%
|
||||
}
|
||||
|
||||
.pure-u-1-8,
|
||||
.pure-u-3-24 {
|
||||
width: 12.5%
|
||||
}
|
||||
|
||||
.pure-u-1-6,
|
||||
.pure-u-4-24 {
|
||||
width: 16.6667%
|
||||
}
|
||||
|
||||
.pure-u-1-5 {
|
||||
width: 20%
|
||||
}
|
||||
|
||||
.pure-u-5-24 {
|
||||
width: 20.8333%
|
||||
}
|
||||
|
||||
.pure-u-1-4,
|
||||
.pure-u-6-24 {
|
||||
width: 25%
|
||||
}
|
||||
|
||||
.pure-u-7-24 {
|
||||
width: 29.1667%
|
||||
}
|
||||
|
||||
.pure-u-1-3,
|
||||
.pure-u-8-24 {
|
||||
width: 33.3333%
|
||||
}
|
||||
|
||||
.pure-u-3-8,
|
||||
.pure-u-9-24 {
|
||||
width: 37.5%
|
||||
}
|
||||
|
||||
.pure-u-2-5 {
|
||||
width: 40%
|
||||
}
|
||||
|
||||
.pure-u-10-24,
|
||||
.pure-u-5-12 {
|
||||
width: 41.6667%
|
||||
}
|
||||
|
||||
.pure-u-11-24 {
|
||||
width: 45.8333%
|
||||
}
|
||||
|
||||
.pure-u-1-2,
|
||||
.pure-u-12-24 {
|
||||
width: 50%
|
||||
}
|
||||
|
||||
.pure-u-13-24 {
|
||||
width: 54.1667%
|
||||
}
|
||||
|
||||
.pure-u-14-24,
|
||||
.pure-u-7-12 {
|
||||
width: 58.3333%
|
||||
}
|
||||
|
||||
.pure-u-3-5 {
|
||||
width: 60%
|
||||
}
|
||||
|
||||
.pure-u-15-24,
|
||||
.pure-u-5-8 {
|
||||
width: 62.5%
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
|
||||
.pure-u-16-24,
|
||||
.pure-u-2-3 {
|
||||
width: 66.6667%
|
||||
.gap {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.pure-u-17-24 {
|
||||
width: 70.8333%
|
||||
|
||||
/** 复写theme **/
|
||||
|
||||
.cbi-section {
|
||||
|
||||
border: 0;
|
||||
border-radius: .375rem;
|
||||
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.pure-u-18-24,
|
||||
.pure-u-3-4 {
|
||||
width: 75%
|
||||
.cbi-section-node {
|
||||
|
||||
border: 0;
|
||||
border-radius: .375rem;
|
||||
margin-bottom: 0px;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
padding: 0rem 0;
|
||||
}
|
||||
|
||||
.pure-u-19-24 {
|
||||
width: 79.1667%
|
||||
#cbi-vssr {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.pure-u-4-5 {
|
||||
width: 80%
|
||||
}
|
||||
|
||||
.pure-u-20-24,
|
||||
.pure-u-5-6 {
|
||||
width: 83.3333%
|
||||
}
|
||||
|
||||
.pure-u-21-24,
|
||||
.pure-u-7-8 {
|
||||
width: 87.5%
|
||||
}
|
||||
|
||||
.pure-u-11-12,
|
||||
.pure-u-22-24 {
|
||||
width: 91.6667%
|
||||
}
|
||||
|
||||
.pure-u-23-24 {
|
||||
width: 95.8333%
|
||||
}
|
||||
|
||||
.pure-u-1,
|
||||
.pure-u-1-1,
|
||||
.pure-u-24-24,
|
||||
.pure-u-5-5 {
|
||||
width: 100%
|
||||
#cbi-vssr .panel-title {
|
||||
width: 100%;
|
||||
display: block;
|
||||
margin-bottom: 0;
|
||||
padding: .8755rem 1.5rem;
|
||||
|
||||
margin-bottom: 0rem;
|
||||
letter-spacing: .1rem;
|
||||
|
||||
font-weight: 600;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/** Top StatusBar **/
|
||||
.status {
|
||||
margin: 1rem -0.5rem 1rem -0.5rem;
|
||||
margin: 0.5rem -0.5rem 1rem -0.5rem;
|
||||
}
|
||||
|
||||
.block {
|
||||
.status .block {
|
||||
margin: 0.5rem 0.5rem;
|
||||
padding: 0;
|
||||
font-weight: normal;
|
||||
@ -255,56 +83,28 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
box-shadow: 0 0 2rem 0 rgba(136, 152, 170, .15);
|
||||
}
|
||||
|
||||
.img-con {
|
||||
.status .block .img-con {
|
||||
margin: 1rem;
|
||||
|
||||
}
|
||||
|
||||
.pure-img {
|
||||
max-height: 100%;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.pure-imgw {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.green {
|
||||
.status .block .green {
|
||||
font-size: 1.25rem;
|
||||
color: #2dce89;
|
||||
}
|
||||
|
||||
.red {
|
||||
.status .block .red {
|
||||
font-size: 1.25rem;
|
||||
color: #fb6340;
|
||||
}
|
||||
|
||||
.sk-text-success {
|
||||
color: #2dce89;
|
||||
}
|
||||
|
||||
.sk-text-error {
|
||||
color: #fb6340;
|
||||
}
|
||||
|
||||
.gap {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.block img {
|
||||
.status .block img {
|
||||
width: 48px;
|
||||
height: auto;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.pure-u-5-8 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
|
||||
.block h4 {
|
||||
.status .block h4 {
|
||||
font-size: .8125rem;
|
||||
font-weight: 600;
|
||||
margin: 1rem;
|
||||
@ -312,12 +112,10 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
line-height: 1.8em;
|
||||
}
|
||||
|
||||
.p-in5 {
|
||||
padding: 8px;
|
||||
}
|
||||
/** Server List **/
|
||||
|
||||
.flag-icon:before {
|
||||
position: absolute;
|
||||
.p-in5 {
|
||||
margin: 8px !important;
|
||||
}
|
||||
|
||||
.cbi-section-table-row {
|
||||
@ -346,6 +144,17 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.ssr-button:link,
|
||||
.ssr-button:hover,
|
||||
.ssr-button:focus,
|
||||
.ssr-button:visited,
|
||||
.ssr-button:active {
|
||||
|
||||
outline: 0;
|
||||
text-decoration: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.cbi-section-table-row.fast .ssr-button {
|
||||
color: #fff;
|
||||
}
|
||||
@ -363,6 +172,15 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.host_con {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 70px;
|
||||
text-align: left;
|
||||
height: 22px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.host_con.fast {
|
||||
color: #6f9a37;
|
||||
}
|
||||
@ -379,7 +197,19 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
color: #fb6340;
|
||||
}
|
||||
|
||||
.host_ok {
|
||||
color: #fff;
|
||||
background: #2dce89;
|
||||
padding: 0.1rem 0.5rem;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
|
||||
.host_error {
|
||||
color: #fff;
|
||||
background: #f5365c;
|
||||
padding: 0.1rem 0.5rem;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
|
||||
.loadings.hide {
|
||||
opacity: 0;
|
||||
@ -392,20 +222,20 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.flag-icon:before {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.alias {
|
||||
margin-bottom: 1px;
|
||||
padding-left: 0px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.incon {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.incon .pure-imgw {
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.incon:nth-child(2) {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
@ -414,10 +244,13 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
border: 0;
|
||||
border-right: #d1dfed 1px solid;
|
||||
background-position: top;
|
||||
|
||||
}
|
||||
|
||||
.incon:nth-child(2) .tp {
|
||||
.incon .pure-imgw {
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.incon .tp {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
@ -430,34 +263,29 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
background: #525f7f;
|
||||
}
|
||||
|
||||
.incon:nth-child(3) {
|
||||
padding-left: 0px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.incon:nth-child(5),
|
||||
.incon:nth-child(6) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.cbi-section-table-cell {
|
||||
text-align: right;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ssr-button {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #525f7f;
|
||||
padding: 0 0 0 0;
|
||||
padding: 0 0.2rem 0 0;
|
||||
height: auto;
|
||||
line-height: 1.5em;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.ssr-button:hover,
|
||||
.ssr-button:focus,
|
||||
.ssr-button:active {
|
||||
color: #525f7f;
|
||||
|
||||
outline: 0;
|
||||
text-decoration: none;
|
||||
box-shadow: none;
|
||||
@ -472,37 +300,18 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
color: #fff !important;
|
||||
background-color: #337ab7 !important;
|
||||
border-color: #2e6da4 !important;
|
||||
background-image: none;
|
||||
float: right;
|
||||
margin-right: 18px;
|
||||
margin-top: 1rem;
|
||||
margin-top: .25rem !important;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.cbi-section-table-cell {
|
||||
position: relative;
|
||||
.cbi-button-check:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.host_con {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 70px;
|
||||
text-align: left;
|
||||
height: 22px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.host_ok {
|
||||
color: #fff;
|
||||
background: #2dce89;
|
||||
padding: 0.1rem 0.5rem;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
|
||||
.host_error {
|
||||
color: #fff;
|
||||
background: #f5365c;
|
||||
padding: 0.1rem 0.5rem;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
/** Bottom StatusBar **/
|
||||
|
||||
footer.mobile-hide {
|
||||
display: block;
|
||||
@ -537,6 +346,7 @@ footer.mobile-hide {
|
||||
|
||||
.status-bar .inner .status-info {
|
||||
font-weight: bold;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.status-bar .icon-con {
|
||||
@ -544,6 +354,8 @@ footer.mobile-hide {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/** Node choose panel **/
|
||||
|
||||
.choose_node .gap {
|
||||
margin: 0.5rem 1rem;
|
||||
position: relative;
|
||||
@ -553,66 +365,8 @@ footer.mobile-hide {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 2000px) {
|
||||
.pure-u-1-5 {
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1600px) {
|
||||
.pure-u-1-5 {
|
||||
width: 33.33333333%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
.pure-u-1-5 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.status .pure-u-1-5 {
|
||||
width: 33.333%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 700px) {
|
||||
.pure-u-1-4 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.pure-u-1-2 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pure-u-1-5 {
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.status .pure-u-1-5 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.cbi-button-add {
|
||||
position: fixed;
|
||||
padding: 0.3rem 0.5rem;
|
||||
z-index: 1000;
|
||||
width: 50px !important;
|
||||
height: 50px;
|
||||
bottom: 90px;
|
||||
right: 5px;
|
||||
font-size: 16px;
|
||||
border-radius: 50%;
|
||||
display: block;
|
||||
background-color: #fb6340 !important;
|
||||
border-color: #fb6340 !important;
|
||||
box-shadow: 0 0 1rem 0 rgba(136, 152, 170, .75);
|
||||
}
|
||||
|
||||
.choose_node .pure-u-1-2 {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
/** Subscribe panel **/
|
||||
|
||||
.modals-bg {
|
||||
position: fixed;
|
||||
@ -625,7 +379,7 @@ footer.mobile-hide {
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.modals-bg.hide{
|
||||
.modals-bg.hide {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
@ -651,7 +405,7 @@ footer.mobile-hide {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.modals.hide{
|
||||
.modals.hide {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transform: scale(0.5);
|
||||
@ -688,7 +442,27 @@ footer.mobile-hide {
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1024px) {
|
||||
@media screen and (max-width: 2000px) {
|
||||
.pure-u-1-5 {
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1600px) {
|
||||
.pure-u-1-5 {
|
||||
width: 33.33333333%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
.pure-u-1-5 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.status .pure-u-1-5 {
|
||||
width: 33.333%;
|
||||
}
|
||||
|
||||
.modals {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
@ -704,6 +478,45 @@ footer.mobile-hide {
|
||||
}
|
||||
|
||||
@media screen and (max-width: 700px) {
|
||||
.pure-u-1-4 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.pure-u-1-2 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pure-u-1-5 {
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.status .pure-u-1-5 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.cbi-button-add {
|
||||
position: fixed;
|
||||
padding: 0.3rem 0.5rem;
|
||||
z-index: 1000;
|
||||
width: 50px !important;
|
||||
height: 50px !important;
|
||||
bottom: 90px;
|
||||
color: #fff;
|
||||
right: 5px;
|
||||
font-size: 16px;
|
||||
border-radius: 50%;
|
||||
display: block;
|
||||
background-color: #fb6340 !important;
|
||||
border-color: #fb6340 !important;
|
||||
box-shadow: 0 0 1rem 0 rgba(136, 152, 170, .75);
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.choose_node .pure-u-1-2 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.modals-bg {
|
||||
position: fixed;
|
||||
z-index: 100000;
|
||||
@ -732,6 +545,14 @@ footer.mobile-hide {
|
||||
height: 2.5em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.p-in5 {
|
||||
padding-bottom: 3rem;
|
||||
}
|
||||
|
||||
.cbi-page-actions {
|
||||
padding-bottom: 4rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
@ -753,4 +574,5 @@ footer.mobile-hide {
|
||||
.ssr-button {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user