🎄 Sync 2025-11-13 00:13:36
This commit is contained in:
@@ -5,19 +5,18 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=libcron
|
PKG_NAME:=libcron
|
||||||
|
PKG_VERSION:=1.3.3
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
PKG_SOURCE_PROTO:=git
|
PKG_SOURCE_PROTO:=git
|
||||||
PKG_SOURCE_URL:=https://github.com/PerMalmberg/libcron.git
|
PKG_SOURCE_URL:=https://github.com/PerMalmberg/libcron.git
|
||||||
PKG_SOURCE_DATE:=2023-11-14
|
PKG_SOURCE_VERSION:=v$(PKG_VERSION)
|
||||||
PKG_SOURCE_VERSION:=41f238ceb09d4179e7346d78584a0c978e5d0059
|
PKG_MIRROR_HASH:=74a81dc759bc6ff664601c9b0767120957e54571c0d8500177f7645e07287f24
|
||||||
PKG_MIRROR_HASH:=1d5ed3dd15abd1df765904b80153943c12cf1b2b212432c8f116a5eff30e953d
|
|
||||||
|
|
||||||
PKG_LICENSE:=MIT
|
PKG_LICENSE:=MIT
|
||||||
PKG_LICENSE_FILES:=LICENSE
|
PKG_LICENSE_FILES:=LICENSE
|
||||||
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
|
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
|
||||||
|
|
||||||
PKG_BUILD_PARALLEL:=1
|
|
||||||
CMAKE_INSTALL:=1
|
CMAKE_INSTALL:=1
|
||||||
|
|
||||||
include $(INCLUDE_DIR)/package.mk
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|||||||
@@ -134,10 +134,10 @@ local api = require "luci.passwall.api"
|
|||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
if (confirm("<%: Are you sure you want to restore the client to default settings?%>")) {
|
if (confirm("<%: Are you sure you want to restore the client to default settings?%>")) {
|
||||||
var xhr1 = new XMLHttpRequest();
|
var xhr1 = new XMLHttpRequest();
|
||||||
xhr1.open("GET",'<%= api.url("clear_log") %>', true);
|
xhr1.open("GET",'<%= api.url("clear_log") %>', false);
|
||||||
xhr1.send();
|
xhr1.send();
|
||||||
var xhr2 = new XMLHttpRequest();
|
var xhr2 = new XMLHttpRequest();
|
||||||
xhr2.open("GET",'<%= api.url("reset_config") %>', true);
|
xhr2.open("GET",'<%= api.url("reset_config") %>', false);
|
||||||
xhr2.send();
|
xhr2.send();
|
||||||
window.location.href = '<%= api.url("log") %>'
|
window.location.href = '<%= api.url("log") %>'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -659,6 +659,21 @@ table td, .table .td {
|
|||||||
if (default_group) {
|
if (default_group) {
|
||||||
cbi_t_switch("passwall.nodes", default_group)
|
cbi_t_switch("passwall.nodes", default_group)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//clear expire data
|
||||||
|
if (localStorage && localStorage.length > 0) {
|
||||||
|
const now = Date.now();
|
||||||
|
for (let i = 0; i < localStorage.length; i++) {
|
||||||
|
let key = localStorage.key(i);
|
||||||
|
if (key && (key.startsWith("icmp") || key.startsWith("tcping"))) {
|
||||||
|
let value_str = localStorage.getItem(key);
|
||||||
|
const value = JSON.parse(value_str);
|
||||||
|
if (!(value && value.savetime && (now - value.timestamp) < value.savetime)) {
|
||||||
|
localStorage.removeItem(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get_now_use_node();
|
get_now_use_node();
|
||||||
|
|
||||||
|
|||||||
@@ -449,6 +449,26 @@ local function get_subscribe_info(cfgid, value)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- 设置 ss 协议实现类型
|
||||||
|
local function set_ss_implementation(result)
|
||||||
|
if ss_type_default == "shadowsocks-libev" and has_ss then
|
||||||
|
result.type = "SS"
|
||||||
|
elseif ss_type_default == "shadowsocks-rust" and has_ss_rust then
|
||||||
|
result.type = 'SS-Rust'
|
||||||
|
elseif ss_type_default == "xray" and has_xray then
|
||||||
|
result.type = 'Xray'
|
||||||
|
result.protocol = 'shadowsocks'
|
||||||
|
result.transport = 'raw'
|
||||||
|
elseif ss_type_default == "sing-box" and has_singbox then
|
||||||
|
result.type = 'sing-box'
|
||||||
|
result.protocol = 'shadowsocks'
|
||||||
|
else
|
||||||
|
log("跳过 SS 节点,因未适配到 SS 核心程序,或未正确设置节点使用类型。")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
-- 处理数据
|
-- 处理数据
|
||||||
local function processData(szType, content, add_mode, group)
|
local function processData(szType, content, add_mode, group)
|
||||||
--log(content, add_mode, group)
|
--log(content, add_mode, group)
|
||||||
@@ -602,21 +622,8 @@ local function processData(szType, content, add_mode, group)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
elseif szType == "ss" then
|
elseif szType == "ss" then
|
||||||
if ss_type_default == "shadowsocks-libev" and has_ss then
|
result = set_ss_implementation(result)
|
||||||
result.type = "SS"
|
if not result then return nil end
|
||||||
elseif ss_type_default == "shadowsocks-rust" and has_ss_rust then
|
|
||||||
result.type = 'SS-Rust'
|
|
||||||
elseif ss_type_default == "xray" and has_xray then
|
|
||||||
result.type = 'Xray'
|
|
||||||
result.protocol = 'shadowsocks'
|
|
||||||
result.transport = 'raw'
|
|
||||||
elseif ss_type_default == "sing-box" and has_singbox then
|
|
||||||
result.type = 'sing-box'
|
|
||||||
result.protocol = 'shadowsocks'
|
|
||||||
else
|
|
||||||
log("跳过 SS 节点,因未适配到 SS 核心程序,或未正确设置节点使用类型。")
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
--SS-URI = "ss://" userinfo "@" hostname ":" port [ "/" ] [ "?" plugin ] [ "#" tag ]
|
--SS-URI = "ss://" userinfo "@" hostname ":" port [ "/" ] [ "?" plugin ] [ "#" tag ]
|
||||||
--userinfo = websafe-base64-encode-utf8(method ":" password)
|
--userinfo = websafe-base64-encode-utf8(method ":" password)
|
||||||
@@ -1069,7 +1076,8 @@ local function processData(szType, content, add_mode, group)
|
|||||||
end
|
end
|
||||||
|
|
||||||
elseif szType == "ssd" then
|
elseif szType == "ssd" then
|
||||||
result.type = "SS"
|
result = set_ss_implementation(result)
|
||||||
|
if not result then return nil end
|
||||||
result.address = content.server
|
result.address = content.server
|
||||||
result.port = content.port
|
result.port = content.port
|
||||||
result.password = content.password
|
result.password = content.password
|
||||||
@@ -1831,7 +1839,7 @@ local function parse_link(raw, add_mode, group, cfgid)
|
|||||||
end
|
end
|
||||||
|
|
||||||
for _, v in ipairs(nodes) do
|
for _, v in ipairs(nodes) do
|
||||||
if v and not string.match(v, "^%s*$") then
|
if v and (szType == 'ssd' or not string.match(v, "^%s*$")) then
|
||||||
xpcall(function ()
|
xpcall(function ()
|
||||||
local result
|
local result
|
||||||
if szType == 'ssd' then
|
if szType == 'ssd' then
|
||||||
|
|||||||
@@ -134,10 +134,10 @@ local api = require "luci.passwall2.api"
|
|||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
if (confirm("<%: Are you sure you want to restore the client to default settings?%>")) {
|
if (confirm("<%: Are you sure you want to restore the client to default settings?%>")) {
|
||||||
var xhr1 = new XMLHttpRequest();
|
var xhr1 = new XMLHttpRequest();
|
||||||
xhr1.open("GET",'<%= api.url("clear_log") %>', true);
|
xhr1.open("GET",'<%= api.url("clear_log") %>', false);
|
||||||
xhr1.send();
|
xhr1.send();
|
||||||
var xhr2 = new XMLHttpRequest();
|
var xhr2 = new XMLHttpRequest();
|
||||||
xhr2.open("GET",'<%= api.url("reset_config") %>', true);
|
xhr2.open("GET",'<%= api.url("reset_config") %>', false);
|
||||||
xhr2.send();
|
xhr2.send();
|
||||||
window.location.href = '<%= api.url("log") %>'
|
window.location.href = '<%= api.url("log") %>'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,13 +177,13 @@ local api = require "luci.passwall2.api"
|
|||||||
<div id="add_link_div">
|
<div id="add_link_div">
|
||||||
<div id="add_link_modal_container">
|
<div id="add_link_modal_container">
|
||||||
<h3><%:Add the node via the link%></h3>
|
<h3><%:Add the node via the link%></h3>
|
||||||
<div class="cbi-value">
|
<div class="value-custom">
|
||||||
<textarea id="nodes_link" rows="10"></textarea>
|
<textarea id="nodes_link" rows="10"></textarea>
|
||||||
<p id="nodes_link_text"><%:Enter share links, one per line. Subscription links are not supported!%></p>
|
<p id="nodes_link_text"><%:Enter share links, one per line. Subscription links are not supported!%></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="cbi-value modal-center">
|
<div class="value-custom">
|
||||||
<label class="cbi-value-title"><%:Group Name%></label>
|
<div class="value-field-custom">
|
||||||
<div class="cbi-value-field">
|
<label class="value-title-custom"><%:Group Name%></label>
|
||||||
<div id="addlink_group_custom" class="custom-dropdown">
|
<div id="addlink_group_custom" class="custom-dropdown">
|
||||||
<div class="selected-display">
|
<div class="selected-display">
|
||||||
<span class="text"><%:default%></span>
|
<span class="text"><%:default%></span>
|
||||||
@@ -253,13 +253,12 @@ local api = require "luci.passwall2.api"
|
|||||||
padding: 5px;
|
padding: 5px;
|
||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
margin-bottom: -10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#nodes_link_text {
|
#nodes_link_text {
|
||||||
color: red;
|
color: red;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-top: 0;
|
margin-top: 5px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@@ -272,43 +271,40 @@ local api = require "luci.passwall2.api"
|
|||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#add_link_modal_container .modal-center {
|
.value-custom {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
width: 100%;
|
||||||
gap: 10px;
|
margin: 10px 0;
|
||||||
margin-bottom: 15px;
|
padding: 0px 5px 0px 5px;
|
||||||
width: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#add_link_modal_container .modal-center .cbi-value-title {
|
.value-field-custom {
|
||||||
display: inline-block;
|
display: inline-flex;
|
||||||
width: 80px;
|
align-items: center;
|
||||||
text-align: right;
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value-title-custom {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 28px;
|
line-height: 28px;
|
||||||
margin: 0;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
flex-shrink: 0;
|
text-align: right;
|
||||||
}
|
|
||||||
|
|
||||||
#add_link_modal_container .modal-center .cbi-value-field {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-start;
|
|
||||||
width: 200px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-dropdown {
|
.custom-dropdown {
|
||||||
position: relative;
|
position: relative;
|
||||||
border: 1px solid #d9d9d9;
|
border: 1px solid #d9d9d9;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
width: 200px;
|
width: 180px;
|
||||||
|
height: 28px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
height: 28px;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selected-display {
|
.selected-display {
|
||||||
@@ -316,7 +312,9 @@ local api = require "luci.passwall2.api"
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selected-display:hover {
|
.selected-display:hover {
|
||||||
@@ -332,7 +330,7 @@ local api = require "luci.passwall2.api"
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 100%;
|
top: 100%;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 180px;
|
||||||
border: 1px solid #d9d9d9;
|
border: 1px solid #d9d9d9;
|
||||||
border-top: none;
|
border-top: none;
|
||||||
box-shadow: 0 1px 3px rgba(0,0,0,0.15);
|
box-shadow: 0 1px 3px rgba(0,0,0,0.15);
|
||||||
@@ -340,7 +338,7 @@ local api = require "luci.passwall2.api"
|
|||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
max-height: 250px;
|
max-height: 200px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
@@ -350,6 +348,7 @@ local api = require "luci.passwall2.api"
|
|||||||
.dropdown-item {
|
.dropdown-item {
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-item.selected {
|
.dropdown-item.selected {
|
||||||
@@ -357,13 +356,17 @@ local api = require "luci.passwall2.api"
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.create-item-input::placeholder {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.dropdown-item.custom-input input {
|
.dropdown-item.custom-input input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 200px;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
|
text-align: left;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -497,7 +497,7 @@ table td, .table .td {
|
|||||||
<input class="btn cbi-button cbi-button-apply" type="button" value="<%:Use%>" id="apply_{{id}}" onclick="open_set_node_div('{{id}}')"/>
|
<input class="btn cbi-button cbi-button-apply" type="button" value="<%:Use%>" id="apply_{{id}}" onclick="open_set_node_div('{{id}}')"/>
|
||||||
<input class="btn cbi-button cbi-button-add" type="button" value="<%:Copy%>" onclick="copy_node('{{id}}')"/>
|
<input class="btn cbi-button cbi-button-add" type="button" value="<%:Copy%>" onclick="copy_node('{{id}}')"/>
|
||||||
<input class="btn cbi-button cbi-button-edit" type="button" value="<%:Edit%>" onclick="location.href='<%=api.url("node_config")%>/{{id}}'" alt="<%:Edit%>" title="<%:Edit%>">
|
<input class="btn cbi-button cbi-button-edit" type="button" value="<%:Edit%>" onclick="location.href='<%=api.url("node_config")%>/{{id}}'" alt="<%:Edit%>" title="<%:Edit%>">
|
||||||
<input class="btn cbi-button cbi-button-remove" type="button" value="<%:Del%>" onclick="del_node('{{id}}')" alt="<%:Del%>" title="<%:Del%>">
|
<input class="btn cbi-button cbi-button-remove" type="button" value="<%:Delete%>" onclick="del_node('{{id}}')" alt="<%:Delete%>" title="<%:Delete%>">
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -659,6 +659,21 @@ table td, .table .td {
|
|||||||
cbi_t_switch("passwall2.nodes", default_group)
|
cbi_t_switch("passwall2.nodes", default_group)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//clear expire data
|
||||||
|
if (localStorage && localStorage.length > 0) {
|
||||||
|
const now = Date.now();
|
||||||
|
for (let i = 0; i < localStorage.length; i++) {
|
||||||
|
let key = localStorage.key(i);
|
||||||
|
if (key && (key.startsWith("icmp") || key.startsWith("tcping"))) {
|
||||||
|
let value_str = localStorage.getItem(key);
|
||||||
|
const value = JSON.parse(value_str);
|
||||||
|
if (!(value && value.savetime && (now - value.timestamp) < value.savetime)) {
|
||||||
|
localStorage.removeItem(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get_now_use_node();
|
get_now_use_node();
|
||||||
|
|
||||||
pingAllNodes();
|
pingAllNodes();
|
||||||
@@ -684,4 +699,4 @@ table td, .table .td {
|
|||||||
<input class="btn cbi-button cbi-button-remove" type="button" onclick="close_set_node_div()" value="<%:Close%>" />
|
<input class="btn cbi-button cbi-button-remove" type="button" onclick="close_set_node_div()" value="<%:Close%>" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -443,6 +443,26 @@ local function get_subscribe_info(cfgid, value)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- 设置 ss 协议实现类型
|
||||||
|
local function set_ss_implementation(result)
|
||||||
|
if ss_type_default == "shadowsocks-libev" and has_ss then
|
||||||
|
result.type = "SS"
|
||||||
|
elseif ss_type_default == "shadowsocks-rust" and has_ss_rust then
|
||||||
|
result.type = 'SS-Rust'
|
||||||
|
elseif ss_type_default == "xray" and has_xray then
|
||||||
|
result.type = 'Xray'
|
||||||
|
result.protocol = 'shadowsocks'
|
||||||
|
result.transport = 'raw'
|
||||||
|
elseif ss_type_default == "sing-box" and has_singbox then
|
||||||
|
result.type = 'sing-box'
|
||||||
|
result.protocol = 'shadowsocks'
|
||||||
|
else
|
||||||
|
log("跳过 SS 节点,因未适配到 SS 核心程序,或未正确设置节点使用类型。")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
-- 处理数据
|
-- 处理数据
|
||||||
local function processData(szType, content, add_mode, group)
|
local function processData(szType, content, add_mode, group)
|
||||||
--log(content, add_mode, group)
|
--log(content, add_mode, group)
|
||||||
@@ -606,21 +626,8 @@ local function processData(szType, content, add_mode, group)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
elseif szType == "ss" then
|
elseif szType == "ss" then
|
||||||
if ss_type_default == "shadowsocks-libev" and has_ss then
|
result = set_ss_implementation(result)
|
||||||
result.type = "SS"
|
if not result then return nil end
|
||||||
elseif ss_type_default == "shadowsocks-rust" and has_ss_rust then
|
|
||||||
result.type = 'SS-Rust'
|
|
||||||
elseif ss_type_default == "xray" and has_xray then
|
|
||||||
result.type = 'Xray'
|
|
||||||
result.protocol = 'shadowsocks'
|
|
||||||
result.transport = 'raw'
|
|
||||||
elseif ss_type_default == "sing-box" and has_singbox then
|
|
||||||
result.type = 'sing-box'
|
|
||||||
result.protocol = 'shadowsocks'
|
|
||||||
else
|
|
||||||
log("跳过 SS 节点,因未适配到 SS 核心程序,或未正确设置节点使用类型。")
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
--SS-URI = "ss://" userinfo "@" hostname ":" port [ "/" ] [ "?" plugin ] [ "#" tag ]
|
--SS-URI = "ss://" userinfo "@" hostname ":" port [ "/" ] [ "?" plugin ] [ "#" tag ]
|
||||||
--userinfo = websafe-base64-encode-utf8(method ":" password)
|
--userinfo = websafe-base64-encode-utf8(method ":" password)
|
||||||
@@ -1075,7 +1082,8 @@ local function processData(szType, content, add_mode, group)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif szType == "ssd" then
|
elseif szType == "ssd" then
|
||||||
result.type = "SS"
|
result = set_ss_implementation(result)
|
||||||
|
if not result then return nil end
|
||||||
result.address = content.server
|
result.address = content.server
|
||||||
result.port = content.port
|
result.port = content.port
|
||||||
result.password = content.password
|
result.password = content.password
|
||||||
@@ -1836,7 +1844,7 @@ local function parse_link(raw, add_mode, group, cfgid)
|
|||||||
end
|
end
|
||||||
|
|
||||||
for _, v in ipairs(nodes) do
|
for _, v in ipairs(nodes) do
|
||||||
if v and not string.match(v, "^%s*$") then
|
if v and (szType == 'ssd' or not string.match(v, "^%s*$")) then
|
||||||
xpcall(function ()
|
xpcall(function ()
|
||||||
local result
|
local result
|
||||||
if szType == 'ssd' then
|
if szType == 'ssd' then
|
||||||
|
|||||||
Reference in New Issue
Block a user