From f28e441b8ee69cc1e2c30f5a587ffeda3e97c4ef Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 30 Mar 2026 14:49:17 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=B6=20Sync=202026-03-30=2014:49:16?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- luci-app-timewol/Makefile | 18 ++- .../luasrc/controller/timewol.lua | 45 ++----- luci-app-timewol/luasrc/model/cbi/timewol.lua | 115 +++++++++--------- .../luasrc/view/timewol/awake.htm | 3 - .../luasrc/view/timewol/index.htm | 18 --- luci-app-timewol/po/zh-cn | 1 - .../po/{zh_Hans => zh-cn}/timewol.po | 3 - luci-app-timewol/po/zh_Hans | 1 + luci-app-timewol/root/etc/init.d/timewol | 93 ++++++-------- 9 files changed, 110 insertions(+), 187 deletions(-) delete mode 100644 luci-app-timewol/luasrc/view/timewol/awake.htm delete mode 120000 luci-app-timewol/po/zh-cn rename luci-app-timewol/po/{zh_Hans => zh-cn}/timewol.po (95%) create mode 120000 luci-app-timewol/po/zh_Hans diff --git a/luci-app-timewol/Makefile b/luci-app-timewol/Makefile index c8c5e2cc..2f4faea0 100644 --- a/luci-app-timewol/Makefile +++ b/luci-app-timewol/Makefile @@ -1,5 +1,4 @@ -# Copyright (C) 2016 Openwrt.org -# Copyright (C) 2024 iv7777 +# Copyright (C) 2025 Openwrt.org # # This is free software, licensed under the Apache License, Version 2.0 . # @@ -7,15 +6,14 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI support for Timewol -LUCI_PKGARCH:=all -LUCI_DEPENDS:=+etherwake +PKG_VERSION:=20250407 +PKG_RELEASE:=2 -define Package/luci-app-timewol/postinst - #!/bin/sh - if [ -z "$${IPKG_INSTROOT}" ]; then - chmod +x /etc/init.d/timewol - fi - exit 0 +LUCI_DEPENDS:=+luci-base +etherwake +LUCI_PKGARCH:=all + +define Package/luci-app-timewol/conffiles +/etc/config/timewol endef include $(TOPDIR)/feeds/luci/luci.mk diff --git a/luci-app-timewol/luasrc/controller/timewol.lua b/luci-app-timewol/luasrc/controller/timewol.lua index ec32eb29..b7b739dd 100644 --- a/luci-app-timewol/luasrc/controller/timewol.lua +++ b/luci-app-timewol/luasrc/controller/timewol.lua @@ -1,46 +1,21 @@ module("luci.controller.timewol", package.seeall) -local x = luci.model.uci.cursor() - function index() - if not nixio.fs.access("/etc/config/timewol") then return end + if not nixio.fs.access("/etc/config/timewol") then return end - entry({"admin", "control"}, firstchild(), "Control", 44).dependent = false - local page = entry({"admin", "control", "timewol"}, cbi("timewol"), _("Timed WOL")) + entry({"admin", "control"}, firstchild(), "Control", 44).dependent = false + + local page = entry({"admin", "control", "timewol"}, cbi("timewol"), _("Timed WOL")) page.order = 95 page.dependent = true page.acl_depends = { "luci-app-timewol" } - entry({"admin", "control", "timewol", "status"}, call("status")).leaf = true - entry( {"admin", "control", "timewol", "awake"}, call("awake") ).leaf = true + + entry({"admin", "control", "timewol", "status"}, call("status")).leaf = true end function status() - local e = {} - e.status = luci.sys.call("cat /etc/crontabs/root |grep etherwake >/dev/null") == 0 - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end - -function awake(sections) - lan = x:get("timewol",sections,"maceth") - mac = x:get("timewol",sections,"macaddr") - local e = {} - cmd = "/usr/bin/etherwake -D -i " .. lan .. " -b " .. mac .. " 2>&1" - local p = io.popen(cmd) - local msg = "" - if p then - while true do - local l = p:read("*l") - if l then - if #l > 100 then l = l:sub(1, 100) .. "..." end - msg = msg .. l - else - break - end - end - p:close() - end - e["data"] = msg - luci.http.prepare_content("application/json") - luci.http.write_json(e) + local e = {} + e.status = luci.sys.call("cat /etc/crontabs/root | grep -v '^[ \t]*#' | grep etherwake >/dev/null") == 0 + luci.http.prepare_content("application/json") + luci.http.write_json(e) end diff --git a/luci-app-timewol/luasrc/model/cbi/timewol.lua b/luci-app-timewol/luasrc/model/cbi/timewol.lua index 3964a126..695e6779 100644 --- a/luci-app-timewol/luasrc/model/cbi/timewol.lua +++ b/luci-app-timewol/luasrc/model/cbi/timewol.lua @@ -1,93 +1,90 @@ local sys = require "luci.sys" +local m, s, o -- Create the main map object -local map = Map("timewol", translate("Timed Wake on LAN"), - translate("Wake up your local area network devices on schedule")) -map.template = "timewol/index" +m = Map("timewol", translate("Timed Wake on LAN"), + translate("Wake up your local area network devices on schedule")) +m.template = "timewol/index" -- Running Status Section -local status_section = map:section(TypedSection, "basic", translate("Running Status")) -status_section.anonymous = true +s = m:section(TypedSection, "basic", translate("Running Status")) +s.anonymous = true -local status = status_section:option(DummyValue, "timewol_status", translate("Current Status")) -status.template = "timewol/timewol" -status.value = translate("Collecting data...") +o = s:option(DummyValue, "timewol_status", translate("Current Status")) +o.template = "timewol/timewol" +o.value = translate("Collecting data...") -- Basic Settings Section -local basic_section = map:section(TypedSection, "basic", translate("Basic Settings")) -basic_section.anonymous = true +s = m:section(TypedSection, "basic", translate("Basic Settings")) +s.anonymous = true -local enable = basic_section:option(Flag, "enable", translate("Enable")) -enable.rmempty = false +o = s:option(Flag, "enable", translate("Enable")) +o.rmempty = false -- Client Settings Section -local client_section = map:section(TypedSection, "macclient", translate("Client Settings")) -client_section.template = "cbi/tblsection" -client_section.anonymous = true -client_section.addremove = true +s = m:section(TypedSection, "macclient", translate("Client Settings")) +s.template = "cbi/tblsection" +s.anonymous = true +s.addremove = true + +o = s:option(Flag, "enable", translate("Enable")) +o.default = 1 +o.rmempty = false -- Client MAC Address -local mac_addr = client_section:option(Value, "macaddr", translate("Client MAC")) -mac_addr.rmempty = false +o = s:option(Value, "macaddr", translate("Client MAC")) +o.rmempty = false sys.net.mac_hints(function(mac, hint) - mac_addr:value(mac, string.format("%s (%s)", mac, hint)) + o:value(mac, string.format("%s (%s)", mac, hint)) end) -- Network Interface -local net_iface = client_section:option(Value, "maceth", translate("Network Interface")) -net_iface.rmempty = false -net_iface.default = "br-lan" +o = s:option(Value, "maceth", translate("Network Interface")) +o.rmempty = false +o.default = "br-lan" for _, device in ipairs(sys.net.devices()) do - if device ~= "lo" then - net_iface:value(device) - end + if device ~= "lo" then + o:value(device) + end end --- wake device -local btn = client_section:option(Button, "_awake",translate("Wake Up Host")) -btn.inputtitle = translate("Awake") -btn.inputstyle = "apply" -btn.disabled = false -btn.template = "timewol/awake" - -- Function to validate cron field values local function validate_cron_field(option_name, value, min, max, default) - if value == "" then - return default - elseif value == "*" then - return value - end - local num = tonumber(value) - if num and num >= min and num <= max then - return value - else - return nil, translatef("Invalid value for %s: %s. Must be between %d and %d or '*'", option_name, value, min, max) - end + if value == "" then + return default + elseif value == "*" then + return value + end + local num = tonumber(value) + if num and num >= min and num <= max then + return value + else + return nil, translatef("Invalid value for %s: %s. Must be between %d and %d or '*'", option_name, value, min, max) + end end -- Scheduling Options with Default Values and Range Checks local schedule_options = { - { "minute", translate("Minute"), 0, 59, "0" }, - { "hour", translate("Hour"), 0, 23, "0" }, - { "day", translate("Day"), 1, 31, "*" }, - { "month", translate("Month"), 1, 12, "*" }, - { "weeks", translate("Week"), 0, 6, "*" } -- 0 for Sunday, 6 for Saturday + { "minute", translate("Minute"), 0, 59, "0" }, + { "hour", translate("Hour"), 0, 23, "0" }, + { "day", translate("Day"), 1, 31, "*" }, + { "month", translate("Month"), 1, 12, "*" }, + { "weeks", translate("Week"), 0, 6, "*" } -- 0 for Sunday, 6 for Saturday } for _, opt in ipairs(schedule_options) do - local field = client_section:option(Value, opt[1], opt[2]) - field.default = opt[5] or opt[4] -- Use default value if present, otherwise use maximum value - field.optional = false - field.validate = function(self, value) - return validate_cron_field(opt[2], value, opt[3], opt[4], field.default) - end + o = s:option(Value, opt[1], opt[2]) + o.default = opt[5] or opt[4] -- Use default value if present, otherwise use maximum value + o.optional = false + o.validate = function(self, value) + return validate_cron_field(opt[2], value, opt[3], opt[4], o.default) + end end -- Apply the configuration changes -map.apply_on_parse = true -function map.on_apply(self) - sys.exec("/etc/init.d/timewol restart") +m.apply_on_parse = true +function m.on_apply(self) + sys.exec("/etc/init.d/timewol restart") end -return map - +return m diff --git a/luci-app-timewol/luasrc/view/timewol/awake.htm b/luci-app-timewol/luasrc/view/timewol/awake.htm deleted file mode 100644 index 91cd71b1..00000000 --- a/luci-app-timewol/luasrc/view/timewol/awake.htm +++ /dev/null @@ -1,3 +0,0 @@ -<%+cbi/valueheader%> - " style="font-size: 100%;" type="button" onclick="onclick_awake(this.id)" <%=attr("name", section) .. attr("id", cbid) .. attr("value", self.inputtitle)%> /> -<%+cbi/valuefooter%> diff --git a/luci-app-timewol/luasrc/view/timewol/index.htm b/luci-app-timewol/luasrc/view/timewol/index.htm index b06f2cf5..d11dc158 100644 --- a/luci-app-timewol/luasrc/view/timewol/index.htm +++ b/luci-app-timewol/luasrc/view/timewol/index.htm @@ -14,23 +14,5 @@ status.innerHTML = result.status?'<%=translate("RUNNING")%>':'<%=translate("NOT RUNNING")%>'; } ) - function _id2section(id) { - var x = id.split("."); - return x[2]; - } - function onclick_awake(id) { - var section = _id2section(id); - var btnXHR = new XHR(); - btnXHR.post('<%=url([[admin]], [[control]], [[timewol]], [[awake]])%>/' + section, { token: '<%=token%>' }, - function(x, data) { - if (x.responseText == "_uncommitted_") { - txt="<%:Please [Save & Apply] your changes first%>"; - alert( txt.replace(new RegExp("<%:&%>", "g"), "&") ); - } else { - alert( JSON.parse(x.response).data ); - } - } - ); - } //]]> diff --git a/luci-app-timewol/po/zh-cn b/luci-app-timewol/po/zh-cn deleted file mode 120000 index 8d69574d..00000000 --- a/luci-app-timewol/po/zh-cn +++ /dev/null @@ -1 +0,0 @@ -zh_Hans \ No newline at end of file diff --git a/luci-app-timewol/po/zh_Hans/timewol.po b/luci-app-timewol/po/zh-cn/timewol.po similarity index 95% rename from luci-app-timewol/po/zh_Hans/timewol.po rename to luci-app-timewol/po/zh-cn/timewol.po index 6ab3e79d..994ea8b0 100644 --- a/luci-app-timewol/po/zh_Hans/timewol.po +++ b/luci-app-timewol/po/zh-cn/timewol.po @@ -34,9 +34,6 @@ msgstr "客户端MAC" msgid "Network Interface" msgstr "网络接口" -msgid "Awake" -msgstr "立即唤醒" - msgid "Minute" msgstr "分钟" diff --git a/luci-app-timewol/po/zh_Hans b/luci-app-timewol/po/zh_Hans new file mode 120000 index 00000000..41451e4a --- /dev/null +++ b/luci-app-timewol/po/zh_Hans @@ -0,0 +1 @@ +zh-cn \ No newline at end of file diff --git a/luci-app-timewol/root/etc/init.d/timewol b/luci-app-timewol/root/etc/init.d/timewol index 41f31de8..875b6b1a 100755 --- a/luci-app-timewol/root/etc/init.d/timewol +++ b/luci-app-timewol/root/etc/init.d/timewol @@ -1,8 +1,6 @@ #!/bin/sh /etc/rc.common # -# Copyright (C) 2015 OpenWrt-dist -# Copyright (C) 2016 fw867 -# Copyright (C) 2024 iv7777 +# Copyright (C) 2025 OpenWrt.org # # This is free software, licensed under the GNU General Public License v3. # See /LICENSE for more information. @@ -13,75 +11,54 @@ CONFIG=timewol CRONTAB_FILE="/etc/crontabs/root" ETHERWAKE_CMD="/usr/bin/etherwake" -# Function to get UCI configuration values with defaults -uci_get_by_type() { - local type=$1 - local option=$2 - local default=$3 - local index=${4:-0} # Use 0 if $4 is not provided - - local value - value=$(uci get "$CONFIG.@$type[$index].$option" 2>/dev/null) || value=$default - echo "$value" +config_n_get() { + local ret=$(uci -q get "${CONFIG}.${1}.${2}" 2>/dev/null) + echo "${ret:=$3}" } -# Function to check if a value represents a true boolean is_true() { - case "$1" in - 1|on|true|yes|enabled) return 0 ;; - *) return 1 ;; - esac + case "$1" in + 1|on|true|yes|enabled) return 0 ;; + *) return 1 ;; + esac } -# Function to load configuration and check if enabled load_config() { - local enabled - enabled=$(uci_get_by_type basic enable "0") - is_true "$enabled" + local enabled=$(config_n_get @basic[0] enable 0) + is_true "$enabled" } -# Function to add WoL rules to the crontab add_rule() { - # Remove existing etherwake entries - sed -i '/etherwake/d' "$CRONTAB_FILE" + sed -i '/etherwake/d' "$CRONTAB_FILE" - for i in $(seq 0 100); do - local macaddr - local maceth - local minute - local hour - local day - local month - local weeks - - macaddr=$(uci_get_by_type macclient macaddr "" "$i") - maceth=$(uci_get_by_type macclient maceth "" "$i") - - # Stop if no more macaddr entries - [ -z "$macaddr" ] && break - [ -z "$maceth" ] && break - - minute=$(uci_get_by_type macclient minute "0" "$i") - hour=$(uci_get_by_type macclient hour "*" "$i") - day=$(uci_get_by_type macclient day "*" "$i") - month=$(uci_get_by_type macclient month "*" "$i") - weeks=$(uci_get_by_type macclient weeks "*" "$i") - - echo "$minute $hour $day $month $weeks $ETHERWAKE_CMD -D -i $maceth $macaddr" >> "$CRONTAB_FILE" - done + local ids=$(uci show $CONFIG | grep "=macclient" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') + [ -n "$ids" ] && { + for id in $ids; do + local enabled=$(config_n_get $id enable 0) + local macaddr=$(config_n_get $id macaddr) + local maceth=$(config_n_get $id maceth) + [ $enabled -eq 1 ] && [ -n "$macaddr" ] && [ -n "$maceth" ] && { + local minute=$(config_n_get $id minute "0") + local hour=$(config_n_get $id hour "*") + local day=$(config_n_get $id day "*") + local month=$(config_n_get $id month "*") + local weeks=$(config_n_get $id weeks "*") + echo "$minute $hour $day $month $weeks $ETHERWAKE_CMD -D -i $maceth $macaddr" >> "$CRONTAB_FILE" + } + done + } } -# Function to start the service start() { - if load_config; then - add_rule - else - exit 0 - fi + if load_config; then + add_rule + /etc/init.d/cron restart + else + exit 0 + fi } -# Function to stop the service stop() { - # Remove etherwake entries from crontab - sed -i '/etherwake/d' "$CRONTAB_FILE" + sed -i '/etherwake/d' "$CRONTAB_FILE" + /etc/init.d/cron restart }