luci-app-vssr: bump to v1.15
This commit is contained in:
parent
575bfad2a8
commit
2a69e851fd
@ -1,8 +1,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-vssr
|
||||
PKG_VERSION:=1.14
|
||||
PKG_RELEASE:=20200824
|
||||
PKG_VERSION:=1.15
|
||||
PKG_RELEASE:=20200825
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
module("luci.controller.vssr", package.seeall)
|
||||
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/vssr") then return end
|
||||
|
||||
@ -47,7 +48,7 @@ function index()
|
||||
entry({"admin", "services", "vssr", "checkport"}, call("check_port")) -- 检测单个端口并返回Ping
|
||||
entry({"admin", "services", "vssr", "run"}, call("act_status")) -- 检测全局服务器状态
|
||||
entry({"admin", "services", "vssr", "change"}, call("change_node")) -- 切换节点
|
||||
--entry({"admin", "services", "vssr", "allserver"}, call("get_servers")) -- 获取所有节点Json
|
||||
entry({"admin", "services", "vssr", "allserver"}, call("get_servers")) -- 获取所有节点Json
|
||||
entry({"admin", "services", "vssr", "subscribe"}, call("get_subscribe")) -- 执行订阅
|
||||
entry({"admin", "services", "vssr", "flag"}, call("get_flag")) -- 获取节点国旗 iso code
|
||||
entry({"admin", "services", "vssr", "ip"}, call("check_ip")) -- 获取ip情况
|
||||
@ -56,37 +57,26 @@ end
|
||||
|
||||
-- 执行订阅
|
||||
function get_subscribe()
|
||||
|
||||
local cjson = require "luci.jsonc"
|
||||
local e = {}
|
||||
local name = "vssr"
|
||||
local uci = luci.model.uci.cursor()
|
||||
local auto_update = luci.http.formvalue("auto_update")
|
||||
local auto_update_time = luci.http.formvalue("auto_update_time")
|
||||
local proxy = luci.http.formvalue("proxy")
|
||||
local subscribe_url = luci.http.formvalue("subscribe_url")
|
||||
if subscribe_url ~= "[]" then
|
||||
local cmd1 = 'uci set vssr.@server_subscribe[0].auto_update="' ..
|
||||
auto_update .. '"'
|
||||
local cmd2 = 'uci set vssr.@server_subscribe[0].auto_update_time="' ..
|
||||
auto_update_time .. '"'
|
||||
local cmd3 = 'uci set vssr.@server_subscribe[0].proxy="' .. proxy .. '"'
|
||||
luci.sys.call('uci delete vssr.@server_subscribe[0].subscribe_url ')
|
||||
luci.sys.call(cmd1)
|
||||
luci.sys.call(cmd2)
|
||||
luci.sys.call(cmd3)
|
||||
for k, v in ipairs(cjson.parse(subscribe_url)) do
|
||||
luci.sys.call(
|
||||
'uci add_list vssr.@server_subscribe[0].subscribe_url="' .. v ..
|
||||
'"')
|
||||
end
|
||||
luci.sys.call('uci commit vssr')
|
||||
luci.sys.call(
|
||||
"nohup /usr/bin/lua /usr/share/vssr/subscribe.lua >/www/check_update.htm 2>/dev/null &")
|
||||
uci:delete(name,"@server_subscribe[0]",subscribe_url)
|
||||
uci:set(name,"@server_subscribe[0]","auto_update",auto_update)
|
||||
uci:set(name,"@server_subscribe[0]","auto_update_time",auto_update_time)
|
||||
uci:set(name,"@server_subscribe[0]","proxy",proxy)
|
||||
uci:set_list(name,"@server_subscribe[0]","subscribe_url",cjson.parse(subscribe_url))
|
||||
uci:commit(name)
|
||||
luci.sys.exec("nohup /usr/bin/lua /usr/share/vssr/subscribe.lua >/www/check_update.htm 2>/dev/null &")
|
||||
e.error = 0
|
||||
else
|
||||
e.error = 1
|
||||
end
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
|
||||
@ -110,12 +100,16 @@ function change_node()
|
||||
local e = {}
|
||||
local uci = luci.model.uci.cursor()
|
||||
local sid = luci.http.formvalue("set")
|
||||
local server = luci.http.formvalue("server")
|
||||
e.status = false
|
||||
e.sid = sid
|
||||
if sid ~= "" then
|
||||
uci:set("vssr", '@global[0]', 'global_server', sid)
|
||||
if sid ~= "" and server ~= "" then
|
||||
uci:set("vssr", '@global[0]', server..'_server', sid)
|
||||
if( server ~= "global" ) then
|
||||
uci:set("vssr", '@global[0]', 'v2ray_flow', "1")
|
||||
end
|
||||
uci:commit("vssr")
|
||||
luci.sys.exec("/etc/init.d/vssr reload")
|
||||
luci.sys.exec("/etc/init.d/vssr restart")
|
||||
e.status = true
|
||||
end
|
||||
luci.http.prepare_content("application/json")
|
||||
@ -128,14 +122,14 @@ function switch()
|
||||
local uci = luci.model.uci.cursor()
|
||||
local sid = luci.http.formvalue("node")
|
||||
local isSwitch = uci:get("vssr", sid, "switch_enable")
|
||||
local toSwitch = (isSwitch == "1") and "0" or "1"
|
||||
uci:set("vssr", sid, "switch_enable",toSwitch)
|
||||
uci:commit("vssr")
|
||||
if isSwitch == "1" then
|
||||
uci:set("vssr", sid, "switch_enable","0")
|
||||
e.switch = false
|
||||
else
|
||||
uci:set("vssr", sid, "switch_enable","1")
|
||||
e.switch = true
|
||||
end
|
||||
uci:commit("vssr")
|
||||
e.status = true
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
@ -146,22 +140,73 @@ function act_status()
|
||||
math.randomseed(os.time())
|
||||
local e = {}
|
||||
-- 全局服务器
|
||||
e.global = luci.sys.call(
|
||||
"busybox ps -w | grep vssr_t | grep -v grep >/dev/null") == 0
|
||||
e.global = luci.sys.call("busybox ps -w | grep vssr_t | grep -v grep >/dev/null") == 0
|
||||
-- 检测PDNSD状态
|
||||
e.pdnsd = luci.sys.call("pidof pdnsd >/dev/null") == 0
|
||||
-- 检测游戏模式状态
|
||||
e.game = luci.sys.call(
|
||||
"busybox ps -w | grep vssr_u | grep -v grep >/dev/null") == 0
|
||||
|
||||
e.game = luci.sys.call("busybox ps -w | grep vssr_u | grep -v grep >/dev/null") == 0
|
||||
-- 检测Socks5
|
||||
e.socks5 = luci.sys.call(
|
||||
"busybox ps -w | grep vssr_s | grep -v grep >/dev/null") == 0
|
||||
|
||||
e.socks5 = luci.sys.call("busybox ps -w | grep vssr_s | grep -v grep >/dev/null") == 0
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
-- 检测单个节点状态并返回连接速度
|
||||
function check_port()
|
||||
local sockets = require "socket"
|
||||
local vssr = require "vssrutil"
|
||||
local set = luci.http.formvalue("host")
|
||||
local port = luci.http.formvalue("port")
|
||||
local retstring = ""
|
||||
local t0 = sockets.gettime()
|
||||
ret = vssr.check_site(set, port)
|
||||
local t1 = sockets.gettime()
|
||||
retstring = tostring(ret) == "true" and "1" or "0"
|
||||
local tt = t1 - t0
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ret = retstring , used = math.floor(tt*1000 + 0.5)})
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- 获取当前代理状态 与节点ip
|
||||
function check_ip()
|
||||
local e = {}
|
||||
local d = {}
|
||||
local mm = require 'maxminddb'
|
||||
local vssr = require "vssrutil"
|
||||
local db = mm.open('/usr/share/vssr/GeoLite2-Country.mmdb')
|
||||
local ip = vssr.wget("http://api.ipify.org/")
|
||||
local res = db:lookup(ip)
|
||||
local port = 80
|
||||
d.flag = string.lower(res:get("country", "iso_code"))
|
||||
d.country = res:get("country", "names", "zh-CN")
|
||||
e.outboard = ip
|
||||
e.outboardip = d
|
||||
e.baidu = vssr.check_site("www.baidu.com",port)
|
||||
e.taobao = vssr.check_site("www.taobao.com",port)
|
||||
e.google = vssr.check_site("www.google.com",port)
|
||||
e.youtube = vssr.check_site("www.youtube.com",port)
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
|
||||
-- 获取节点国旗 iso code
|
||||
function get_flag()
|
||||
local e = {}
|
||||
local vssr = require "vssrutil"
|
||||
local host = luci.http.formvalue("host")
|
||||
local remark = luci.http.formvalue("remark")
|
||||
e.host = host
|
||||
e.flag = vssr.get_flag(remark,host)
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
|
||||
|
||||
-- 刷新检测文件
|
||||
function refresh_data()
|
||||
local set = luci.http.formvalue("set")
|
||||
@ -253,86 +298,4 @@ function refresh_data()
|
||||
end
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ret = retstring, retcount = icount})
|
||||
end
|
||||
|
||||
-- 检测单个节点状态并返回连接速度
|
||||
function check_port()
|
||||
|
||||
local sockets = require "socket"
|
||||
local set = luci.http.formvalue("host")
|
||||
local port = luci.http.formvalue("port")
|
||||
local retstring = ""
|
||||
local iret = 1
|
||||
iret = luci.sys.call(" ipset add ss_spec_wan_ac " .. set .. " 2>/dev/null")
|
||||
socket = nixio.socket("inet", "stream")
|
||||
socket:setopt("socket", "rcvtimeo", 2)
|
||||
socket:setopt("socket", "sndtimeo", 2)
|
||||
local t0 = sockets.gettime()
|
||||
ret = socket:connect(set, port)
|
||||
socket:close()
|
||||
local t1 = sockets.gettime()
|
||||
if tostring(ret) == "true" then
|
||||
retstring = "1"
|
||||
else
|
||||
retstring = "0"
|
||||
end
|
||||
if iret == 0 then
|
||||
luci.sys.call(" ipset del ss_spec_wan_ac " .. set)
|
||||
end
|
||||
|
||||
local tt = t1 - t0
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ret = retstring , used = math.floor(tt*1000 + 0.5)})
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- 检测 当前节点ip 和 网站访问情况
|
||||
function check_ip()
|
||||
|
||||
-- 获取当前的ip和国家
|
||||
local e = {}
|
||||
local d = {}
|
||||
local mm = require 'maxminddb'
|
||||
local db = mm.open('/usr/share/vssr/GeoLite2-Country.mmdb')
|
||||
local http = require "luci.sys"
|
||||
local ip = string.gsub(http.httpget("https://api.ip.sb/ip"), "\n", "")
|
||||
local res = db:lookup(ip)
|
||||
d.flag = string.lower(res:get("country", "iso_code"))
|
||||
d.country = res:get("country", "names", "zh-CN")
|
||||
e.outboard = ip
|
||||
e.outboardip = d
|
||||
|
||||
-- 检测国内通道
|
||||
e.baidu = false
|
||||
sret1 = luci.sys.call("/usr/bin/ssr-check www.baidu.com 80 3 1")
|
||||
if sret1 == 0 then e.baidu = true end
|
||||
|
||||
e.taobao = false
|
||||
sret2 = luci.sys.call("/usr/bin/ssr-check www.taobao.com 80 3 1")
|
||||
if sret2 == 0 then e.taobao = true end
|
||||
|
||||
-- 检测国外通道
|
||||
e.google = false
|
||||
sret3 = luci.sys.call("/usr/bin/ssr-check www.google.com 80 3 1")
|
||||
if sret3 == 0 then e.google = true end
|
||||
|
||||
e.youtube = false
|
||||
sret4 = luci.sys.call("/usr/bin/ssr-check www.youtube.com 80 3 1")
|
||||
if sret4 == 0 then e.youtube = true end
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
|
||||
-- 获取节点国旗 iso code
|
||||
function get_flag()
|
||||
local e = {}
|
||||
local host = luci.http.formvalue("host")
|
||||
local remark = luci.http.formvalue("remark")
|
||||
local cmd = '/usr/share/vssr/getflag.sh "' .. remark .. '" ' .. host
|
||||
e.host = host
|
||||
e.flag = luci.sys.exec(cmd)
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
end
|
||||
@ -6,8 +6,6 @@ local m, s, sec, o, kcp_enable
|
||||
local vssr = "vssr"
|
||||
local gfwmode=0
|
||||
|
||||
|
||||
|
||||
if nixio.fs.access("/etc/dnsmasq.ssr/gfw_list.conf") then
|
||||
gfwmode=1
|
||||
end
|
||||
@ -19,13 +17,30 @@ m = Map(vssr)
|
||||
m:section(SimpleSection).template = "vssr/status_top"
|
||||
|
||||
local server_table = {}
|
||||
|
||||
local tw_table = {}
|
||||
local tvb_table = {}
|
||||
uci:foreach(vssr, "servers", function(s)
|
||||
if s.alias then
|
||||
server_table[s[".name"]] = "[%s]:%s" %{string.upper(s.type), s.alias}
|
||||
elseif s.server and s.server_port then
|
||||
server_table[s[".name"]] = "[%s]:%s:%s" %{string.upper(s.type), s.server, s.server_port}
|
||||
end
|
||||
|
||||
if s.flag == "tw" then
|
||||
if s.alias then
|
||||
tw_table[s[".name"]] = "[%s]:%s" %{string.upper(s.type), s.alias}
|
||||
elseif s.server and s.server_port then
|
||||
tw_table[s[".name"]] = "[%s]:%s:%s" %{string.upper(s.type), s.server, s.server_port}
|
||||
end
|
||||
end
|
||||
|
||||
if s.flag == "hk" then
|
||||
if s.alias then
|
||||
tvb_table[s[".name"]] = "[%s]:%s" %{string.upper(s.type), s.alias}
|
||||
elseif s.server and s.server_port then
|
||||
tvb_table[s[".name"]] = "[%s]:%s:%s" %{string.upper(s.type), s.server, s.server_port}
|
||||
end
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
@ -34,8 +49,21 @@ for key,_ in pairs(server_table) do
|
||||
table.insert(key_table,key)
|
||||
end
|
||||
|
||||
table.sort(key_table)
|
||||
local key_table_tw = {}
|
||||
for key,_ in pairs(tw_table) do
|
||||
table.insert(key_table_tw,key)
|
||||
end
|
||||
|
||||
local key_table_tvb = {}
|
||||
for key,_ in pairs(tvb_table) do
|
||||
table.insert(key_table_tvb,key)
|
||||
end
|
||||
|
||||
|
||||
|
||||
table.sort(key_table)
|
||||
table.sort(key_table_tw)
|
||||
table.sort(key_table_tvb)
|
||||
local route_name = {"youtube_server","tw_video_server","netflix_server","disney_server","prime_server","tvb_server","custom_server"}
|
||||
local route_label = {"Youtube Proxy","TaiWan Video Proxy","Netflix Proxy","Diseny+ Proxy","Prime Video Proxy","TVB Video Proxy","Custom Proxy"}
|
||||
|
||||
@ -61,7 +89,13 @@ o.description = translate("When open v2ray routed,Apply may take more time.")
|
||||
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(key_table) do o:value(key,server_table[key]) end
|
||||
if(v == "tw_video_server") then
|
||||
for _,key in pairs(key_table_tw) do o:value(key,tw_table[key]) end
|
||||
elseif(v == "tvb_server") then
|
||||
for _,key in pairs(key_table_tvb) do o:value(key,tvb_table[key]) end
|
||||
else
|
||||
for _,key in pairs(key_table) do o:value(key,server_table[key]) end
|
||||
end
|
||||
o:depends("v2ray_flow", "1")
|
||||
o.default = "nil"
|
||||
end
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
|
||||
<script>
|
||||
|
||||
const CHECK_IP_URL = '<%=url([[admin]], [[services]], [[vssr]], [[ip]])%>';
|
||||
|
||||
var wW = $(window).width();
|
||||
|
||||
function resize() {
|
||||
@ -40,6 +40,7 @@
|
||||
}
|
||||
|
||||
function wirte_status(data) {
|
||||
|
||||
if (data.outboard) {
|
||||
json = data.outboardip;
|
||||
country = (json.flag == "tw") ? "中国 台湾" : json.country;
|
||||
@ -50,8 +51,10 @@
|
||||
data.taobao ? $(".i2").attr("src", VSSR_ASSETS + "img/site_icon_02.png") : $(".i2").attr("src", VSSR_ASSETS + "img/site_icon1_02.png");
|
||||
data.google ? $(".i3").attr("src", VSSR_ASSETS + "img/site_icon_03.png") : $(".i3").attr("src", VSSR_ASSETS + "img/site_icon1_03.png");
|
||||
data.youtube ? $(".i4").attr("src", VSSR_ASSETS + "img/site_icon_04.png") : $(".i4").attr("src", VSSR_ASSETS + "img/site_icon1_04.png");
|
||||
setTimeout(function () { $( "body").trigger( "iploaded", [ true ] ); }, 200);
|
||||
|
||||
}
|
||||
XHR.poll(5, CHECK_IP_URL, null,
|
||||
XHR.poll(10, CHECK_IP_URL, null,
|
||||
function (x, data) {
|
||||
wirte_status(data);
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<link rel="stylesheet" href="/luci-static/vssr/css/vssr.css?v=202000427-1">
|
||||
<link rel="stylesheet" href="/luci-static/vssr/css/vssr.css?v=202000825-1">
|
||||
|
||||
<script src="<%=media%>/js/jquery.min.js"></script>
|
||||
|
||||
<div class="pure-g status">
|
||||
@ -59,8 +60,9 @@
|
||||
const GAME_MODE = '<%:Game Mode%>';
|
||||
const RUNNING = '<%:Running%>';
|
||||
const NOT_RUNNING = '<%:Not Running%>';
|
||||
const CHECK_IP_URL = '<%=url([[admin]], [[services]], [[vssr]], [[ip]])%>';
|
||||
|
||||
XHR.poll(5, STATUS1_URL, null,
|
||||
XHR.poll(2, STATUS1_URL, null,
|
||||
function (x, data) {
|
||||
if (data) {
|
||||
if (data.global) {
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
<script type="text/javascript" src="/luci-static/vssr/emoji.js"></script>
|
||||
<fieldset class="cbi-section" id="cbi-apply-vssr1" style="display: none;">
|
||||
<span class="panel-title">正在切换节点</span>
|
||||
<img src="/luci-static/resources/icons/loading.gif" alt="载入中" style="vertical-align:middle">
|
||||
</fieldset>
|
||||
<script type="text/javascript" src="/luci-static/vssr/sweetalert.js"></script>
|
||||
<script type="text/javascript" src="/luci-static/vssr/polyfill.js"></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">总计
|
||||
@ -19,7 +18,7 @@
|
||||
-%>
|
||||
|
||||
<div class="pure-u-1-5">
|
||||
<div class="cbi-section-table-row " id="cbi-<%=self.config%>-<%=section%>">
|
||||
<div class="cbi-section-table-row " id="cbi-<%=self.config%>-<%=section%>" data-flag="<%=self.flag%>">
|
||||
<div class="loadings hide"></div>
|
||||
<div class="incon type flag-icon <%=self.flag%>" data-setction="<%=section%>">
|
||||
<img class="pure-imgw hidden" src="/luci-static/vssr/img/switch.png">
|
||||
@ -95,7 +94,10 @@
|
||||
const SWITCH_NODE_URL = '<%=luci.dispatcher.build_url("admin", "services", "vssr","switch")%>';
|
||||
|
||||
var servers = JSON.parse('<%= self.servers%>'.replace(/\t/g, ""));
|
||||
var iploaded = false;
|
||||
var ajaxArray = new Array();
|
||||
var currentCheckCount = 0;
|
||||
|
||||
|
||||
//渲染节点列表
|
||||
$.each(servers, function (i, val) {
|
||||
@ -104,6 +106,7 @@
|
||||
$(id).addClass("fast");
|
||||
}
|
||||
val.flag = (val.flag == undefined) ? "un" : val.flag;
|
||||
$(id).attr("data-flag",val.flag);
|
||||
$(id).find(".type .tp").text(val.type);
|
||||
$(id).find(".type").addClass("flag-icon-" + val.flag);
|
||||
$(id).find(".alias").text(val.alias);
|
||||
@ -119,19 +122,73 @@
|
||||
//转换节点名称的Emoji显示
|
||||
$(".alias").emoji();
|
||||
//适配方框的大小
|
||||
|
||||
$(".flag-icon").each(function (index, el) {
|
||||
if ($(el).height < 60) {
|
||||
$(el).parent.height(60);
|
||||
$(el).width(60)
|
||||
} else {
|
||||
$(el).width($(el).height());
|
||||
}
|
||||
});
|
||||
if ($(el).height < 60) {
|
||||
$(el).parent.height(60);
|
||||
$(el).width(60)
|
||||
} else {
|
||||
$(el).width($(el).height());
|
||||
}
|
||||
});
|
||||
|
||||
//切换节点
|
||||
function apply_node(node) {
|
||||
$("#cbi-apply-vssr1").show(); //显示应用中
|
||||
$.each(ajaxArray, function (n, value) { value.abort(); }) //中断所有的ajax请求
|
||||
$.get(CHANGE_NODE_URL, { set: node },
|
||||
//$("#cbi-apply-vssr1").show(); //显示应用中
|
||||
|
||||
var $html = "";
|
||||
$html +='<div class="pure-g choose_node">';
|
||||
$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="youtube" data-node="'+node+'"> Youtube </button></div></div>';
|
||||
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"){
|
||||
$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({
|
||||
title: '请选择应用于',
|
||||
html:$html,
|
||||
focusConfirm: false,
|
||||
confirmButtonText:'关闭',
|
||||
onRender: (toast) => {
|
||||
$(".change-node").click(function(){
|
||||
var dataServer = $(this).attr("data-server");
|
||||
XHR.halt();
|
||||
$.each(ajaxArray, function (n, value) { value.abort(); }) //中断所有的ajax请求
|
||||
Swal.fire({
|
||||
title: '正在应用中',
|
||||
allowOutsideClick:false,
|
||||
onBeforeOpen: () => {
|
||||
Swal.showLoading()
|
||||
}
|
||||
})
|
||||
$.get(CHANGE_NODE_URL, { set: node,server:dataServer },
|
||||
function (data, status) {
|
||||
$("#cbi-apply-vssr1").hide(); //隐藏应用中
|
||||
if (data.status) {
|
||||
var id = '#cbi-<%=self.config%>-' + node;
|
||||
if(dataServer == "global"){
|
||||
$(".cbi-section-table-row").removeClass("fast");
|
||||
$(id).addClass("fast");
|
||||
}
|
||||
|
||||
Swal.close();
|
||||
XHR.run();
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
/*$.get(CHANGE_NODE_URL, { set: node },
|
||||
function (data, status) {
|
||||
$("#cbi-apply-vssr1").hide(); //隐藏应用中
|
||||
if (data.status) {
|
||||
@ -139,8 +196,10 @@
|
||||
$(".cbi-section-table-row").removeClass("fast");
|
||||
$(id).addClass("fast");
|
||||
}
|
||||
});
|
||||
});*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
//设定自动切换台
|
||||
$(".incon").click(function () {
|
||||
@ -163,12 +222,18 @@
|
||||
//检测所有节点延迟
|
||||
function check() {
|
||||
$(".host_con").html("");
|
||||
$.each(ajaxArray, function (n, value) { value.abort(); }) //中断所有的ajax请求
|
||||
ajaxArray = [];
|
||||
currentCheckCount = 0;
|
||||
XHR.halt();
|
||||
$(".pure-u-1-5").each(function () {
|
||||
host = $(this).find(".cbi-section-table-row ").attr("server");
|
||||
port = $(this).find(".cbi-section-table-row ").attr("server_port");
|
||||
$(".host_con").text("");
|
||||
check_port(host, port, this);
|
||||
if(host != undefined){
|
||||
check_port(host, port, this);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@ -177,6 +242,7 @@
|
||||
$.ajaxSettings.async = true;
|
||||
var axhr = $.get(CHECK_PING_URL, { host: hosts, port: ports },
|
||||
function (data, status) {
|
||||
currentCheckCount ++
|
||||
var host_con = $(target).find(".host_con");
|
||||
host_con.removeClass("fast");
|
||||
host_con.removeClass("middle");
|
||||
@ -200,12 +266,24 @@
|
||||
host_con.addClass("nopass");
|
||||
host_con.text("Error");
|
||||
}
|
||||
|
||||
if(currentCheckCount == ajaxArray.length){
|
||||
XHR.run();
|
||||
}
|
||||
});
|
||||
ajaxArray.push(axhr);
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
setTimeout(function () { check(); }, 500); //延迟500MS开始检测
|
||||
//setTimeout(function () { check(); }, 500); //延迟500MS开始检测
|
||||
|
||||
$( "body" ).on( "iploaded", function( event, param1 ) {
|
||||
if(!iploaded){
|
||||
iploaded = true;
|
||||
check();
|
||||
}
|
||||
});
|
||||
|
||||
$(".cbi-page-actions").hide(); //隐藏底部保存提交按钮
|
||||
$(".cbi-button-check").click(function () {
|
||||
check();
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
api.ip.sb
|
||||
api.ipify.org
|
||||
fast.com
|
||||
netflix.ca
|
||||
netflix.com
|
||||
|
||||
136
package/ctcgfw/luci-app-vssr/root/usr/share/lua/vssrutil.lua
Normal file
136
package/ctcgfw/luci-app-vssr/root/usr/share/lua/vssrutil.lua
Normal file
@ -0,0 +1,136 @@
|
||||
#!/usr/bin/lua
|
||||
|
||||
------------------------------------------------
|
||||
-- This file is converter ip to country iso code
|
||||
-- @author Jerryk <jerrykuku@qq.com>
|
||||
------------------------------------------------
|
||||
local _M = {}
|
||||
|
||||
-- Get country iso code with remark or host
|
||||
-- Return String:iso_code
|
||||
function _M.get_flag(remark, host)
|
||||
local nixio = require "nixio"
|
||||
local ip = require "luci.ip"
|
||||
local mm = require 'maxminddb'
|
||||
local db = mm.open('/usr/share/vssr/GeoLite2-Country.mmdb')
|
||||
local iso_table = {
|
||||
"AC", "AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AQ", "AR", "AS",
|
||||
"AT", "AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH",
|
||||
"BI", "BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BV", "BW",
|
||||
"BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM",
|
||||
"CN", "CO", "CP", "CR", "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DG",
|
||||
"DJ", "DK", "DM", "DO", "DZ", "EA", "EC", "EE", "EG", "EH", "ER", "ES",
|
||||
"ET", "EU", "FI", "FJ", "FK", "FM", "FO", "FR", "GA", "GB", "GD", "GE",
|
||||
"GF", "GG", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT",
|
||||
"GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "IC", "ID", "IE",
|
||||
"IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "JP",
|
||||
"KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA",
|
||||
"LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC",
|
||||
"MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ",
|
||||
"MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE",
|
||||
"NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE",
|
||||
"PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY",
|
||||
"QA", "RE", "RO", "RS", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG",
|
||||
"SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SV",
|
||||
"SX", "SY", "SZ", "TA", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL",
|
||||
"TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "UN",
|
||||
"US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", "WS",
|
||||
"XK", "YE", "YT", "ZA", "ZM", "ZW", "US", "HK", "TW", "JP", "GB", "GB",
|
||||
"DE", "FR", "IN", "TR", "SG", "KR", "RU", "IE"
|
||||
}
|
||||
|
||||
local emoji_table = {
|
||||
"🇦🇨", "🇦🇩", "🇦🇪", "🇦🇫", "🇦🇬", "🇦🇮",
|
||||
"🇦🇱", "🇦🇲", "🇦🇴", "🇦🇶", "🇦🇷", "🇦🇸",
|
||||
"🇦🇹", "🇦🇺", "🇦🇼", "🇦🇽", "🇦🇿", "🇧🇦",
|
||||
"🇧🇧", "🇧🇩", "🇧🇪", "🇧🇫", "🇧🇬", "🇧🇭",
|
||||
"🇧🇮", "🇧🇯", "🇧🇱", "🇧🇲", "🇧🇳", "🇧🇴",
|
||||
"🇧🇶", "🇧🇷", "🇧🇸", "🇧🇹", "🇧🇻", "🇧🇼",
|
||||
"🇧🇾", "🇧🇿", "🇨🇦", "🇨🇨", "🇨🇩", "🇨🇫",
|
||||
"🇨🇬", "🇨🇭", "🇨🇮", "🇨🇰", "🇨🇱", "🇨🇲",
|
||||
"🇨🇳", "🇨🇴", "🇨🇵", "🇨🇷", "🇨🇺", "🇨🇻",
|
||||
"🇨🇼", "🇨🇽", "🇨🇾", "🇨🇿", "🇩🇪", "🇩🇬",
|
||||
"🇩🇯", "🇩🇰", "🇩🇲", "🇩🇴", "🇩🇿", "🇪🇦",
|
||||
"🇪🇨", "🇪🇪", "🇪🇬", "🇪🇭", "🇪🇷", "🇪🇸",
|
||||
"🇪🇹", "🇪🇺", "🇫🇮", "🇫🇯", "🇫🇰", "🇫🇲",
|
||||
"🇫🇴", "🇫🇷", "🇬🇦", "🇬🇧", "🇬🇩", "🇬🇪",
|
||||
"🇬🇫", "🇬🇬", "🇬🇭", "🇬🇮", "🇬🇱", "🇬🇲",
|
||||
"🇬🇳", "🇬🇵", "🇬🇶", "🇬🇷", "🇬🇸", "🇬🇹",
|
||||
"🇬🇺", "🇬🇼", "🇬🇾", "🇭🇰", "🇭🇲", "🇭🇳",
|
||||
"🇭🇷", "🇭🇹", "🇭🇺", "🇮🇨", "🇮🇩", "🇮🇪",
|
||||
"🇮🇱", "🇮🇲", "🇮🇳", "🇮🇴", "🇮🇶", "🇮🇷",
|
||||
"🇮🇸", "🇮🇹", "🇯🇪", "🇯🇲", "🇯🇴", "🇯🇵",
|
||||
"🇰🇪", "🇰🇬", "🇰🇭", "🇰🇮", "🇰🇲", "🇰🇳",
|
||||
"🇰🇵", "🇰🇷", "🇰🇼", "🇰🇾", "🇰🇿", "🇱🇦",
|
||||
"🇱🇧", "🇱🇨", "🇱🇮", "🇱🇰", "🇱🇷", "🇱🇸",
|
||||
"🇱🇹", "🇱🇺", "🇱🇻", "🇱🇾", "🇲🇦", "🇲🇨",
|
||||
"🇲🇩", "🇲🇪", "🇲🇫", "🇲🇬", "🇲🇭", "🇲🇰",
|
||||
"🇲🇱", "🇲🇲", "🇲🇳", "🇲🇴", "🇲🇵", "🇲🇶",
|
||||
"🇲🇷", "🇲🇸", "🇲🇹", "🇲🇺", "🇲🇻", "🇲🇼",
|
||||
"🇲🇽", "🇲🇾", "🇲🇿", "🇳🇦", "🇳🇨", "🇳🇪",
|
||||
"🇳🇫", "🇳🇬", "🇳🇮", "🇳🇱", "🇳🇴", "🇳🇵",
|
||||
"🇳🇷", "🇳🇺", "🇳🇿", "🇴🇲", "🇵🇦", "🇵🇪",
|
||||
"🇵🇫", "🇵🇬", "🇵🇭", "🇵🇰", "🇵🇱", "🇵🇲",
|
||||
"🇵🇳", "🇵🇷", "🇵🇸", "🇵🇹", "🇵🇼", "🇵🇾",
|
||||
"🇶🇦", "🇷🇪", "🇷🇴", "🇷🇸", "🇷🇺", "🇷🇼",
|
||||
"🇸🇦", "🇸🇧", "🇸🇨", "🇸🇩", "🇸🇪", "🇸🇬",
|
||||
"🇸🇭", "🇸🇮", "🇸🇯", "🇸🇰", "🇸🇱", "🇸🇲",
|
||||
"🇸🇳", "🇸🇴", "🇸🇷", "🇸🇸", "🇸🇹", "🇸🇻",
|
||||
"🇸🇽", "🇸🇾", "🇸🇿", "🇹🇦", "🇹🇨", "🇹🇩",
|
||||
"🇹🇫", "🇹🇬", "🇹🇭", "🇹🇯", "🇹🇰", "🇹🇱",
|
||||
"🇹🇲", "🇹🇳", "🇹🇴", "🇹🇷", "🇹🇹", "🇹🇻",
|
||||
"🇹🇼", "🇹🇿", "🇺🇦", "🇺🇬", "🇺🇲", "🇺🇳",
|
||||
"🇺🇸", "🇺🇾", "🇺🇿", "🇻🇦", "🇻🇨", "🇻🇪",
|
||||
"🇻🇬", "🇻🇮", "🇻🇳", "🇻🇺", "🇼🇫", "🇼🇸",
|
||||
"🇽🇰", "🇾🇪", "🇾🇹", "🇿🇦", "🇿🇲", "🇿🇼",
|
||||
"美国", "香港", "台湾", "日本", "英国", "UK", "德国",
|
||||
"法国", "印度", "土耳其", "新加坡", "韩国", "俄罗斯",
|
||||
"爱尔兰"
|
||||
}
|
||||
|
||||
local iso_code = nil
|
||||
if (remark ~= nil) then
|
||||
for i, v in pairs(emoji_table) do
|
||||
if (string.find(remark, v)) then
|
||||
iso_code = string.lower(iso_table[i])
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (iso_code == nil) then
|
||||
local ret = nixio.getaddrinfo(host, "any")
|
||||
local hostip = ret[1].address
|
||||
local res = db:lookup(hostip)
|
||||
iso_code = string.lower(res:get("country", "iso_code"))
|
||||
end
|
||||
return string.gsub(iso_code, '\n', '')
|
||||
end
|
||||
|
||||
-- Get status of conncet to any site with host and port
|
||||
-- Return String:true or nil
|
||||
function _M.check_site(host, port)
|
||||
local nixio = require "nixio"
|
||||
local socket = nixio.socket("inet", "stream")
|
||||
socket:setopt("socket", "rcvtimeo", 2)
|
||||
socket:setopt("socket", "sndtimeo", 2)
|
||||
local ret = socket:connect(host, port)
|
||||
socket:close()
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
function _M.trim(text)
|
||||
if not text or text == "" then
|
||||
return ""
|
||||
end
|
||||
return (string.gsub(text, "^%s*(.-)%s*$", "%1"))
|
||||
end
|
||||
|
||||
function _M.wget(url)
|
||||
local stdout = luci.sys.exec('wget-ssl -q --user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36" --no-check-certificate -t 3 -T 10 -O- "' .. url .. '"')
|
||||
return _M.trim(stdout)
|
||||
end
|
||||
|
||||
return _M
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Copyright (C) 2019 Jerryk <jerrykuku@qq.com>
|
||||
lua=/usr/bin/lua
|
||||
name="$1"
|
||||
host=$2
|
||||
code=''
|
||||
iso_array=(AC AD AE AF AG AI AL AM AO AQ AR AS AT AU AW AX AZ BA BB BD BE BF BG BH BI BJ BL BM BN BO BQ BR BS BT BV BW BY BZ CA CC CD CF CG CH CI CK CL CM CN CO CP CR CU CV CW CX CY CZ DE DG DJ DK DM DO DZ EA EC EE EG EH ER ES ET EU FI FJ FK FM FO FR GA GB GD GE GF GG GH GI GL GM GN GP GQ GR GS GT GU GW GY HK HM HN HR HT HU IC ID IE IL IM IN IO IQ IR IS IT JE JM JO JP KE KG KH KI KM KN KP KR KW KY KZ LA LB LC LI LK LR LS LT LU LV LY MA MC MD ME MF MG MH MK ML MM MN MO MP MQ MR MS MT MU MV MW MX MY MZ NA NC NE NF NG NI NL NO NP NR NU NZ OM PA PE PF PG PH PK PL PM PN PR PS PT PW PY QA RE RO RS RU RW SA SB SC SD SE SG SH SI SJ SK SL SM SN SO SR SS ST SV SX SY SZ TA TC TD TF TG TH TJ TK TL TM TN TO TR TT TV TW TZ UA UG UM UN US UY UZ VA VC VE VG VI VN VU WF WS XK YE YT ZA ZM ZW US HK TW JP GB GB DE FR IN TR SG KR RU IE)
|
||||
|
||||
emoji_array=(🇦🇨 🇦🇩 🇦🇪 🇦🇫 🇦🇬 🇦🇮 🇦🇱 🇦🇲 🇦🇴 🇦🇶 🇦🇷 🇦🇸 🇦🇹 🇦🇺 🇦🇼 🇦🇽 🇦🇿 🇧🇦 🇧🇧 🇧🇩 🇧🇪 🇧🇫 🇧🇬 🇧🇭 🇧🇮 🇧🇯 🇧🇱 🇧🇲 🇧🇳 🇧🇴 🇧🇶 🇧🇷 🇧🇸 🇧🇹 🇧🇻 🇧🇼 🇧🇾 🇧🇿 🇨🇦 🇨🇨 🇨🇩 🇨🇫 🇨🇬 🇨🇭 🇨🇮 🇨🇰 🇨🇱 🇨🇲 🇨🇳 🇨🇴 🇨🇵 🇨🇷 🇨🇺 🇨🇻 🇨🇼 🇨🇽 🇨🇾 🇨🇿 🇩🇪 🇩🇬 🇩🇯 🇩🇰 🇩🇲 🇩🇴 🇩🇿 🇪🇦 🇪🇨 🇪🇪 🇪🇬 🇪🇭 🇪🇷 🇪🇸 🇪🇹 🇪🇺 🇫🇮 🇫🇯 🇫🇰 🇫🇲 🇫🇴 🇫🇷 🇬🇦 🇬🇧 🇬🇩 🇬🇪 🇬🇫 🇬🇬 🇬🇭 🇬🇮 🇬🇱 🇬🇲 🇬🇳 🇬🇵 🇬🇶 🇬🇷 🇬🇸 🇬🇹 🇬🇺 🇬🇼 🇬🇾 🇭🇰 🇭🇲 🇭🇳 🇭🇷 🇭🇹 🇭🇺 🇮🇨 🇮🇩 🇮🇪 🇮🇱 🇮🇲 🇮🇳 🇮🇴 🇮🇶 🇮🇷 🇮🇸 🇮🇹 🇯🇪 🇯🇲 🇯🇴 🇯🇵 🇰🇪 🇰🇬 🇰🇭 🇰🇮 🇰🇲 🇰🇳 🇰🇵 🇰🇷 🇰🇼 🇰🇾 🇰🇿 🇱🇦 🇱🇧 🇱🇨 🇱🇮 🇱🇰 🇱🇷 🇱🇸 🇱🇹 🇱🇺 🇱🇻 🇱🇾 🇲🇦 🇲🇨 🇲🇩 🇲🇪 🇲🇫 🇲🇬 🇲🇭 🇲🇰 🇲🇱 🇲🇲 🇲🇳 🇲🇴 🇲🇵 🇲🇶 🇲🇷 🇲🇸 🇲🇹 🇲🇺 🇲🇻 🇲🇼 🇲🇽 🇲🇾 🇲🇿 🇳🇦 🇳🇨 🇳🇪 🇳🇫 🇳🇬 🇳🇮 🇳🇱 🇳🇴 🇳🇵 🇳🇷 🇳🇺 🇳🇿 🇴🇲 🇵🇦 🇵🇪 🇵🇫 🇵🇬 🇵🇭 🇵🇰 🇵🇱 🇵🇲 🇵🇳 🇵🇷 🇵🇸 🇵🇹 🇵🇼 🇵🇾 🇶🇦 🇷🇪 🇷🇴 🇷🇸 🇷🇺 🇷🇼 🇸🇦 🇸🇧 🇸🇨 🇸🇩 🇸🇪 🇸🇬 🇸🇭 🇸🇮 🇸🇯 🇸🇰 🇸🇱 🇸🇲 🇸🇳 🇸🇴 🇸🇷 🇸🇸 🇸🇹 🇸🇻 🇸🇽 🇸🇾 🇸🇿 🇹🇦 🇹🇨 🇹🇩 🇹🇫 🇹🇬 🇹🇭 🇹🇯 🇹🇰 🇹🇱 🇹🇲 🇹🇳 🇹🇴 🇹🇷 🇹🇹 🇹🇻 🇹🇼 🇹🇿 🇺🇦 🇺🇬 🇺🇲 🇺🇳 🇺🇸 🇺🇾 🇺🇿 🇻🇦 🇻🇨 🇻🇪 🇻🇬 🇻🇮 🇻🇳 🇻🇺 🇼🇫 🇼🇸 🇽🇰 🇾🇪 🇾🇹 🇿🇦 🇿🇲 🇿🇼 美国 香港 台湾 日本 英国 UK 德国 法国 印度 土耳其 新加坡 韩国 俄罗斯 爱尔兰)
|
||||
|
||||
|
||||
for i in "${!emoji_array[@]}"; do
|
||||
if [[ $name == *${emoji_array[$i]}* ]]; then
|
||||
code=${iso_array[$i]}
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ! -z $code ]; then
|
||||
echo $code | tr "[A-Z]" "[a-z]"
|
||||
else
|
||||
|
||||
|
||||
if echo $host | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" >/dev/null; then
|
||||
hostip=${host}
|
||||
elif [ "$host" != "${host#*:[0-9a-fA-F]}" ]; then
|
||||
hostip=${host}
|
||||
else
|
||||
hostip=$(nslookup ${host} | grep 'Address 1' | sed 's/Address 1: //g')
|
||||
if echo $hostip | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" >/dev/null; then
|
||||
hostip=${hostip}
|
||||
else
|
||||
hostip=$(cat /etc/ssr_ip)
|
||||
fi
|
||||
fi
|
||||
lua /usr/share/vssr/iso_code.lua $hostip
|
||||
fi
|
||||
@ -1,10 +0,0 @@
|
||||
#!/usr/bin/lua
|
||||
------------------------------------------------
|
||||
-- This file is converter ip to country iso code
|
||||
-- @author Jerryk <jerrykuku@qq.com>
|
||||
------------------------------------------------
|
||||
|
||||
local mm = require 'maxminddb'
|
||||
local db = mm.open('/usr/share/vssr/GeoLite2-Country.mmdb')
|
||||
local res = db:lookup(arg[1])
|
||||
print(string.lower(res:get("country", "iso_code")))
|
||||
@ -9,6 +9,7 @@ require 'luci.util'
|
||||
require 'luci.jsonc'
|
||||
require 'luci.sys'
|
||||
|
||||
|
||||
-- these global functions are accessed all the time by the event handler
|
||||
-- so caching them is worth the effort
|
||||
local luci = luci
|
||||
@ -261,19 +262,15 @@ local function processData(szType, content)
|
||||
result.hashkey = md5(jsonStringify(result))
|
||||
result.alias = alias
|
||||
result.switch_enable = switch_enable
|
||||
|
||||
local flag = luci.sys.exec('/usr/share/' .. name .. '/getflag.sh "' ..
|
||||
result.alias .. '" ' .. result.server)
|
||||
result.flag = string.gsub(flag, '\n', '')
|
||||
local vssrutil = require "vssrutil"
|
||||
result.flag = vssrutil.get_flag(result.alias,result.server)
|
||||
|
||||
return result
|
||||
end
|
||||
-- wget
|
||||
local function wget(url)
|
||||
local stdout = luci.sys.exec(
|
||||
'wget-ssl --user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36" --no-check-certificate -t 3 -T 10 -O- "' ..
|
||||
url .. '"')
|
||||
return trim(stdout)
|
||||
local stdout = luci.sys.exec('wget-ssl -q --user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36" --no-check-certificate -t 3 -T 10 -O- "' .. url .. '"')
|
||||
return trim(stdout)
|
||||
end
|
||||
|
||||
local execute = function()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
@import url("flag-icon.min.css");
|
||||
|
||||
@import url("sweetalert2.css?v=2");
|
||||
/*!
|
||||
Pure v1.0.1
|
||||
Copyright 2013 Yahoo!
|
||||
@ -225,7 +225,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
}
|
||||
|
||||
.pure-u-23-24 {
|
||||
width: 95.8333%
|
||||
width: 95.8333%
|
||||
}
|
||||
|
||||
.pure-u-1,
|
||||
@ -251,7 +251,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
overflow-y: hidden;
|
||||
border: 1px solid rgba(0, 0, 0, .05);
|
||||
border-radius: .375rem;
|
||||
background-color: #fff;
|
||||
background-color:#fff;
|
||||
box-shadow: 0 0 2rem 0 rgba(136, 152, 170, .15);
|
||||
}
|
||||
|
||||
@ -372,23 +372,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
color: #fb6340;
|
||||
}
|
||||
|
||||
.loadings {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
border-radius: .5rem;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 30px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
|
||||
.loadings.hide {
|
||||
opacity: 0;
|
||||
@ -415,7 +399,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 61px;
|
||||
width: 64px;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
border-right: #d1dfed 1px solid;
|
||||
@ -543,6 +527,13 @@ footer.mobile-hide{
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.choose_node .gap{
|
||||
margin:0.5rem 1rem;
|
||||
position:relative;
|
||||
}
|
||||
.choose_node .gap .cbi-button{
|
||||
width:100% !important;
|
||||
}
|
||||
@media screen and (max-width: 2000px) {
|
||||
.pure-u-1-5 {
|
||||
width: 25%;
|
||||
@ -598,6 +589,9 @@ footer.mobile-hide{
|
||||
border-color: #fb6340 !important;
|
||||
box-shadow: 0 0 1rem 0 rgba(136, 152, 170, .75);
|
||||
}
|
||||
.choose_node .pure-u-1-2{
|
||||
width:50%;
|
||||
}
|
||||
}
|
||||
|
||||
.modals-bg {
|
||||
@ -697,4 +691,24 @@ footer.mobile-hide{
|
||||
height: 2.5em;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.block {
|
||||
background-color: #3c3c3c !important;
|
||||
box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
.cbi-section-table-row {
|
||||
color: #ccc;
|
||||
background-color: #3c3c3c !important;
|
||||
box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
.incon:nth-child(2) {
|
||||
border-right: #1e1e1e 1px solid;
|
||||
}
|
||||
|
||||
.ssr-button {
|
||||
color: #ccc;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,301 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
|
||||
typeof define === 'function' && define.amd ? define(factory) :
|
||||
(factory());
|
||||
}(this, (function () { 'use strict';
|
||||
|
||||
/**
|
||||
* @this {Promise}
|
||||
*/
|
||||
function finallyConstructor(callback) {
|
||||
var constructor = this.constructor;
|
||||
return this.then(
|
||||
function(value) {
|
||||
// @ts-ignore
|
||||
return constructor.resolve(callback()).then(function() {
|
||||
return value;
|
||||
});
|
||||
},
|
||||
function(reason) {
|
||||
// @ts-ignore
|
||||
return constructor.resolve(callback()).then(function() {
|
||||
// @ts-ignore
|
||||
return constructor.reject(reason);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Store setTimeout reference so promise-polyfill will be unaffected by
|
||||
// other code modifying setTimeout (like sinon.useFakeTimers())
|
||||
var setTimeoutFunc = setTimeout;
|
||||
|
||||
function isArray(x) {
|
||||
return Boolean(x && typeof x.length !== 'undefined');
|
||||
}
|
||||
|
||||
function noop() {}
|
||||
|
||||
// Polyfill for Function.prototype.bind
|
||||
function bind(fn, thisArg) {
|
||||
return function() {
|
||||
fn.apply(thisArg, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Function} fn
|
||||
*/
|
||||
function Promise(fn) {
|
||||
if (!(this instanceof Promise))
|
||||
throw new TypeError('Promises must be constructed via new');
|
||||
if (typeof fn !== 'function') throw new TypeError('not a function');
|
||||
/** @type {!number} */
|
||||
this._state = 0;
|
||||
/** @type {!boolean} */
|
||||
this._handled = false;
|
||||
/** @type {Promise|undefined} */
|
||||
this._value = undefined;
|
||||
/** @type {!Array<!Function>} */
|
||||
this._deferreds = [];
|
||||
|
||||
doResolve(fn, this);
|
||||
}
|
||||
|
||||
function handle(self, deferred) {
|
||||
while (self._state === 3) {
|
||||
self = self._value;
|
||||
}
|
||||
if (self._state === 0) {
|
||||
self._deferreds.push(deferred);
|
||||
return;
|
||||
}
|
||||
self._handled = true;
|
||||
Promise._immediateFn(function() {
|
||||
var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
|
||||
if (cb === null) {
|
||||
(self._state === 1 ? resolve : reject)(deferred.promise, self._value);
|
||||
return;
|
||||
}
|
||||
var ret;
|
||||
try {
|
||||
ret = cb(self._value);
|
||||
} catch (e) {
|
||||
reject(deferred.promise, e);
|
||||
return;
|
||||
}
|
||||
resolve(deferred.promise, ret);
|
||||
});
|
||||
}
|
||||
|
||||
function resolve(self, newValue) {
|
||||
try {
|
||||
// Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
|
||||
if (newValue === self)
|
||||
throw new TypeError('A promise cannot be resolved with itself.');
|
||||
if (
|
||||
newValue &&
|
||||
(typeof newValue === 'object' || typeof newValue === 'function')
|
||||
) {
|
||||
var then = newValue.then;
|
||||
if (newValue instanceof Promise) {
|
||||
self._state = 3;
|
||||
self._value = newValue;
|
||||
finale(self);
|
||||
return;
|
||||
} else if (typeof then === 'function') {
|
||||
doResolve(bind(then, newValue), self);
|
||||
return;
|
||||
}
|
||||
}
|
||||
self._state = 1;
|
||||
self._value = newValue;
|
||||
finale(self);
|
||||
} catch (e) {
|
||||
reject(self, e);
|
||||
}
|
||||
}
|
||||
|
||||
function reject(self, newValue) {
|
||||
self._state = 2;
|
||||
self._value = newValue;
|
||||
finale(self);
|
||||
}
|
||||
|
||||
function finale(self) {
|
||||
if (self._state === 2 && self._deferreds.length === 0) {
|
||||
Promise._immediateFn(function() {
|
||||
if (!self._handled) {
|
||||
Promise._unhandledRejectionFn(self._value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (var i = 0, len = self._deferreds.length; i < len; i++) {
|
||||
handle(self, self._deferreds[i]);
|
||||
}
|
||||
self._deferreds = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
function Handler(onFulfilled, onRejected, promise) {
|
||||
this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
|
||||
this.onRejected = typeof onRejected === 'function' ? onRejected : null;
|
||||
this.promise = promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a potentially misbehaving resolver function and make sure
|
||||
* onFulfilled and onRejected are only called once.
|
||||
*
|
||||
* Makes no guarantees about asynchrony.
|
||||
*/
|
||||
function doResolve(fn, self) {
|
||||
var done = false;
|
||||
try {
|
||||
fn(
|
||||
function(value) {
|
||||
if (done) return;
|
||||
done = true;
|
||||
resolve(self, value);
|
||||
},
|
||||
function(reason) {
|
||||
if (done) return;
|
||||
done = true;
|
||||
reject(self, reason);
|
||||
}
|
||||
);
|
||||
} catch (ex) {
|
||||
if (done) return;
|
||||
done = true;
|
||||
reject(self, ex);
|
||||
}
|
||||
}
|
||||
|
||||
Promise.prototype['catch'] = function(onRejected) {
|
||||
return this.then(null, onRejected);
|
||||
};
|
||||
|
||||
Promise.prototype.then = function(onFulfilled, onRejected) {
|
||||
// @ts-ignore
|
||||
var prom = new this.constructor(noop);
|
||||
|
||||
handle(this, new Handler(onFulfilled, onRejected, prom));
|
||||
return prom;
|
||||
};
|
||||
|
||||
Promise.prototype['finally'] = finallyConstructor;
|
||||
|
||||
Promise.all = function(arr) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (!isArray(arr)) {
|
||||
return reject(new TypeError('Promise.all accepts an array'));
|
||||
}
|
||||
|
||||
var args = Array.prototype.slice.call(arr);
|
||||
if (args.length === 0) return resolve([]);
|
||||
var remaining = args.length;
|
||||
|
||||
function res(i, val) {
|
||||
try {
|
||||
if (val && (typeof val === 'object' || typeof val === 'function')) {
|
||||
var then = val.then;
|
||||
if (typeof then === 'function') {
|
||||
then.call(
|
||||
val,
|
||||
function(val) {
|
||||
res(i, val);
|
||||
},
|
||||
reject
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
args[i] = val;
|
||||
if (--remaining === 0) {
|
||||
resolve(args);
|
||||
}
|
||||
} catch (ex) {
|
||||
reject(ex);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
res(i, args[i]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Promise.resolve = function(value) {
|
||||
if (value && typeof value === 'object' && value.constructor === Promise) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return new Promise(function(resolve) {
|
||||
resolve(value);
|
||||
});
|
||||
};
|
||||
|
||||
Promise.reject = function(value) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
reject(value);
|
||||
});
|
||||
};
|
||||
|
||||
Promise.race = function(arr) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (!isArray(arr)) {
|
||||
return reject(new TypeError('Promise.race accepts an array'));
|
||||
}
|
||||
|
||||
for (var i = 0, len = arr.length; i < len; i++) {
|
||||
Promise.resolve(arr[i]).then(resolve, reject);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Use polyfill for setImmediate for performance gains
|
||||
Promise._immediateFn =
|
||||
// @ts-ignore
|
||||
(typeof setImmediate === 'function' &&
|
||||
function(fn) {
|
||||
// @ts-ignore
|
||||
setImmediate(fn);
|
||||
}) ||
|
||||
function(fn) {
|
||||
setTimeoutFunc(fn, 0);
|
||||
};
|
||||
|
||||
Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
|
||||
if (typeof console !== 'undefined' && console) {
|
||||
console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
|
||||
}
|
||||
};
|
||||
|
||||
/** @suppress {undefinedVars} */
|
||||
var globalNS = (function() {
|
||||
// the only reliable means to get the global object is
|
||||
// `Function('return this')()`
|
||||
// However, this causes CSP violations in Chrome apps.
|
||||
if (typeof self !== 'undefined') {
|
||||
return self;
|
||||
}
|
||||
if (typeof window !== 'undefined') {
|
||||
return window;
|
||||
}
|
||||
if (typeof global !== 'undefined') {
|
||||
return global;
|
||||
}
|
||||
throw new Error('unable to locate global object');
|
||||
})();
|
||||
|
||||
if (!('Promise' in globalNS)) {
|
||||
globalNS['Promise'] = Promise;
|
||||
} else if (!globalNS.Promise.prototype['finally']) {
|
||||
globalNS.Promise.prototype['finally'] = finallyConstructor;
|
||||
}
|
||||
|
||||
})));
|
||||
File diff suppressed because one or more lines are too long
@ -8,7 +8,7 @@ var Vssr = {
|
||||
|
||||
|
||||
$(document).ready(function () {
|
||||
Royal.init();
|
||||
Vssr.init();
|
||||
});
|
||||
|
||||
$(window).load(function () {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user