update 2026-10-05 00:19:25

This commit is contained in:
action committed 2026-10-05 00:19:25 +08:00
1 parent c75ec11645
commit 5c0c622001
23 files changed
+281 -101

No files matched your search

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 319 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 640 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 550 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 547 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 659 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 KiB

+1 -1
View File
@@ -7,7 +7,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall
PKG_VERSION:=26.10.3
PKG_VERSION:=26.10.4
PKG_RELEASE:=1
PKG_PO_VERSION:=$(PKG_VERSION)
@@ -105,7 +105,8 @@ function index()
entry({"admin", "services", appname, "read_rulelist"}, call("read_rulelist")).leaf = true
--[[Components update]]
entry({"admin", "services", appname, "check_passwall"}, call("app_check")).leaf = true
entry({"admin", "services", appname, "check_" .. appname}, call("app_check")).leaf = true
entry({"admin", "services", appname, "update_" .. appname}, call("app_update")).leaf = true
local coms = require "luci.passwall.com"
local com
for _, com in ipairs(coms.order) do
@@ -809,6 +810,23 @@ function app_check()
http_write_json(json)
end
function app_update()
local id = http.formvalue("id")
if not id or not id:match("^[%w_-]+$") then http_write_json({code = 1}); return end
local task = http.formvalue("task")
local result
if task == "progress" then
result = api.to_download_progress(appname, id, http.formvalue("total_size"))
elseif task == "install" then
if not luci.dispatcher.test_post_security() then return end
result = api.to_install_self(id, http.formvalue("force"))
else
local part = http.formvalue("part") == "2" and "2" or "1"
result = api.to_download(appname, http.formvalue("url"), http.formvalue("size"), id .. part, part == "2")
end
http_write_json(result)
end
function com_check(comname)
local json = api.to_check("",comname)
http_write_json(json)
@@ -429,6 +429,16 @@ if singbox_tags:find("with_quic") then
o = s:option(Value, "hysteria2_down_mbps", translate("Max download Mbps"))
o:depends({ protocol = "hysteria2" })
o = s:option(Value, "hysteria2_stream_recv_win", translate("QUIC stream receive window"))
o.datatype = "uinteger"
o.placeholder = "8388608"
o:depends({ protocol = "hysteria2" })
o = s:option(Value, "hysteria2_conn_recv_win", translate("QUIC connection receive window"))
o.datatype = "uinteger"
o.placeholder = "20971520"
o:depends({ protocol = "hysteria2" })
o = s:option(Value, "hysteria2_idle_timeout", translate("Idle Timeout"), translate("Units:seconds") .. " (4~120)")
o.datatype = "range(4,120)"
o:depends({ protocol = "hysteria2"})
@@ -361,6 +361,16 @@ o:depends({ protocol = "hysteria2" })
o = s:option(Value, "hysteria2_down_mbps", translate("Max download Mbps"))
o:depends({ protocol = "hysteria2" })
o = s:option(Value, "hysteria2_stream_recv_win", translate("QUIC stream receive window"))
o.datatype = "uinteger"
o.placeholder = "8388608"
o:depends({ protocol = "hysteria2" })
o = s:option(Value, "hysteria2_conn_recv_win", translate("QUIC connection receive window"))
o.datatype = "uinteger"
o.placeholder = "20971520"
o:depends({ protocol = "hysteria2" })
o = s:option(Value, "hysteria2_idle_timeout", translate("Idle Timeout"), translate("Units:seconds") .. " (4~120)")
o.datatype = "range(4,120)"
o:depends({ protocol = "hysteria2"})
@@ -109,10 +109,14 @@ o.rewrite_option = o.option
o = s:option(Value, "down_mbps", translate("Max download Mbps"))
o.rewrite_option = o.option
o = s:option(Value, "recv_window", translate("QUIC stream receive window"))
o = s:option(Value, "stream_recv_win", translate("QUIC stream receive window"))
o.datatype = "uinteger"
o.placeholder = "8388608"
o.rewrite_option = o.option
o = s:option(Value, "recv_window_conn", translate("QUIC connection receive window"))
o = s:option(Value, "conn_recv_win", translate("QUIC connection receive window"))
o.datatype = "uinteger"
o.placeholder = "20971520"
o.rewrite_option = o.option
o = s:option(Value, "idle_timeout", translate("Idle Timeout"), translate("Units:seconds") .. " (4~120)")
+52 -20
View File
@@ -12,7 +12,6 @@ datatypes = require "luci.cbi.datatypes"
jsonc = require "luci.jsonc"
i18n = require "luci.i18n"
appname = "passwall"
curl_args = { "-skfL", "--connect-timeout 3", "--retry 3", "-H 'Accept: */*'" }
command_timeout = 300
OPENWRT_ARCH = nil
@@ -1239,8 +1238,8 @@ function to_check(arch, app_name)
}
end
function to_download(app_name, url, size, task_id)
local result = check_path(app_name)
function to_download(app_name, url, size, task_id, keep_files)
local result = app_name == appname and {code = 0} or check_path(app_name)
if result.code ~= 0 then
return result
end
@@ -1249,7 +1248,7 @@ function to_download(app_name, url, size, task_id)
return {code = 1, error = i18n.translate("Download url is required.")}
end
remove("/tmp/" .. app_name .. "_download.*")
if not keep_files then remove("/tmp/" .. app_name .. "_download.*") end
local tmp_file
if task_id and task_id:match("^[%w_-]+$") then
@@ -1298,6 +1297,9 @@ function to_download_progress(app_name, task_id, total_size)
total_size = tonumber(total_size) or 0
local tmp_file = "/tmp/" .. app_name .. "_download." .. task_id
local downloaded = tonumber(fs.stat(tmp_file, "size")) or 0
if app_name == appname then
downloaded = (tonumber(fs.stat(tmp_file .. "1", "size")) or 0) + (tonumber(fs.stat(tmp_file .. "2", "size")) or 0)
end
local percent
if total_size > 0 then
-- The download request has not completed yet, so leave 100% for its success callback.
@@ -1455,7 +1457,7 @@ function get_version()
end
function to_check_self()
local release = get_api_json(com.passwall:get_url())
local release = get_api_json(com[appname]:get_url())
if type(release) == "table" and #release > 0 then
release = release[1]
end
@@ -1469,26 +1471,56 @@ function to_check_self()
-- Keep the release suffix (-1, -2, ...) so package revisions are compared too.
local remote_version = release.tag_name:gsub("^v", "")
local has_update = compare_versions(local_version, "<", remote_version)
if not has_update then
return {
code = 0,
local_version = local_version,
remote_version = remote_version,
html_url = release.html_url,
data = release.assets or {}
}
local prefix, extension
if sys.call("command -v apk >/dev/null 2>&1") == 0 then
prefix, extension = "25.12+_", ".apk"
else
if sys.call("command -v uname >/dev/null 2>&1") ~= 0 then return {code = 1} end
local kernel = trim(sys.exec("uname -r 2>/dev/null")):match("^(%d+%.%d+)")
if not kernel then return {code = 1} end
prefix = compare_versions(kernel, "<", "5.11") and "22.03-_" or "23.05-24.10_"
extension = ".ipk"
end
local main, i18n_package
for _, asset in ipairs(release.assets or {}) do
local name = asset.name or ""
if name:find(prefix, 1, true) == 1 and name:sub(-#extension) == extension then
name = name:sub(#prefix + 1)
if name:match("^luci%-app%-" .. appname .. "[_%-]%d") then main = asset end
if name:match("^luci%-i18n%-" .. appname .. "%-zh%-cn[_%-]%d") then i18n_package = asset end
end
end
if not main or not i18n_package then return {code = 1} end
return {
code = 1,
has_update = true,
local_version = local_version,
remote_version = remote_version,
html_url = release.html_url,
data = release.assets or {},
error = i18n.translatef("The latest version: %s, currently does not support automatic update, if you need to update, please compile or download the ipk and then manually install.", remote_version)
code = 0, has_update = has_update, local_version = local_version,
remote_version = remote_version, html_url = release.html_url,
data = main, i18n = i18n_package
}
end
function to_install_self(id, force)
if not id or not id:match("^[%w_-]+$") then return {code = 1} end
local dir = "/tmp/" .. appname .. "_luci_update." .. id
local manager = sys.call("command -v apk >/dev/null 2>&1") == 0 and "apk" or "opkg"
local extension = manager == "apk" and ".apk" or ".ipk"
local status_dir = "/www/luci-static/resources/" .. appname .. "-update"
local status = status_dir .. "/" .. id .. ".json"
fs.mkdir(dir)
fs.mkdir(status_dir)
exec("/bin/mv", {"/tmp/" .. appname .. "_download." .. id .. "1", dir .. "/luci-app-" .. appname .. extension})
exec("/bin/mv", {"/tmp/" .. appname .. "_download." .. id .. "2", dir .. "/luci-i18n-" .. appname .. "-zh-cn" .. extension})
local script = dir .. "/luci_update.sh"
if exec("/bin/cp", {"/usr/share/" .. appname .. "/luci_update.sh", script}) ~= 0 then
remove(dir)
return {code = 1}
end
fs.chmod(script, 755)
fs.writefile(status, '{"installing":true}')
sys.call("nohup " .. script .. " " .. dir .. " " .. status .. " " .. manager .. " " ..
(force == "1" and "1" or "0") .. " >/dev/null 2>&1 </dev/null &")
return {code = 0}
end
function is_js_luci()
return sys.call('[ -f "/www/luci-static/resources/uci.js" ]') == 0
end
@@ -144,8 +144,8 @@ function gen_config(var)
ech = (node.ech == "1") and node.ech_config or nil
},
quic = {
initStreamReceiveWindow = (node.hysteria2_recv_window) and tonumber(node.hysteria2_recv_window) or nil,
initConnReceiveWindow = (node.hysteria2_recv_window_conn) and tonumber(node.hysteria2_recv_window_conn) or nil,
initStreamReceiveWindow = node.hysteria2_stream_recv_win and tonumber(node.hysteria2_stream_recv_win) or nil,
initConnReceiveWindow = node.hysteria2_conn_recv_win and tonumber(node.hysteria2_conn_recv_win) or nil,
maxIdleTimeout = (function(t)
t = tonumber(tostring(t or "30"):match("^%d+"))
return (t and t >= 4 and t <= 120) and t .. "s" or "30s"
@@ -623,7 +623,9 @@ function gen_outbound(flag, node, tag, proxy_table)
t = tonumber(tostring(t or "0"):match("^%d+"))
return (t and t >= 2 and t <= 60) and t .. "s" or nil
end)(node.hysteria2_keep_alive_period),
disable_path_mtu_discovery = version_ge_1_14_0 and (tonumber(node.hysteria2_disable_mtu_discovery) == 1) or nil,
stream_receive_window = tonumber(node.hysteria2_stream_recv_win) and tonumber(node.hysteria2_stream_recv_win)/1048576 .. " MB" or nil,
connection_receive_window = tonumber(node.hysteria2_conn_recv_win) and tonumber(node.hysteria2_conn_recv_win)/1048576 .. " MB" or nil,
disable_path_mtu_discovery = version_ge_1_14_0 and (node.hysteria2_disable_mtu_discovery == "1") or nil,
tls = tls,
realm = node.hysteria2_realms and (function()
result.server = nil
@@ -364,7 +364,9 @@ function gen_outbound(flag, node, tag, proxy_table)
t = tonumber(tostring(t or "0"):match("^%d+"))
return (t and t >= 2 and t <= 60) and t or nil
end)(node.hysteria2_keep_alive_period),
disablePathMTUDiscovery = tonumber(node.hysteria2_disable_mtu_discovery) == 1
disablePathMTUDiscovery = node.hysteria2_disable_mtu_discovery == "1",
initStreamReceiveWindow = node.hysteria2_stream_recv_win and tonumber(node.hysteria2_stream_recv_win) or nil,
initConnectionReceiveWindow = node.hysteria2_conn_recv_win and tonumber(node.hysteria2_conn_recv_win) or nil,
}
end
if fragment and fragment_table and ({raw=1, ws=1, httpupgrade=1, grpc=1, xhttp=1})[TP] then
@@ -7,6 +7,7 @@ local com = self.com
<script type="text/javascript">
//<![CDATA[
var appname = '<%=api.appname%>';
var appInfoList = new Array();
var inProgressCount = 0;
var tokenStr = '<%=token%>';
@@ -22,6 +23,25 @@ local com = self.com
var downloadingText = '<%:Downloading...%>';
var decompressioningText = '<%:Unpacking...%>';
var movingText = '<%:Moving...%>';
var installingText = '<%:Installing...%>';
var installingNotice = '<%:Do not refresh or switch pages during installation.%>';
var updateFailedText = '<%:Update failed%>';
var unknownErrorText = '<%:Unknown error%>';
var componentUpdates = 0, luciUpdating = false;
function syncUpdateButtons() {
var buttons = document.querySelectorAll('#app_version input[data-update-app]');
for (var i = 0; i < buttons.length; i++) {
var btn = buttons[i];
btn.disabled = !!btn.updateDisabled || luciUpdating ||
(btn.getAttribute('data-update-app') === appname && componentUpdates > 0);
}
}
function setButtonDisabled(btn, disabled) {
btn.updateDisabled = disabled;
syncUpdateButtons();
}
//window.onload = function () {};
@@ -35,8 +55,11 @@ local com = self.com
inProgressCount++;
}
function removePageNotice() {
function removePageNotice(app) {
if (app === appname) luciUpdating = false;
else if (app) componentUpdates--;
inProgressCount--;
syncUpdateButtons();
if (inProgressCount === 0) {
window.onbeforeunload = undefined;
}
@@ -46,21 +69,24 @@ local com = self.com
if (btn) {
btn.value = updateSuccessText;
btn.placeholder = updateSuccessText;
btn.disabled = true;
setButtonDisabled(btn, true);
}
if (inProgressCount === 0) {
window.setTimeout(function () {
window.location.reload();
if (inProgressCount === 0 && !luciUpdating) window.location.reload();
}, 1000);
}
}
function onRequestError(btn, errorMessage) {
btn.disabled = false;
function onRequestError(btn, errorMessage, checking) {
setButtonDisabled(btn, false);
btn.value = retryText;
var ckeckDetailElm = document.getElementById(btn.id + '-detail');
var app = btn.getAttribute('data-update-app');
var detailId = app === appname ? appname + '-check_btn' : '_' + app + '-check_btn';
var ckeckDetailElm = document.getElementById(detailId + '-detail');
if (app === appname && !checking) errorMessage = errorMessage ? updateFailedText : unknownErrorText;
if (errorMessage && ckeckDetailElm) {
ckeckDetailElm.textContent = errorMessage
}
@@ -75,7 +101,7 @@ local com = self.com
}
function checkUpdate(btn, app) {
btn.disabled = true;
setButtonDisabled(btn, true);
btn.value = inProgressText;
addPageNotice();
@@ -89,13 +115,13 @@ local com = self.com
arch: ''
}, function (x, json) {
removePageNotice();
if (json.code) {
if (!json || json.code) {
appInfoList[app] = undefined;
onRequestError(btn, json.error);
onRequestError(btn, json && json.error, true);
} else {
appInfoList[app] = json;
if (json.has_update) {
btn.disabled = false;
setButtonDisabled(btn, false);
btn.value = clickToUpdateText;
btn.placeholder = clickToUpdateText;
@@ -110,7 +136,7 @@ local com = self.com
ckeckDetailElm.innerHTML = urlNode;
}
} else {
btn.disabled = true;
setButtonDisabled(btn, true);
btn.value = noUpdateText;
var forceBtn = document.getElementById('_' + app + '-force_btn');
if (forceBtn) {
@@ -122,7 +148,10 @@ local com = self.com
}
function doUpdate(btn, app) {
btn.disabled = true;
if (luciUpdating || (app === appname && componentUpdates > 0)) return;
if (app === appname) luciUpdating = true;
else componentUpdates++;
setButtonDisabled(btn, true);
btn.value = downloadingText;
addPageNotice();
@@ -131,6 +160,7 @@ local com = self.com
var appInfo = appInfoList[app];
var downloadId = Date.now().toString(36) + Math.random().toString(36).substring(2, 8);
var totalSize = appInfo && appInfo.data ? Number(appInfo.data.size) : 0;
if (app === appname) totalSize += Number(appInfo.i18n.size) || 0;
if (!isFinite(totalSize) || totalSize <= 0) {
totalSize = 0;
}
@@ -169,41 +199,44 @@ local com = self.com
progressTimer = setInterval(updateDownloadProgress, 1000);
}
// Download file
XHR.get(appUpdateUrl, {
token: tokenStr,
url: appInfo ? appInfo.data.browser_download_url : '',
size: appInfo ? appInfo.data.size / 1024 : null,
id: downloadId
}, function (x, json) {
stopDownloadProgress();
if (json.code) {
removePageNotice();
onRequestError(btn, json.error);
} else if (json.zip) {
btn.value = decompressioningText;
// Extract file
XHR.get(appUpdateUrl, {
token: tokenStr,
task: 'extract',
file: json.file,
subfix: appInfo ? appInfo.type : ''
}, function (x, json) {
if (json.code) {
removePageNotice();
onRequestError(btn, json.error);
} else {
move(btn, appUpdateUrl, json.file);
}
}, 300)
} else {
move(btn, appUpdateUrl, json.file);
}
}, 300)
function download(part) {
var asset = app === appname && part === 2 ? appInfo.i18n : appInfo.data;
XHR.get(appUpdateUrl, {
token: tokenStr, url: asset.browser_download_url,
size: (app === appname && part === 1 ? totalSize : asset.size) / 1024,
id: downloadId, part: part
}, function (x, json) {
if (json && !json.code && app === appname && part === 1) {
download(2);
return;
}
stopDownloadProgress();
if (!json || json.code) {
removePageNotice(app);
onRequestError(btn, json && (json.error || updateFailedText));
} else if (app === appname) {
installLuci(btn, appUpdateUrl, downloadId);
} else if (json.zip) {
btn.value = decompressioningText;
XHR.get(appUpdateUrl, {
token: tokenStr, task: 'extract', file: json.file, subfix: appInfo.type || ''
}, function (x, json) {
if (!json || json.code) {
removePageNotice(app);
onRequestError(btn, json && json.error);
} else {
move(btn, app, appUpdateUrl, json.file);
}
}, 300);
} else {
move(btn, app, appUpdateUrl, json.file);
}
}, 300);
}
download(1);
}
function move(btn, url, file) {
function move(btn, app, url, file) {
btn.value = movingText;
// Move file to target dir
@@ -212,7 +245,7 @@ local com = self.com
task: 'move',
file: file
}, function (x, json) {
removePageNotice();
removePageNotice(app);
if (json.code) {
onRequestError(btn, json.error);
} else {
@@ -220,6 +253,47 @@ local com = self.com
}
}, 300)
}
function installLuci(btn, url, id) {
btn.value = installingText;
var detail = document.getElementById(appname + '-check_btn-detail');
detail.textContent = installingNotice;
// Read the tiny result file even if rpcd restart invalidates the session.
var pending = false, finished = false;
var timer = setInterval(function() {
if (pending) return;
pending = true;
var xhr = new XMLHttpRequest();
xhr.open('GET', '<%=resource%>/' + appname + '-update/' + id + '.json?_=' + Date.now(), true);
xhr.timeout = 5000;
xhr.onerror = xhr.ontimeout = function() { pending = false; };
xhr.onload = function() {
pending = false;
if (finished) return;
var json;
try { json = JSON.parse(xhr.responseText); } catch (e) { return; }
if (typeof json.code !== 'number') return;
finished = true;
clearInterval(timer);
removePageNotice(appname);
if (json.code) onRequestError(btn, updateFailedText);
else {
window.onbeforeunload = undefined;
window.location.reload();
}
};
xhr.send();
}, 1000);
XHR.post(url, {token: tokenStr, task: 'install', id: id,
force: appInfoList[appname].has_update ? '0' : '1'}, function(x, json) {
if (!finished && json && json.code) {
finished = true;
clearInterval(timer);
removePageNotice(appname);
onRequestError(btn, updateFailedText);
}
}, 300);
}
//]]>
</script>
@@ -228,9 +302,11 @@ local com = self.com
<div class="cbi-value-field">
<!--div class="cbi-value-description"-->
<span>【 <%=api.get_version()%> 】</span>
<input class="btn cbi-button cbi-button-apply" type="button" id="passwall-check_btn"
onclick="onBtnClick(this,'passwall');" value="<%:Check update%>" />
<span id="passwall-check_btn-detail"></span>
<input class="btn cbi-button cbi-button-apply" type="button" id="<%=api.appname%>-check_btn" data-update-app="<%=api.appname%>"
onclick="onBtnClick(this, appname);" value="<%:Check update%>" />
<input class="btn cbi-button cbi-button-apply" type="button" id="_<%=api.appname%>-force_btn" data-update-app="<%=api.appname%>"
onclick="doUpdate(this, appname);" value="<%:Force update%>" style="display:none" />
<span id="<%=api.appname%>-check_btn-detail"></span>
<!--/div-->
</div>
</div>
@@ -245,9 +321,9 @@ local com = self.com
<div class="cbi-value-field">
<!--div class="cbi-value-description"-->
<span>【 <span class="com_version" key="<%=k%>"><%=translate("Null")%></span> 】</span>
<input class="btn cbi-button cbi-button-apply" type="button" id="_<%=k%>-check_btn"
<input class="btn cbi-button cbi-button-apply" type="button" id="_<%=k%>-check_btn" data-update-app="<%=k%>"
onclick="onBtnClick(this,'<%=k%>');" value="<%:Check update%>" />
<input class="btn cbi-button cbi-button-apply" type="button" id="_<%=k%>-force_btn"
<input class="btn cbi-button cbi-button-apply" type="button" id="_<%=k%>-force_btn" data-update-app="<%=k%>"
onclick="doUpdate(this,'<%=k%>');" value="<%:Force update%>" style="display:none"/>
<span id="_<%=k%>-check_btn-detail"></span>
<!--/div-->
+12 -3
View File
@@ -995,9 +995,6 @@ msgstr "回滚中..."
msgid "Update Options"
msgstr "更新选项"
msgid "The latest version: %s, currently does not support automatic update, if you need to update, please compile or download the ipk and then manually install."
msgstr "最新版本:%s,目前暂不支持自动更新,如需更新,请自行编译或下载 ipk 然后手动安装。"
msgid "Enable custom URL"
msgstr "启用自定义规则地址"
@@ -2168,3 +2165,15 @@ msgstr "配置支持的密码套件列表,以冒号 (:) 分隔。"
msgid "Connection Reuse"
msgstr "连接复用"
msgid "Installing..."
msgstr "安装中"
msgid "Do not refresh or switch pages during installation."
msgstr "安装时请勿刷新页面和切换页面。"
msgid "Update failed"
msgstr "更新失败"
msgid "Unknown error"
msgstr "未知错误"
@@ -0,0 +1,31 @@
#!/bin/sh
CONFIG=passwall
dir="$1"
status="$2"
manager="$3"
force="$4"
if [ "$manager" = apk ]; then
extra=""
[ "$force" = 1 ] && extra="--force-reinstall --force-overwrite"
apk add --allow-untrusted $extra "$dir/luci-app-${CONFIG}.apk" "$dir/luci-i18n-${CONFIG}-zh-cn.apk"
result=$?
else
extra=""
[ "$force" = 1 ] && extra="--force-reinstall"
opkg install $extra "$dir/luci-app-${CONFIG}.ipk" "$dir/luci-i18n-${CONFIG}-zh-cn.ipk"
result=$?
fi
rm -rf "$dir"
if [ "$result" = 0 ]; then
rm -f "/tmp/etc/${CONFIG}_tmp/${CONFIG}_version" /tmp/luci-indexcache /tmp/luci-indexcache.*
if [ -x /etc/init.d/rpcd ]; then
/etc/init.d/rpcd restart >/dev/null 2>&1
fi
if [ -x /etc/init.d/uhttpd ]; then
/etc/init.d/uhttpd reload >/dev/null 2>&1
fi
fi
[ "$result" = 0 ] && echo '{"code":0}' > "$status" || echo '{"code":1}' > "$status"
(sleep 60; rm -f "$status") >/dev/null 2>&1 &
@@ -1,14 +0,0 @@
<% if luci.sys.exec("echo -n `uci -q get base_config.@status[0].links`") ~= "0" then %>
<script>
var links = document.createElement('div');
links.innerHTML ='<table class="table"><tr class="tr"><td class="td left"><a href="https://openwrt.ai/" target="_blank">固件下载与定制</a></td><td class="td left" width="25%"><a href="https://openwrt.ai/fadian/" target="_blank" style="color:orangered">赞助</a></td><td class="td left" width="25%"><a href="https://github.com/kiddin9/Kwrt" target="_blank">源码与反馈</a></td><td class="td left" width="25%"><a href="https://t.me/opkwrt" target="_blank">TG交流</a></td></tr></table>';
setTimeout(function(){
var telegram = document.querySelectorAll(".cbi-section")[0];
telegram.appendChild(links);
}, 1500);
setTimeout(function(){
var telegram = document.querySelectorAll(".cbi-section")[0];
telegram.appendChild(links);
}, 2400);
</script>
<%end%>
+2 -2
View File
@@ -21,13 +21,13 @@ define Download/geoip
HASH:=1cba1f0982cf62502fa079c66047c3d0c608196da5b3305671e68f60e917a482
endef
GEOSITE_VER:=20261002050024
GEOSITE_VER:=20261004053124
GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER)
define Download/geosite
URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/
URL_FILE:=dlc.dat
FILE:=$(GEOSITE_FILE)
HASH:=5534f873d62dabddc245e169626f3c800893264047e411e48827ddfb5c726af6
HASH:=1b9012ab376e142da68506385e4b0590abeb20a0deac0169293e1057fce8d949
endef
GEOSITE_IRAN_VER:=202609280201
+3 -3
View File
@@ -5,12 +5,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=v2rayA
PKG_VERSION:=2.5.8
PKG_VERSION:=2.5.9
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/v2rayA/v2rayA/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=dfc0c113134728ef8c73ff8a7fea398103af1b9e38749437fed668d72985e601
PKG_HASH:=46d20e8f145749546a69aa0f300a4c88af77d99436dd5d21ef705d407f32abfe
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)/service
PKG_LICENSE:=AGPL-3.0-only
@@ -60,7 +60,7 @@ define Download/v2raya-web
URL:=https://github.com/v2rayA/v2rayA/releases/download/v$(PKG_VERSION)/
URL_FILE:=web.tar.gz
FILE:=$(WEB_FILE)
HASH:=bac5158511e3f3a2ece8ad93cb816331436de9b75fe8b4629a248b810e43554b
HASH:=2de77982f71e05765d539b24f472a242e6b5bc284e25151782db72345d32976a
endef
define Build/Prepare