update 2026-09-06 16:17:35

This commit is contained in:
action
2026-09-06 16:17:35 +08:00
parent 35c80a77bc
commit 51ed2622f8
26 changed files with 220 additions and 223 deletions
+23 -16
View File
@@ -1,25 +1,24 @@
#!/bin/sh /etc/rc.common
USE_PROCD=1
START=99
STOP=10
CONF="filebrowser-q"
PROG="/usr/bin/filebrowser-q"
CONF_PATH="/etc/filebrowser-q/config.yaml"
PID_FILE="/var/run/filebrowser-q.pid"
DB_PATH="/etc/filebrowser-q/database.db"
start() {
config_load "$CONF"
start_service() {
config_load "$CONF"
local enabled
config_get_bool enabled "config" "enabled" "0"
[ "$enabled" -eq "1" ] || return 1
local enabled
config_get_bool enabled "config" "enabled" "0"
[ "$enabled" -eq "1" ] || return 1
local listen_port root_path root_name
local listen_port root_path root_name
config_get listen_port "config" "listen_port" "8787"
config_get root_path "config" "root_path" "/"
# 路径为 / 时 name 设为 root,否则留空
root_name=""
[ "$root_path" = "/" ] && root_name="root"
@@ -28,7 +27,7 @@ start() {
cat <<EOF > "$CONF_PATH"
server:
port: $listen_port
database: "/etc/filebrowser-q/database.db"
database: "$DB_PATH"
sources:
- path: "$root_path"
name: "$root_name"
@@ -49,12 +48,20 @@ EOF
-i "$CONF_PATH"
fi
echo "Starting filebrowser..."
start-stop-daemon -S -q -b -m -p "$PID_FILE" -x "$PROG" -- -c "$CONF_PATH"
procd_open_instance
procd_set_param command "$PROG"
procd_append_param command -c "$CONF_PATH"
procd_set_param limits core="unlimited"
procd_set_param limits nofile="1000000 1000000"
procd_set_param stdout 1
procd_set_param stderr 1
procd_set_param respawn
procd_close_instance
}
stop() {
kill -9 `pidof filebrowser-q | sed "s/$$//g"` 2>/dev/null
rm -f "$PID_FILE"
echo "filebrowser stopped"
service_triggers() {
procd_add_reload_trigger "$CONF"
}
@@ -6,9 +6,21 @@
'require view';
'require fs';
const callServiceList = rpc.declare({
object: 'service',
method: 'list',
params: ['name'],
expect: { '': {} }
});
function getServiceStatus() {
return L.resolveDefault(callServiceList('filebrowser-q'), {}).then(function(res) {
let isRunning = false;
try {
isRunning = res['filebrowser-q']['instances']['instance1']['running'];
} catch (e) { }
return isRunning;
});
}
function renderStatus(isRunning, port) {
@@ -26,16 +38,8 @@ function renderStatus(isRunning, port) {
}
return view.extend({
load: async function () {
const promises = await Promise.all([
L.resolveDefault(fs.stat('/var/run/filebrowser-q.pid'), null),
uci.load('filebrowser-q')
]);
const data = {
isRunning: promises[0],
conf: promises[1]
};
return data;
load() {
return uci.load('filebrowser-q');
},
render(data) {
@@ -49,24 +53,17 @@ return view.extend({
s = m.section(form.TypedSection);
s.anonymous = true;
s.render = function() {
poll.add(function() {
return fs.stat('/var/run/filebrowser-q.pid').then(function(stat) {
let view = document.getElementById('service_status');
if (view) {
view.innerHTML = renderStatus(stat, webport);
}
}).catch(function() {
let view = document.getElementById('service_status');
if (view) {
view.innerHTML = renderStatus(null, webport);
}
});
});
poll.add(function() {
return L.resolveDefault(getServiceStatus()).then(function(res) {
let view = document.getElementById('service_status');
view.innerHTML = renderStatus(res, webport);
});
});
return E('div', { class: 'cbi-section', id: 'status_bar' }, [
E('p', { id: 'service_status' }, _('Collecting data...'))
]);
};
return E('div', { class: 'cbi-section', id: 'status_bar' }, [
E('p', { id: 'service_status' }, _('Collecting data...'))
]);
}
s = m.section(form.NamedSection, 'config', 'filebrowser');
@@ -1,2 +1,3 @@
#!/bin/sh
[ "$ACTION" = ifup ] && /etc/init.d/mosdns restart
[ "$ACTION" = "ifup" ] || exit 0
[ "$INTERFACE" = "wan" ] && /etc/init.d/mosdns reload
@@ -47,6 +47,11 @@ function waitForElement(selector, callback) {
observer.observe(document.body, { childList: true, subtree: true });
}
function waitForElementId(id, callback) {
waitForElement("#" + CSS.escape(id), callback);
//waitForElement('[id="' + id + '"]', callback);
}
function get_current_url() {
return window.location.origin + window.location.pathname;
}
@@ -192,10 +192,15 @@ o.rmempty = false
o:depends({ _hide_node_option = "1", ['!reverse'] = true })
o = s:option(ListValue, "node", "<a style='color: red'>" .. translate("Proxy Node") .. "</a>")
o.default = ""
o.group = {}
o:depends({ _hide_node_option = false, use_global_config = false })
o.template = m:template_path("/cbi/nodes_listvalue")
o.group = {}
current_node_id = o:formvalue(arg[1])
if not current_node_id then
current_node_id = m:get(arg[1], "node")
end
current_node = current_node_id and m:get(current_node_id) or {}
o = s:option(DummyValue, "_acl_node_bool", "")
o.template = m:template_path("/cbi/hidevalue")
@@ -519,6 +524,8 @@ o.description = desc .. "</ul>"
o:depends({dns_shunt = "dnsmasq", tcp_proxy_mode = "proxy", chn_list = "direct"})
local o_node = s.fields["node"]
local shunt_list = {}
for k, v in pairs(socks_list) do
o_node:value(v.id, v["remark"])
o_node.group[#o_node.group+1] = (v.group and v.group ~= "") and v.group or translate("default")
@@ -528,7 +535,7 @@ for k, v in pairs(nodes_table) do
s.fields["dns_mode"]:depends({ _acl_node_bool = "1" })
break
end
if v.protocol == "_shunt" then
if v.protocol and v.protocol == "_shunt" then
if v.type == "Xray" and has_xray then
o_node:value(v.id, v["remark"])
o_node.group[#o_node.group+1] = (v.group and v.group ~= "") and v.group or translate("default")
@@ -544,6 +551,7 @@ for k, v in pairs(nodes_table) do
s.fields["_node_sel_shunt"]:depends({ node = v.id })
s.fields["remote_rewrite_ttl"]:depends({ _acl_node_bool = "1", node = v.id })
end
shunt_list[#shunt_list + 1] = v
else
o_node:value(v.id, v["remark"])
o_node.group[#o_node.group+1] = (v.group and v.group ~= "") and v.group or translate("default")
@@ -552,4 +560,19 @@ end
m:appendTemplate("/acl/config_footer", {section = arg[1]})
--[[
-- Shunt
if current_node.protocol == "_shunt" then
local shunt_lua = loadfile("/usr/lib/lua/luci/model/cbi/passwall/client/include/shunt_options.lua")
setfenv(shunt_lua, getfenv(1))(m, s, {
s_cfgid = s.section,
node_id = current_node_id,
node = current_node,
verify_option = s.fields["node"]
})
end
m:appendTemplate("/acl/shunt", { shunt_list = api.jsonc.stringify(shunt_list), section = s.section })
]]--
return api.return_map(m)
@@ -139,7 +139,7 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
tips.cfgvalue = function(t, n)
return string.format('<a style="color: red">%s</a>', translate("There are no available nodes, please add or subscribe nodes first."))
end
tips:depends({ node = "", ["!reverse"] = true })
tips:depends("_node", "1")
for k, v in pairs(shunt_list) do
tips:depends("node", v.id)
end
@@ -153,7 +153,7 @@ o = s:taboption("Main", Value, "node_socks_port", translate("Node") .. " Socks "
o.default = 1070
o.placeholder = 1070
o.datatype = "range(1,65535)"
o:depends({ node = "", ["!reverse"] = true })
o:depends("_node", "1")
--[[
if has_singbox or has_xray then
o = s:taboption("Main", Value, "node_http_port", translate("Node") .. " HTTP " .. translate("Listen Port") .. " " .. translate("0 is not use"))
@@ -163,7 +163,12 @@ end
]]--
o = s:taboption("Main", Flag, "node_socks_bind_local", translate("Node") .. " Socks " .. translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
o.default = "1"
o:depends({ node = "", ["!reverse"] = true })
o:depends("_node", "1")
o = s:taboption("Main", DummyValue, "_node", "")
o.template = m:template_path("/cbi/hidevalue")
o.value = "1"
o:depends({ node = "", ['!reverse'] = true })
-- Node → DNS Depends Settings
o = s:taboption("Main", DummyValue, "_node_sel_shunt", "")
@@ -747,7 +752,7 @@ for k, v in pairs(nodes_table) do
if #normal_list == 0 and #iface_list == 0 then
break
end
if v.protocol == "_shunt" then
if v.protocol and v.protocol == "_shunt" then
if has_singbox or has_xray then
o_node:value(v.id, v["remark"])
o_node.group[#o_node.group+1] = (v.group and v.group ~= "") and v.group or translate("default")
@@ -4,6 +4,7 @@ if not data.node_id or not data.node then
return
end
local api = m.api
local s_cfgid = data.s_cfgid
local current_node_id = data.node_id
local node_list = data.node_list or api.get_node_list()
+1 -1
View File
@@ -13,7 +13,7 @@ jsonc = require "luci.jsonc"
i18n = require "luci.i18n"
appname = "passwall"
curl_args = { "-skfL", "--connect-timeout 3", "--retry 3" }
curl_args = { "-skfL", "--connect-timeout 3", "--retry 3", "-H 'Accept: */*'" }
command_timeout = 300
OPENWRT_ARCH = nil
DISTRIB_ARCH = nil
@@ -1196,7 +1196,7 @@ function gen_config(var)
format = format,
path = _type == "local" and w or nil,
url = _type == "remote" and w or nil,
http_client = _type == "remote" and "remote_http_client" or nil,
http_client = (_type == "remote" and version_ge_1_14_0) and "remote_http_client" or nil,
--update_interval = _type == "remote" and "1d" or nil,
}
end
@@ -2281,7 +2281,7 @@ function gen_config(var)
-- 实验性
experimental = experimental,
-- HTTP Client
http_clients = http_clients
http_clients = version_ge_1_14_0 and http_clients or nil,
}
table.insert(outbounds, {
type = "direct",
@@ -0,0 +1,59 @@
<%
local map = self.map
local api = map.api
local appname = map.config
local section = self.section
-%>
<script type="text/javascript">
//<![CDATA[
const shunt_list = JSON.parse('<%=self.shunt_list%>');
document.addEventListener("DOMContentLoaded", () => {
const id = "cbid.<%=appname%>.<%=section%>.node";
let node = null;
const onChange = (e) => {
const new_val = e.target.value;
const new_hasItem = shunt_list.some(element => element.id == new_val);
if (new_hasItem) {
XHR.get('<%=api.url("update_config")%>', {
id: "<%=section%>",
data: JSON.stringify({
node: new_val,
mode: "1"
})
}, function(x, data) {
if (x && x.status == 200 && data.code == 1) {
window.location.reload();
} else {
alert("<%:Error%>");
}
});
} else {
document.getElementById("cbi-<%=appname%>-shunt_option_list")?.style.setProperty("display", "none");
}
};
const check = () => {
const el = document.getElementById(id);
if (el === node) return;
if (node && !el) {
document.getElementById("cbi-<%=appname%>-shunt_option_list")?.style.setProperty("display", "none");
} else {
let o_hasItem = shunt_list.some(element => element.id == el.value);
if (o_hasItem) {
document.getElementById("cbi-<%=appname%>-shunt_option_list")?.style.setProperty("display", "");
}
}
node = el;
if (node) {
node.addEventListener("change", onChange);
}
};
const observer = new MutationObserver(check);
observer.observe(document.body, {
childList: true,
subtree: true
});
check();
});
//]]>
</script>
@@ -421,10 +421,10 @@ table td, .table .td {
<%- else %>
(function() {
if (typeof(cbi_t_switch) === "function") {
var old_switch = cbi_t_switch;
const ori_cbi_t_switch = cbi_t_switch;
cbi_t_switch = function(section, tab) {
dechecked_all_node();
return old_switch(section, tab);
return ori_cbi_t_switch(section, tab);
};
}
})();
@@ -1516,36 +1516,70 @@ table td, .table .td {
//Node list option saving logic
document.addEventListener("DOMContentLoaded", function () {
function onChange(option, value) {
function onChange(option, value, refresh) {
ajax.abortAll();
XHR.get('<%=api.url("save_node_list_opt")%>', {
option: option,
value: value
}, function(x) {
if (x && x.status == 200) {
document.getElementById("node_list").innerHTML = "";
loadNodeList();
if (refresh) {
document.getElementById("node_list").innerHTML = "";
loadNodeList();
}
} else {
alert("<%:Error%>");
}
});
}
waitForElement('input[type="checkbox"][name*="<%=appname%>"][name*="show_node_info"]', function(el) {
el.addEventListener("change", () => {
el.blur();
show_node_info = el.checked ? "1" : "0";
onChange("show_node_info", show_node_info);
function dom_event() {
waitForElement('input[type="checkbox"][name*="<%=appname%>"][name*="show_node_info"]', function(el) {
el.addEventListener("change", () => {
el.blur();
show_node_info = el.checked ? "1" : "0";
onChange("auto_detection_time", auto_detection_time, true);
});
});
});
waitForElement('select[name*="<%=appname%>"][name*="auto_detection_time"]', function(el) {
el.addEventListener("change", () => {
el.blur();
auto_detection_time = el.value;
onChange("auto_detection_time", auto_detection_time);
});
});
<% if api.is_js_luci() then -%>
waitForElement('div[id*="cbid.<%=appname%>"][id*="url_test_url"]', function(el) {
el.addEventListener("cbi-dropdown-change", () => {
if (el.value && (!el.new_val || el.new_val != el.value)) {
onChange("url_test_url", el.value, false);
el.new_val = el.value;
}
});
});
<% else -%>
waitForElement('select[id*="<%=appname%>"][id*="url_test_url"]', function(el) {
el.addEventListener("change", () => {
if (el.value && (!el.new_val || el.new_val != el.value)) {
onChange("url_test_url", el.value, false);
el.new_val = el.value;
}
});
});
waitForElement('input[id*="<%=appname%>"][id*="url_test_url"]', function(el) {
el.addEventListener("change", () => {
if (el.value && (!el.new_val || el.new_val != el.value)) {
onChange("url_test_url", el.value, false);
el.new_val = el.value;
}
});
});
<% end -%>
}
<% if not api.is_js_luci() then -%>
const ori_cbi_d_update = cbi_d_update;
cbi_d_update = function() {
ori_cbi_d_update();
dom_event();
};
<% end -%>
dom_event();
const links = document.querySelectorAll('a');
links.forEach(link => {
@@ -111,7 +111,7 @@ api.uci_foreach_c("haproxy_config", function(t)
if server_node.type ~= "Socks" then
local relay_port = server_node.port
local new_port = api.get_new_port()
local config_file = string.format("haproxy_%s_%s.json", t[".name"], new_port)
local config_file = string.format("%s_%s.json", t[".name"], new_port)
sys.call(string.format('/usr/share/%s/app.sh run_socks "%s"> /dev/null',
appname,
string.format("flag=%s node=%s bind=%s socks_port=%s config_file=%s",
@@ -1060,7 +1060,7 @@ add_firewall_rule() {
$ipt_n -A PSW_OUTPUT $(dst $IPSET_LAN) -j RETURN
$ipt_n -A PSW_OUTPUT $(dst $IPSET_VPS) -j RETURN
[ "${USE_DIRECT_LIST}" = "1" ] && $ipt_n -A PSW_OUTPUT $(dst $IPSET_WHITE) -j RETURN
$ipt_n -A PSW_OUTPUT -m mark --mark 255 -j RETURN
$ipt_n -A PSW_OUTPUT -m mark --mark 0xff/0xff -j RETURN
$ipt_n -N PSW_DNS
if [ $(config_n_get @global[0] dns_redirect "1") = "0" ]; then
@@ -1115,7 +1115,7 @@ add_firewall_rule() {
[ "${USE_BLOCK_LIST}" = "1" ] && $ipt_m -A PSW_OUTPUT $(dst $IPSET_BLOCK) -j MARK --set-mark 88
[ "${USE_DIRECT_LIST}" = "1" ] && $ipt_m -A PSW_OUTPUT $(dst $IPSET_WHITE) -j RETURN
$ipt_m -A PSW_OUTPUT -m conntrack --ctdir REPLY -j RETURN
$ipt_m -A PSW_OUTPUT -m mark --mark 255 -j RETURN
$ipt_m -A PSW_OUTPUT -m mark --mark 0xff/0xff -j RETURN
ip rule add fwmark ${FWMARK} table 999 priority 999
ip route add local 0.0.0.0/0 dev lo table 999
@@ -1130,7 +1130,7 @@ add_firewall_rule() {
$ip6t_n -A PSW_OUTPUT $(dst $IPSET_LAN6) -j RETURN
$ip6t_n -A PSW_OUTPUT $(dst $IPSET_VPS6) -j RETURN
[ "${USE_DIRECT_LIST}" = "1" ] && $ip6t_n -A PSW_OUTPUT $(dst $IPSET_WHITE6) -j RETURN
$ip6t_n -A PSW_OUTPUT -m mark --mark 255 -j RETURN
$ip6t_n -A PSW_OUTPUT -m mark --mark 0xff/0xff -j RETURN
}
$ip6t_n -N PSW_DNS
@@ -1167,7 +1167,7 @@ add_firewall_rule() {
insert_rule_before "$ip6t_m" "PREROUTING" "PSW" "-p tcp -m socket -j PSW_DIVERT"
$ip6t_m -N PSW_OUTPUT
$ip6t_m -A PSW_OUTPUT -m mark --mark 255 -j RETURN
$ip6t_m -A PSW_OUTPUT -m mark --mark 0xff/0xff -j RETURN
$ip6t_m -A PSW_OUTPUT $(dst $IPSET_LAN6) -j RETURN
$ip6t_m -A PSW_OUTPUT $(dst $IPSET_VPS6) -j RETURN
[ "${USE_BLOCK_LIST}" = "1" ] && $ip6t_m -A PSW_OUTPUT $(dst $IPSET_BLOCK6) -j MARK --set-mark 88
@@ -4,7 +4,8 @@
. /usr/share/passwall/utils.sh
LOCK_FILE=${LOCK_PATH}/${CONFIG}_lease2hosts.lock
LEASE_FILE="/tmp/dhcp.leases"
LEASE_FILE=$(uci -q get "dhcp.@dnsmasq[0].leasefile")
LEASE_FILE=${LEASE_FILE:="/tmp/dhcp.leases"}
HOSTS_FILE="$TMP_PATH2/dhcp-hosts"
TMP_FILE="/tmp/dhcp-hosts.tmp"
@@ -1178,7 +1178,7 @@ add_firewall_rule() {
[ "${USE_BLOCK_LIST}" = "1" ] && nft_rule_dual "PSW_OUTPUT_MANGLE" "ip daddr" "$NFTSET_BLOCK" "counter reject"
[ "${USE_DIRECT_LIST}" = "1" ] && nft_rule_dual "PSW_OUTPUT_MANGLE" "ip daddr" "$NFTSET_WHITE" "counter return"
nft "add rule $NFTABLE_NAME PSW_OUTPUT_MANGLE ct direction reply counter return"
nft "add rule $NFTABLE_NAME PSW_OUTPUT_MANGLE meta mark 255 counter return"
nft "add rule $NFTABLE_NAME PSW_OUTPUT_MANGLE meta mark and 0xff == 0xff counter return"
# jump chains
nft "add rule $NFTABLE_NAME mangle_prerouting counter jump PSW_DIVERT"
@@ -1199,7 +1199,7 @@ add_firewall_rule() {
nft "add rule $NFTABLE_NAME PSW_OUTPUT_NAT ip daddr @$NFTSET_VPS counter return"
[ "${USE_BLOCK_LIST}" = "1" ] && nft_rule_dual "PSW_OUTPUT_NAT" "ip daddr" "$NFTSET_BLOCK" "counter reject"
[ "${USE_DIRECT_LIST}" = "1" ] && nft_rule_dual "PSW_OUTPUT_NAT" "ip daddr" "$NFTSET_WHITE" "counter return"
nft "add rule $NFTABLE_NAME PSW_OUTPUT_NAT meta mark 255 counter return"
nft "add rule $NFTABLE_NAME PSW_OUTPUT_NAT meta mark and 0xff == 0xff counter return"
}
#icmp ipv6-icmp redirect
@@ -1239,7 +1239,7 @@ add_firewall_rule() {
[ "${USE_BLOCK_LIST}" = "1" ] && nft_rule_dual "PSW_OUTPUT_MANGLE_V6" "ip6 daddr" "$NFTSET_BLOCK6" "counter reject"
[ "${USE_DIRECT_LIST}" = "1" ] && nft_rule_dual "PSW_OUTPUT_MANGLE_V6" "ip6 daddr" "$NFTSET_WHITE6" "counter return"
nft "add rule $NFTABLE_NAME PSW_OUTPUT_MANGLE_V6 ct direction reply counter return"
nft "add rule $NFTABLE_NAME PSW_OUTPUT_MANGLE_V6 meta mark 255 counter return"
nft "add rule $NFTABLE_NAME PSW_OUTPUT_MANGLE_V6 meta mark and 0xff == 0xff counter return"
[ -n "$IPT_APPEND_DNS" ] && {
local local_dns dns_address dns_port
@@ -103,6 +103,7 @@ local function curl(url, file)
"--connect-timeout 3",
"--max-time 300",
"--speed-limit 51200 --speed-time 15",
"-H 'Accept: */*'",
'-A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36"',
"--dump-header -",
"-w '\\n%{http_code}'"
@@ -1708,6 +1708,7 @@ local function curl(url, file, ua, mode)
"-fskL",
"--retry 3",
"--connect-timeout 3",
"-H 'Accept: */*'",
"-H 'Accept-Encoding: identity'",
"--dump-header -",
"-w '\\n%{http_code}'"
@@ -40,9 +40,10 @@ config_n_get() {
echo "${ret:=$3}"
}
config_t_set() {
config_t_get() {
local index=${4:-0}
local ret=$(uci -q set "${CONFIG}.@${1}[${index}].${2}=${3}" 2>/dev/null)
local ret=$(uci -q get "${CONFIG}.@${1}[${index}].${2}" 2>/dev/null)
echo "${ret:=${3}}"
}
first_type() {
@@ -3,7 +3,7 @@
. /usr/share/passwall2/utils.sh
LOCK_FILE=${LOCK_PATH}/${CONFIG}_lease2hosts.lock
LEASE_FILE=$(config_t_get dnsmasq leasefile "/tmp/dhcp.leases")
LEASE_FILE=$(uci -q get dhcp.@dnsmasq[0].leasefile || echo "/tmp/dhcp.leases")
HOSTS_FILE="$TMP_PATH2/dhcp-hosts"
TMP_FILE="/tmp/dhcp-hosts.tmp"
-22
View File
@@ -1,22 +0,0 @@
# Copyright (C) 2020 Gyj1109
# 适配 OpenWrt 25.12 修改版
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-syncthing
PKG_VERSION:=1.0
PKG_RELEASE:=3
LUCI_TITLE:=LuCI support for Syncthing
LUCI_PKGARCH:=all
# 适配 25.12:确保安装了 syncthing 后,LuCI 界面能正确拉起
LUCI_DEPENDS:=+syncthing
include $(TOPDIR)/feeds/luci/luci.mk
# 明确定义配置文件的归属,这对 25.12 的 apk 管理器非常重要
define Package/$(PKG_NAME)/conffiles
/etc/config/syncthing
endef
$(eval $(call BuildPackage,$(PKG_NAME)))
-2
View File
@@ -1,2 +0,0 @@
# luci-app-syncthing
在Potat0000源码基础上进行了汉化优化,官方openwrt23.05.3编译后可使用
@@ -1,17 +0,0 @@
module("luci.controller.syncthing", package.seeall)
function index()
if not nixio.fs.access("/etc/config/syncthing") then
return
end
entry({"admin", "services", "syncthing"}, cbi("syncthing"), _("文件同步"), 10).dependent = true
entry({"admin", "services", "syncthing", "status"}, call("act_status")).leaf = true
end
function act_status()
local e = {}
e.running = luci.sys.call("pgrep syncthing >/dev/null") == 0
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
@@ -1,48 +0,0 @@
require("nixio.fs")
m = Map("syncthing", translate("Syncthing同步工具"))
m:section(SimpleSection).template = "syncthing/syncthing_status"
s = m:section(TypedSection, "syncthing")
s.anonymous = true
o = s:option(Flag, "enabled", translate("启用"))
o.default = 0
o.rmempty = false
gui_address = s:option(Value, "gui_address", translate("GUI访问地址"))
gui_address.description = translate("使用0.0.0.0以监控所有访问。")
gui_address.default = "http://0.0.0.0:8384"
gui_address.placeholder = "http://0.0.0.0:8384"
gui_address.rmempty = false
home = s:option(Value, "home", translate("配置文件目录"))
home.description = translate("只有保存在/etc/syncthing中的配置会自动备份!")
home.default = "/etc/syncthing"
home.placeholder = "/etc/syncthing"
home.rmempty = false
user = s:option(ListValue, "user", translate("用户"))
user.description = translate("默认是syncthing,但这可能会导致权限被拒绝。Syncthing官方不建议以root身份运行。")
user:value("", translate("syncthing"))
for u in luci.util.execi("cat /etc/passwd | cut -d ':' -f1") do
user:value(u)
end
macprocs = s:option(Value, "macprocs", translate("线程限制"))
macprocs.description = translate("0表示匹配CPU数量(默认),>0表示显式指定并发数。")
macprocs.default = "0"
macprocs.placeholder = "0"
macprocs.datatype = "range(0,32)"
macprocs.rmempty = false
nice = s:option(Value, "nice", translate("优先级"))
nice.description = translate("显式指定优先级值。0是最高,19是最低。(暂时不允许设置负值)")
nice.default = "19"
nice.placeholder = "19"
nice.datatype = "range(0,19)"
nice.rmempty = false
return m
@@ -1,27 +0,0 @@
<script type="text/javascript">//<![CDATA[
XHR.poll(1, '<%=url([[admin]], [[services]], [[syncthing]], [[status]])%>', null,
function (x, data) {
var tb = document.getElementById('syncthing_status');
if (data && tb) {
if (data.running) {
var links = '<em><b><font color="green">Syncthing <%:运行中%></font></b></em><input class="btn cbi-button mar-10" type="button" value="<%:打开Syncthing页面%>" onclick="openwebui();" />';
tb.innerHTML = links;
} else {
tb.innerHTML = '<em><b><font color="red">Syncthing <%:未运行%></font></b></em>';
}
}
}
);
function openwebui(){
var url = window.location.host+":<%=luci.sys.exec("uci -q get syncthing.syncthing.gui_address"):match(":[0-9]+"):gsub(":", "")%>";
window.open('http://'+url,'target','');
}
//]]>
</script>
<style>.mar-10 {margin-left: 50px; margin-right: 10px;}</style>
<fieldset class="cbi-section">
<p id="syncthing_status">
<em><%:正在收集数据...%></em>
</p>
</fieldset>
@@ -1,12 +0,0 @@
#!/bin/sh
touch /etc/config/syncthing
uci -q batch <<-EOF >/dev/null
delete ucitrack.@syncthing[-1]
add ucitrack syncthing
set ucitrack.@syncthing[-1].exec='/etc/init.d/syncthing stop && /etc/init.d/syncthing start'
commit ucitrack
EOF
# remove LuCI cache
rm -f /tmp/luci*
exit 0
@@ -1,11 +0,0 @@
{
"luci-app-syncthing": {
"description": "Grant UCI access for luci-app-syncthing",
"read": {
"uci": [ "syncthing" ]
},
"write": {
"uci": [ "syncthing" ]
}
}
}