1
0
mirror of https://github.com/kenzok8/small-package synced 2025-09-18 18:51:16 +08:00

update-12.04

This commit is contained in:
github-actions[bot]
2021-12-04 09:01:13 +08:00
parent d9bed163f5
commit 96e6f38956
110 changed files with 14091 additions and 382 deletions

View File

@ -47,7 +47,7 @@ config CDNSPEEDTEST_COMPRESS_GOPROXY
config CDNSPEEDTEST_COMPRESS_UPX
bool "Compress executable files with UPX"
depends on !mips64
default y if mips||mipsel
default n
endef
ifeq ($(CONFIG_CDNSPEEDTEST_COMPRESS_GOPROXY),y)

View File

@ -11,9 +11,9 @@ PKG_ARCH_DDNSTO:=$(ARCH)
PKG_NAME:=ddnsto
PKG_VERSION:=0.3.0
PKG_RELEASE:=1
PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://firmware.koolshare.cn/binary/ddnsto/
PKG_SOURCE_URL:=http://fw.koolcenter.com/binary/ddnsto/
PKG_HASH:=skip
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-binary-$(PKG_VERSION)
@ -40,6 +40,13 @@ define Package/$(PKG_NAME)/conffiles
/etc/config/ddnsto
endef
define Package/$(PKG_NAME)/postinst
#!/bin/sh
if [ -z "$${IPKG_INSTROOT}" ]; then
[ -f /etc/uci-defaults/ddnsto ] && /etc/uci-defaults/ddnsto && rm -f /etc/uci-defaults/ddnsto
fi
endef
define Build/Configure
endef

View File

@ -5,14 +5,14 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=libcron
PKG_VERSION:=1.3.0
PKG_RELEASE:=$(AUTORELEASE)
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/PerMalmberg/libcron.git
PKG_SOURCE_DATE:=2020-12-04
PKG_SOURCE_VERSION:=b0046755bda166dde253e33f68a5b0a1c3ed387e
PKG_SOURCE_DATE:=2021-11-22
PKG_SOURCE_VERSION:=d4679b7c3cd7b03bf3865dc1709f1d1133fb7ee1
PKG_MIRROR_HASH:=skip
PKG_VERSION:=1.3.0-$(call version_abbrev,$(PKG_SOURCE_VERSION))
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=LICENSE
@ -32,15 +32,8 @@ define Package/libcron
endef
define Package/libcron/description
Libcron offers an easy to use API to add callbacks with corresponding cron-formatted strings.
endef
define Build/Install
$(INSTALL_DIR) $(PKG_INSTALL_DIR)/usr/lib/
$(CP) $(PKG_BUILD_DIR)/libcron/out/Release/liblibcron.a $(PKG_INSTALL_DIR)/usr/lib/
$(INSTALL_DIR) $(PKG_INSTALL_DIR)/usr/include/libcron/
$(CP) $(PKG_BUILD_DIR)/libcron/include/* $(PKG_INSTALL_DIR)/usr/include/
$(CP) $(PKG_BUILD_DIR)/libcron/externals/date/include/* $(PKG_INSTALL_DIR)/usr/include/
Libcron offers an easy to use API to add callbacks with corresponding
cron-formatted strings.
endef
$(eval $(call BuildPackage,libcron))

65
linkease/Makefile Normal file
View File

@ -0,0 +1,65 @@
#
# Copyright (C) 2015-2016 OpenWrt.org
# Copyright (C) 2020 jjm2473@gmail.com
#
# This is free software, licensed under the GNU General Public License v3.
#
include $(TOPDIR)/rules.mk
PKG_ARCH_LINKEASE:=$(ARCH)
PKG_NAME:=linkease
PKG_VERSION:=0.3.66
PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=http://fw.koolcenter.com/binary/LinkEase/LinuxStorage/
PKG_HASH:=skip
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-binary-$(PKG_VERSION)
PKG_BUILD_PARALLEL:=1
PKG_USE_MIPS16:=0
include $(INCLUDE_DIR)/package.mk
define Package/$(PKG_NAME)
SECTION:=net
CATEGORY:=Network
SUBMENU:=Web Servers/Proxies
TITLE:=LinkEase - the file cloud
DEPENDS:=
URL:=https://www.ddnsto.com/linkease/
endef
define Package/$(PKG_NAME)/description
LinkEase is a file cloud
endef
define Package/$(PKG_NAME)/conffiles
/etc/config/linkease
endef
define Package/$(PKG_NAME)/postinst
#!/bin/sh
if [ -z "$${IPKG_INSTROOT}" ]; then
[ -f /etc/uci-defaults/linkease ] && /etc/uci-defaults/linkease && rm -f /etc/uci-defaults/linkease
fi
endef
define Build/Configure
endef
define Build/Compile
endef
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/sbin/linkease-plugins $(1)/etc/config $(1)/etc/init.d $(1)/etc/uci-defaults
$(INSTALL_BIN) $(PKG_BUILD_DIR)/linkease.$(PKG_ARCH_LINKEASE) $(1)/usr/sbin/linkease
$(INSTALL_BIN) ./files/aria2.sh $(1)/usr/sbin/linkease-plugins/aria2.sh
$(INSTALL_CONF) ./files/linkease.config $(1)/etc/config/linkease
$(INSTALL_BIN) ./files/linkease.init $(1)/etc/init.d/linkease
$(INSTALL_BIN) ./files/linkease.uci-default $(1)/etc/uci-defaults/linkease
endef
$(eval $(call BuildPackage,$(PKG_NAME)))

134
linkease/files/aria2.sh Executable file
View File

@ -0,0 +1,134 @@
#!/bin/bash
sh_ver="1.0.0"
export PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/sbin:/bin
aria2_conf_dir=/var/etc/aria2/
#替换成你设备aria2.conf路径
aria2_conf=${aria2_conf_dir}/aria2.conf.main
#替换成你设备的aria2c路径
aria2c=/usr/bin/aria2c
Green_font_prefix="\033[32m"
Red_font_prefix="\033[31m"
Green_background_prefix="\033[42;37m"
Red_background_prefix="\033[41;37m"
Font_color_suffix="\033[0m"
Info="[${Green_font_prefix}信息${Font_color_suffix}]"
Error="[${Red_font_prefix}错误${Font_color_suffix}]"
Tip="[${Green_font_prefix}注意${Font_color_suffix}]"
error_code=11
success_code=0
return_error(){
echo 'Content-Type:application/json;charset=utf-8'
echo
echo "{
"\"success\"":$error_code,
"\"error\"":"\"$1\"",
"\"result"\":null
}"
exit 1
}
return_ok(){
echo 'Content-Type:application/json;charset=utf-8'
echo
echo "{
"\"success\"":$success_code,
"\"error\"":"\"$1\"",
"\"result"\":null
}"
exit 0
}
return_result(){
echo 'Content-Type:application/json;charset=utf-8'
echo
echo "{
"\"success\"":$success_code,
"\"error\"":"\"\"",
"\"result"\":$1
}"
exit 0
}
#进程中是否运行aria2
check_pid() {
PID=$(ps -ef | grep "aria2c" | grep -v grep | grep -v "aria2.sh" | grep -v "init.d" | grep -v "service" | awk '{print $2}')
}
#aria2是否正在运行
aria2_work_status(){
check_pid
# [[ ! -z ${PID} ]] && echo -e "${Error} Aria2 正在运行,请检查 !" && exit 1
[[ ! -z ${PID} ]] && return_ok "Aria2正在运行"
return_error "Aria2未运行"
}
#检测设备是否安装aria2
check_installed_status() {
[[ ! -e ${aria2c} ]] && return_error "Aria2 没有安装,请检查 !"
[[ ! -e ${aria2_conf} ]] && return_error "Aria2 配置文件不存在,请检查 !"
# return_ok "Aria2已安装"
}
#读取aria2配置信息
read_config() {
check_installed_status
if [[ ! -e ${aria2_conf} ]]; then
return_error "Aria2 配置文件不存在,请检查 !"
else
conf_text=$(cat ${aria2_conf} | grep -v '#')
aria2_dir=$(echo -e "${conf_text}" | grep "^dir=" | awk -F "=" '{print $NF}')
aria2_port=$(echo -e "${conf_text}" | grep "^rpc-listen-port=" | awk -F "=" '{print $NF}')
aria2_passwd=$(echo -e "${conf_text}" | grep "^rpc-secret=" | awk -F "=" '{print $NF}')
aria2_bt_port=$(echo -e "${conf_text}" | grep "^listen-port=" | awk -F "=" '{print $NF}')
aria2_dht_port=$(echo -e "${conf_text}" | grep "^dht-listen-port=" | awk -F "=" '{print $NF}')
return_result "{
"\"dir"\":"\"$aria2_dir"\",
"\"rpc-listen-port"\":"\"$aria2_port"\",
"\"rpc-secret"\":"\"$aria2_passwd"\",
"\"listen-port"\":"\"$aria2_bt_port"\",
"\"dht-listen-port"\":"\"$aria2_dht_port"\"}"
fi
}
#"Content-Type:text/html;charset=utf-8"
#echo
#SERVER_SOFTWARE = $SERVER_SOFTWARE #服务器软件
#SERVER_NAME = $SERVER_NAME #服务器主机名
#GATEWAY_INTERFACE = $GATEWAY_INTERFACE #CGI版本
#SERVER_PROTOCOL = $SERVER_PROTOCOL #通信使用的协议
#SERVER_PORT = $SERVER_PORT #服务器的端口号
#REQUEST_METHOD = $REQUEST_METHOD #请求方法(GET/POST/PUT/DELETE..)
#HTTP_ACCEPT = $HTTP_ACCEPT #HTTP定义的浏览器能够接受的数据类型
#SCRIPT_NAME = $SCRIPT_NAME #当前运行的脚本名称(包含路径)
#QUERY_STRING = $QUERY_STRING #地址栏中传的数据get方式
#REMOTE_ADDR = $REMOTE_ADDR #客户端的ip
#根据url QUERY调不同方法
query(){
aria2Query=${QUERY_STRING}
parse(){
echo $1 | sed 's/.*'$2'=\([[:alnum:]]*\).*/\1/'
}
value=$(parse $aria2Query "action")
if [ ! -z = "$value" ]
then
if [ "$value" = "status" ]
then
check_installed_status
elif [ "$value" = "readConfig" ]
then
read_config
elif [ "$value" = "workStatus" ]
then
aria2_work_status
else
echo
fi
else
return_error "action不能为空"
fi
}
query

View File

@ -0,0 +1,3 @@
config linkease
option 'port' '8897'
option 'enabled' '1'

23
linkease/files/linkease.init Executable file
View File

@ -0,0 +1,23 @@
#!/bin/sh /etc/rc.common
START=99
USE_PROCD=1
get_config() {
config_get_bool enabled $1 enabled 1
config_get_bool logger $1 logger
config_get port $1 port 8897
}
start_service() {
config_load linkease
config_foreach get_config linkease
[ $enabled != 1 ] && return 1
procd_open_instance
procd_set_param command /usr/sbin/linkease
[ -n "$port" ] && procd_append_param command --deviceAddr ":$port"
[ "$logger" == 1 ] && procd_set_param stderr 1
procd_set_param respawn
procd_close_instance
}

View File

@ -0,0 +1,22 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@linkease[-1]
add ucitrack linkease
set ucitrack.@linkease[-1].init=linkease
commit ucitrack
delete firewall.linkease
set firewall.linkease=rule
set firewall.linkease.name="linkease"
set firewall.linkease.target="ACCEPT"
set firewall.linkease.src="wan"
set firewall.linkease.proto="tcp"
set firewall.linkease.dest_port="8897"
commit firewall
EOF
/etc/init.d/linkease enable
/etc/init.d/linkease start
exit 0

View File

@ -0,0 +1,14 @@
#
#-- Copyright (C) 2018 dz <dingzhong110@gmail.com>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI Support for advancedsetting
LUCI_DEPENDS:=
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,14 @@
#-- Copyright (C) 2018 dz <dingzhong110@gmail.com>
module("luci.controller.advancedsetting", package.seeall)
function index()
if not nixio.fs.access("/etc/config/advancedsetting") then
return
end
local page
page = entry({"admin", "system", "advancedsetting"}, cbi("advancedsetting"), _("Advanced Setting"), 60)
page.dependent = true
page.acl_depends = { "luci-app-advancedsetting" }
end

View File

@ -0,0 +1,75 @@
#-- Copyright (C) 2018 dz <dingzhong110@gmail.com>
local fs = require "nixio.fs"
local sys = require "luci.sys"
m = Map("advancedsetting", translate("Advanced Setting"), translate("Direct editing of built-in Script Documents for various services, unless you know what you are doing, do not easily modify these configuration documents"))
s = m:section(TypedSection, "advancedsetting")
s.anonymous=true
--dnsmasq
if nixio.fs.access("/etc/dnsmasq.conf") then
s:tab("config1", translate("dnsmasq"),translate("This page is the document content for configuring /etc/dnsmasq.conf. Restart takes effect after application is saved"))
conf = s:taboption("config1", Value, "editconf1", nil, translate("Each line of the opening numeric symbol (#) or semicolon (;) is considered a comment; delete (;) and enable the specified option."))
conf.template = "cbi/tvalue"
conf.rows = 20
conf.wrap = "off"
function conf.cfgvalue(self, section)
return fs.readfile("/etc/dnsmasq.conf") or ""
end
function conf.write(self, section, value)
if value then
value = value:gsub("\r\n?", "\n")
fs.writefile("/tmp/dnsmasq.conf", value)
if (luci.sys.call("cmp -s /tmp/dnsmasq.conf /etc/dnsmasq.conf") == 1) then
fs.writefile("/etc/dnsmasq.conf", value)
luci.sys.call("/etc/init.d/dnsmasq restart >/dev/null")
end
fs.remove("/tmp/dnsmasq.conf")
end
end
end
--network
if nixio.fs.access("/etc/config/network") then
s:tab("config2", translate("network"),translate("This page is the document content for configuring /etc/config/network. Restart takes effect after application is saved"))
conf = s:taboption("config2", Value, "editconf2", nil, translate("Each line of the opening numeric symbol (#) or semicolon (;) is considered a comment; delete (;) and enable the specified option."))
conf.template = "cbi/tvalue"
conf.rows = 20
conf.wrap = "off"
function conf.cfgvalue(self, section)
return fs.readfile("/etc/config/network") or ""
end
function conf.write(self, section, value)
if value then
value = value:gsub("\r\n?", "\n")
fs.writefile("/tmp/netwok", value)
if (luci.sys.call("cmp -s /tmp/network /etc/config/network") == 1) then
fs.writefile("/etc/config/network", value)
luci.sys.call("/etc/init.d/network restart >/dev/null")
end
fs.remove("/tmp/network")
end
end
end
--hosts
if nixio.fs.access("/etc/hosts") then
s:tab("config3", translate("hosts"),translate("This page is the document content for configuring /etc/hosts. Restart takes effect after application is saved"))
conf = s:taboption("config3", Value, "editconf3", nil, translate("Each line of the opening numeric symbol (#) or semicolon (;) is considered a comment; delete (;) and enable the specified option."))
conf.template = "cbi/tvalue"
conf.rows = 20
conf.wrap = "off"
function conf.cfgvalue(self, section)
return fs.readfile("/etc/hosts") or ""
end
function conf.write(self, section, value)
if value then
value = value:gsub("\r\n?", "\n")
fs.writefile("/tmp/etc/hosts", value)
if (luci.sys.call("cmp -s /tmp/etc/hosts /etc/hosts") == 1) then
fs.writefile("/etc/hosts", value)
luci.sys.call("/etc/init.d/dnsmasq restart >/dev/null")
end
fs.remove("/tmp/etc/hosts")
end
end
end
return m

View File

@ -0,0 +1 @@
zh_Hans

View File

@ -0,0 +1,21 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\n"
msgid "Advanced Setting"
msgstr "高级设置"
msgid "Direct editing of built-in Script Documents for various services, unless you know what you are doing, do not easily modify these configuration documents"
msgstr "各类服务内置脚本文档的直接编辑,除非你知道自己在干什么,否则请不要轻易修改这些配置文档"
msgid "This page is the document content for configuring /etc/dnsmasq.conf. Restart takes effect after application is saved"
msgstr "本页是配置/etc/dnsmasq.conf的文档内容。应用保存后重启生效"
msgid "Each line of the opening numeric symbol (#) or semicolon (;) is considered a comment; delete (;) and enable the specified option."
msgstr "开头的数字符号(#)或分号的每一行(;)被视为注释;删除(;)启用指定选项。"
msgid "This page is the document content for configuring /etc/config/network. Restart takes effect after application is saved"
msgstr "本页是配置/etc/config/network的文档内容。"
msgid "This page is the document content for configuring /etc/hosts. Restart takes effect after application is saved"
msgstr "本页是配置/etc/hosts的文档内容。"

View File

@ -0,0 +1 @@
config advancedsetting

View File

@ -0,0 +1,11 @@
{
"luci-app-advancedsetting": {
"description": "Grant UCI access for luci-app-advancedsetting",
"read": {
"uci": [ "advancedsetting" ]
},
"write": {
"uci": [ "advancedsetting" ]
}
}
}

View File

@ -0,0 +1,17 @@
# Copyright (C) 2016 Openwrt.org
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI support for EasyUpdate From sundaqiang
LUCI_DEPENDS:=+bash
LUCI_PKGARCH:=all
PKG_VERSION:=1.0
PKG_RELEASE:=20211125
PKG_MAINTAINER:=sundaqiang
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,61 @@
# luci-app-easyupdate<74><65><EFBFBD><EFBFBD><EFBFBD>׸<EFBFBD><D7B8>£<EFBFBD>
<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>P3TERX/Actions-OpenWrt<72>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̼<EFBFBD><CCBC><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
### ʹ<>÷<EFBFBD><C3B7><EFBFBD>
#### <20><><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
```yaml
- name: Install feeds
run: cd openwrt && ./scripts/feeds install -a -f
```
#### <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>²<EFBFBD><C2B2><EFBFBD>
```yaml
- name: Openwrt AutoUpdate
run: |
TEMP=$(date +"OpenWrt_%Y%m%d_%H%M%S_")$(git rev-parse --short HEAD)
echo "RELEASE_TAG=$TEMP" >> $GITHUB_ENV
#required>>add "DISTRIB_GITHUB" to "zzz-default-settings"
sed -i "/DISTRIB_DESCRIPTION=/a\sed -i '/DISTRIB_GITHUB/d' /etc/openwrt_release" openwrt/package/lean/default-settings/files/zzz-default-settings
sed -i "/DISTRIB_GITHUB/a\echo \"DISTRIB_GITHUB=\'https://github.com/${{github.repository}}\'\" >> /etc/openwrt_release" openwrt/package/lean/default-settings/files/zzz-default-settings
#required>>add "DISTRIB_VERSIONS" to "zzz-default-settings"
sed -i "/DISTRIB_DESCRIPTION=/a\sed -i '/DISTRIB_VERSIONS/d' /etc/openwrt_release" openwrt/package/lean/default-settings/files/zzz-default-settings
sed -i "/DISTRIB_VERSIONS/a\echo \"DISTRIB_VERSIONS=\'${TEMP:8}\'\" >> /etc/openwrt_release" openwrt/package/lean/default-settings/files/zzz-default-settings
#nonessential>>add "github.actor" to "DISTRIB_DESCRIPTION" in "zzz-default-settings"
sed -i "s/OpenWrt /${{github.actor}} compiled (${TEMP:8}) \/ OpenWrt /g" openwrt/package/lean/default-settings/files/zzz-default-settings
```
#### <20><><EFBFBD><EFBFBD><EFBFBD>²<EFBFBD><C2B2><EFBFBD><EFBFBD><EFBFBD>`tag_name`<60><>ֵ`${{ steps.tag.outputs.release_tag }}`
```yaml
- name: Upload firmware to release
uses: softprops/action-gh-release@v1
if: steps.tag.outputs.status == 'success' && !cancelled()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.tag.outputs.release_tag }}
body_path: release.txt
files: ${{ env.FIRMWARE }}/*
```
#### <20><><EFBFBD><EFBFBD>Ϊ`${{ env.RELEASE_TAG }}`
```yaml
- name: Upload firmware to release
uses: softprops/action-gh-release@v1
if: steps.tag.outputs.status == 'success' && !cancelled()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ env.RELEASE_TAG }}
body_path: release.txt
files: ${{ env.FIRMWARE }}/*
```
#### Ҳ<><D2B2><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD>޸ĺõ<C4BA>actions
[Actions-OpenWrt](https://github.com/sundaqiang/Actions-OpenWrt)
### Ч<><D0A7>չʾ
![easyupdate][1]
[1]: https://raw.githubusercontent.com/sundaqiang/openwrt-packages/master/img/easyupdate.png

View File

@ -0,0 +1,116 @@
module("luci.controller.easyupdate",package.seeall)
function index()
if not nixio.fs.access("/etc/config/easyupdate") then
return
end
local c=luci.model.uci.cursor()
local r=0
if not c:get("easyupdate", "main", "proxy") then
r=1
c:set("easyupdate", "main", "proxy", "1")
end
if not c:get("easyupdate", "main", "keepconfig") then
r=1
c:set("easyupdate", "main", "keepconfig", "1")
end
if not c:get("easyupdate", "main", "github") then
r=1
local pcall, dofile, _G = pcall, dofile, _G
pcall(dofile, "/etc/openwrt_release")
c:set("easyupdate", "main", "github", _G.DISTRIB_GITHUB)
end
if r then
c:commit("easyupdate")
end
entry({"admin", "services", "easyupdate"}, cbi("easyupdate"),_("EasyUpdate"), 99).dependent = true
entry({"admin", "services", "easyupdate", "getver"}, call("getver")).leaf = true
entry({"admin", "services", "easyupdate", "download"}, call("download")).leaf = true
entry({"admin", "services", "easyupdate", "getlog"}, call("getlog")).leaf = true
entry({"admin", "services", "easyupdate", "flash"}, call("flash")).leaf = true
end
function Split(str, delim, maxNb)
-- Eliminate bad cases...
if string.find(str, delim) == nil then
return { str }
end
if maxNb == nil or maxNb < 1 then
maxNb = 0 -- No limit
end
local result = {}
local pat = "(.-)" .. delim .. "()"
local nb = 0
local lastPos
for part, pos in string.gfind(str, pat) do
nb = nb + 1
result[nb] = part
lastPos = pos
if nb == maxNb then break end
end
-- Handle the last field
if nb ~= maxNb then
result[nb + 1] = string.sub(str, lastPos)
end
return result
end
function getver()
local e={}
local c=luci.model.uci.cursor()
local l=Split(c:get("easyupdate", "main", "github"), "/")
e.newver=luci.sys.exec("uclient-fetch -qO- 'https://api.github.com/repos/" .. l[4] .. "/" .. l[5] .. "/releases/latest' | jsonfilter -e '@.tag_name'")
e.newver=e.newver:sub(e.newver:find('_')+1,-2)
e.newverint=os.time({day=e.newver:sub(7,8), month=e.newver:sub(5,6), year=e.newver:sub(1,4), hour=e.newver:sub(10,11), min=e.newver:sub(12,13), sec=e.newver:sub(14,15)})
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function download()
local e={}
local c=luci.model.uci.cursor()
local l=Split(c:get("easyupdate", "main", "github"), "/")
local sedd
if nixio.fs.access("/sys/firmware/efi") then
sedd="combined-efi.img.gz"
else
sedd="combined.img.gz"
end
local url=luci.sys.exec("uclient-fetch -qO- 'https://api.github.com/repos/" .. l[4] .. "/" .. l[5] .. "/releases/latest' | jsonfilter -e '@.assets[*].browser_download_url' | sed -n '/" .. sedd .. "/p'")
url=url:gsub("\n","")
local u=c:get("easyupdate", "main", "proxy")
if u then
u="https://ghproxy.com/"
else
u=""
end
local l=Split(url, "/")
luci.sys.exec("uclient-fetch -O '/tmp/" .. l[9] .. "' '" .. u .. url .. "' > /tmp/easyupdate.log 2>&1 &")
e.code=1
e.data=l[9]
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function getlog()
local e = {}
e.data=nixio.fs.readfile ("/tmp/easyupdate.log")
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function flash()
local e={}
local f = luci.http.formvalue('file')
local c=luci.model.uci.cursor()
local k=c:get("easyupdate", "main", "keepconfig")
if k then
k=""
else
k="-n"
end
luci.sys.exec("sysupgrade " .. k .. " '/tmp/" .. f .. "' > /tmp/easyupdate.log 2>&1 &")
e.code=1
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end

View File

@ -0,0 +1,57 @@
local pcall, dofile, _G = pcall, dofile, _G
pcall(dofile, "/etc/openwrt_release")
m=Map("easyupdate",translate("EasyUpdate"),translate("EasyUpdate LUCI supports scheduled upgrade & one-click firmware upgrade") .. [[<br /><br /><a href="https://github.com/sundaqiang/openwrt-packages" target="_blank">Powered by sundaqiang</a>]])
s=m:section(TypedSection,"easyupdate")
s.anonymous=true
e=s:option(Flag, "enable", translate("Enable"),translate("When selected, firmware upgrade will be automatically at the specified time."))
e.default=0
e.optional=false
p=s:option(Flag, "proxy", translate("Use China Mirror"),translate("When selected, will use the China mirror when accessing Github."))
p.default=1
p.optional=false
k= s:option(Flag, "keepconfig", translate("KEEP CONFIG"),translate("When selected, configuration is retained when firmware upgrade."))
k.default=1
k.optional=false
f=s:option(Flag, "forceflash", translate("Preference Force Flashing"),translate("When selected, Preference Force Flashing while firmware upgrading."))
f.default=0
f.optional=false
w=s:option(ListValue,"week",translate("Update Time"),translate("Advised to set the automatic update time to idle time."))
w:value(7,translate("Everyday"))
w:value(1,translate("Monday"))
w:value(2,translate("Tuesday"))
w:value(3,translate("Wednesday"))
w:value(4,translate("Thursday"))
w:value(5,translate("Friday"))
w:value(6,translate("Saturday"))
w:value(0,translate("Sunday"))
w.default=0
w:depends("enable", "1")
h=s:option(Value,"hour",translate("Hour"))
h.datatype="range(0,23)"
h.rmempty=true
h.default=0
h:depends("enable", "1")
n=s:option(Value,"minute",translate("Minute"))
n.datatype="range(0,59)"
n.rmempty=true
n.default=30
n:depends("enable", "1")
g=s:option(Value,"github",translate("Github Url"),translate("Your Github project address "))
g.default=''
g.rmempty=false
b=s:option(Button,"",translate("Firmware Upgrade"))
b.template="easyupdate/button"
b.versions=_G.DISTRIB_VERSIONS
return m

View File

@ -0,0 +1,168 @@
<%+cbi/valueheader%>
<input class="cbi-button cbi-input-reload" id="update" type="button" value="<%:Collecting data...%>" size="0" disabled onclick="check_version()">
<br>
<div class="cbi-value-description">
<span class="cbi-value-helpicon"><img src="/luci-static/resources/cbi/help.gif" alt="帮助"></span>
<span>
<%:Local Firmware Version%>:<%=self.versions%>
</span>
<br>
<span class="cbi-value-helpicon"><img src="/luci-static/resources/cbi/help.gif" alt="帮助"></span>
<span id="cloudver">
<%:Cloud Firmware Version%>:<%:Collecting data...%>
</span>
</div>
<%+cbi/valuefooter%>
<style type="text/css">
#update_apply_overlay {
white-space: pre-line;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
display: none;
z-index: 20000;
}
#update_apply_overlay .alert-message {
overflow: auto;
position: relative;
top: 10%;
width: 60%;
margin: auto;
display: flex;
flex-wrap: wrap;
min-height: 10%;
align-items: center;
max-height: 80%;
}
#update_apply_overlay .alert-message > h4,
#update_apply_overlay .alert-message > p,
#update_apply_overlay .alert-message > div {
flex-basis: 100%;
}
#update_apply_overlay .alert-message > img {
margin-right: 1em;
flex-basis: 32px;
}
body.apply-overlay-active {
overflow: hidden;
height: 100vh;
}
body.apply-overlay-active #update_apply_overlay {
display: block;
}
</style>
<script type="text/javascript">
function update_status_message(type, content) {
document.getElementById('update_apply_overlay') || document.body.insertAdjacentHTML("beforeend",'<div id="update_apply_overlay"><div class="alert-message"></div></div>')
var overlay = document.getElementById('update_apply_overlay')
message = overlay.querySelector('.alert-message');
if (message && type) {
if (!message.classList.contains(type)) {
message.classList.remove('notice');
message.classList.remove('warning');
message.classList.add(type);
}
if (content)
message.innerHTML = content;
message.scrollTop = message.scrollHeight;
document.body.classList.add('apply-overlay-active');
document.body.scrollTop = document.documentElement.scrollTop = 0;
}
else {
document.body.classList.remove('apply-overlay-active');
}
}
function getver() {
XHR.get('<%=url([[admin]], [[services]], [[easyupdate]], [[getver]])%>', null,
function(x, data) {
const tb = document.getElementById('cloudver');
const up = document.getElementById('update');
if (data && tb) {
if (data.newver) {
tb.innerHTML = '<%:Cloud Firmware Version%>:' + data.newver;
nowverint=<%=os.time({day=self.versions:sub(7,8), month=self.versions:sub(5,6), year=self.versions:sub(1,4), hour=self.versions:sub(10,11), min=self.versions:sub(12,13), sec=self.versions:sub(14,15)})%>
if (data.newverint > nowverint){
up.value = '<%:Download Firmware%>'
up.disabled = false
up.setAttribute('newver', data.newver);
}else{
up.value = '<%:Is the latest%>'
up.disabled = true
}
}else{
tb.innerHTML = '<%:Cloud Firmware Version%>:<%:Collecting data...%>';
up.value = '<%:Retry Firmware Check%>'
up.disabled = false
}
}
}
);
}
getver()
function check_version() {
const tb = document.getElementById('update');
const flash= tb.getAttribute("flash")
if (flash){
XHR.get('<%=url([[admin]], [[services]], [[easyupdate]], [[flash]])%>', {file: tb.getAttribute("file")}, (x, r) => {
if (r.code == 1) {
XHR.poll(1, '<%=url([[admin]], [[services]], [[easyupdate]], [[getlog]])%>', null,(x, r) => {
update_status_message('notice', r.data);
if (r.data.indexOf("Commencing upgrade") > -1 ){
XHR.halt()
setTimeout(() => {
location.replace(document.location.origin)
},180000);
}
})
} else {
tb.disabled = false;
tb.value = '<%:Retry Firmware Upgrade%>';
}
});
return
}
const newver= tb.getAttribute("newver")
if (newver){
tb.disabled = true;
XHR.get('<%=url([[admin]], [[services]], [[easyupdate]], [[download]])%>', null, (x, r) => {
if (r.code == 1) {
tb.setAttribute('file', r.data);
XHR.poll(1, '<%=url([[admin]], [[services]], [[easyupdate]], [[getlog]])%>', null,(x, r) => {
if (r.data.indexOf(" error") > -1 || r.data.indexOf("Connection reset") > -1){
XHR.halt()
update_status_message('warning', r.data);
document.getElementById('update_apply_overlay').addEventListener("click", (e)=>{
update_status_message()
})
}else{
if (r.data.indexOf("Download completed") > -1 ){
XHR.halt()
setTimeout(() => {
update_status_message();
tb.value = '<%:Firmware Upgrade%>'
tb.setAttribute('flash', 1);
},3000);
}else{
update_status_message('notice', r.data);
}
}
tb.disabled = false;
})
} else {
tb.disabled = false;
tb.value = '<%:Retry Firmware Download%>';
}
});
}else{
getver()
}
}
</script>

View File

@ -0,0 +1,68 @@
msgid "EasyUpdate"
msgstr "简易更新"
msgid "EasyUpdate LUCI supports scheduled upgrade & one-click firmware upgrade"
msgstr "EasyUpdate 支持LUCI定时升级和一键式固件升级"
msgid "When selected, firmware upgrade will be automatically at the specified time."
msgstr "选中后,系统将在指定的时间自动升级固件。"
msgid "When selected, will use the China mirror when accessing Github."
msgstr "选中后将在访问Github时使用中国镜像。"
msgid "KEEP CONFIG"
msgstr "保留配置"
msgid "When selected, configuration is retained when firmware upgrade."
msgstr "选中后,固件升级时配置将保留。"
msgid "Preference Force Flashing"
msgstr "强制刷入"
msgid "When selected, Preference Force Flashing while firmware upgrading."
msgstr "选中时,升级固件时将强制刷入。"
msgid "Update Time"
msgstr "更新时机"
msgid "Advised to set the automatic update time to idle time."
msgstr "建议将自动更新时间设置为空闲时间。"
msgid "Everyday"
msgstr "每天"
msgid "Hour"
msgstr "小时"
msgid "Minute"
msgstr "分钟"
msgid "Github Url"
msgstr "Github网址"
msgid "Your Github project address"
msgstr "你的Github项目地址"
msgid "Firmware Upgrade"
msgstr "固件升级"
msgid "Local Firmware Version"
msgstr "本地的固件版本"
msgid "Cloud Firmware Version"
msgstr "云端的固件版本"
msgid "Download Firmware"
msgstr "下载固件"
msgid "Is the latest"
msgstr "已是最新"
msgid "Retry Firmware Check"
msgstr "重试固件检查"
msgid "Retry Firmware Upgrade"
msgstr "重试固件升级"
msgid "Retry Firmware Download"
msgstr "重试固件下载"

View File

@ -0,0 +1,2 @@
config easyupdate 'main'
option enable '0'

View File

@ -0,0 +1,11 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@easyupdate[-1]
add ucitrack easyupdate
set ucitrack.@easyupdate[-1].init=easyupdate
commit ucitrack
EOF
rm -f /tmp/luci-indexcache
exit 0

View File

@ -0,0 +1,11 @@
{
"luci-app-easyupdate": {
"description": "Grant UCI access for luci-app-easyupdate",
"read": {
"uci": [ "easyupdate" ]
},
"write": {
"uci": [ "easyupdate" ]
}
}
}

18
luci-app-mosdns/Makefile Normal file
View File

@ -0,0 +1,18 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-mosdns
PKG_VERSION:=1.0
PKG_RELEASE:=4
LUCI_TITLE:=LuCI Support for mosdns
LUCI_PKGARCH:=all
LUCI_DEPENDS:=+mosdns
define Package/$(PKG_NAME)/conffiles
/etc/mosdns/config.yaml
/etc/config/mosdns
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,20 @@
module("luci.controller.mosdns", package.seeall)
function index()
if not nixio.fs.access("/etc/config/mosdns") then
return
end
entry({"admin", "services", "mosdns"}, alias("admin", "services", "mosdns", "basic"), _("MosDNS"), 30).dependent = true
entry({"admin", "services", "mosdns", "basic"}, cbi("mosdns/basic"), _("Basic Setting"), 1).leaf = true
entry({"admin", "services", "mosdns", "update"}, cbi("mosdns/update"), _("Geodata Update"), 2).leaf = true
entry({"admin", "services", "mosdns", "config"}, cbi("mosdns/config"), _("Manual Configuration"), 3).leaf = true
entry({"admin", "services", "mosdns", "status"}, call("act_status")).leaf = true
end
function act_status()
local e = {}
e.running = luci.sys.call("pgrep -f mosdns >/dev/null") == 0
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end

View File

@ -0,0 +1,21 @@
m = Map("mosdns")
m.title = translate("MosDNS")
m.description = translate("MosDNS is a 'programmable' DNS forwarder.")
m:section(SimpleSection).template = "mosdns/mosdns_status"
s = m:section(TypedSection, "mosdns")
s.addremove = false
s.anonymous = true
enable = s:option(Flag, "enabled", translate("Enable"))
enable.rmempty = false
redirect = s:option(Flag, "redirect", translate("Enable DNS Redirect"))
redirect.rmempty = false
autoconf = s:option(Flag, "autoconf", translate("Enable AutoConfiguration"))
autoconf.description = translate("Turning it on will make the necessary adjustments to other plug-in settings.")
autoconf.rmempty = false
return m

View File

@ -0,0 +1,21 @@
m = Map("mosdns")
s = m:section(TypedSection, "mosdns")
s.addremove = false
s.anonymous = true
config = s:option(TextValue, "manual-config")
config.description = translate("View the YAML Configuration file used by this MosDNS. You can edit it as you own need; Beware the listening port 5335 was hardcoded into the init script, do not change that.")
config.template = "cbi/tvalue"
config.rows = 25
function config.cfgvalue(self, section)
return nixio.fs.readfile("/etc/mosdns/config.yaml")
end
function config.write(self, section, value)
value = value:gsub("\r\n?", "\n")
nixio.fs.writefile("/etc/mosdns/config.yaml", value)
end
return m

View File

@ -0,0 +1,41 @@
m = Map("mosdns")
m.title = translate("MosDNS")
m.description = translate("MosDNS is a 'programmable' DNS forwarder.")
m:section(SimpleSection).template = "mosdns/mosdns_status"
s = m:section(TypedSection, "mosdns")
s.addremove = false
s.anonymous = true
enable = s:option(Flag, "geo_auto_update", translate("Enable Auto Database Update"))
enable.rmempty = false
enable = s:option(Flag, "syncconfig", translate("Enable Config Update"))
enable.rmempty = false
o = s:option(ListValue, "geo_update_week_time", translate("Update Cycle"))
o:value("all", translate("Every Day"))
o:value("1", translate("Every Monday"))
o:value("2", translate("Every Tuesday"))
o:value("3", translate("Every Wednesday"))
o:value("4", translate("Every Thursday"))
o:value("5", translate("Every Friday"))
o:value("6", translate("Every Saturday"))
o:value("7", translate("Every Sunday"))
o.default = "all"
update_time = s:option(ListValue, "geo_update_day_time", translate("Update Time (Every Day)"))
for t = 0, 23 do
update_time:value(t, t..":00")
end
update_time.default = 0
data_update = s:option(Button, "geo_update_database", translate("Database Update"))
data_update.inputtitle = translate("Check And Update")
data_update.inputstyle = "reload"
data_update.write = function()
luci.sys.exec("/etc/mosdns/mosupdater.sh >/dev/null 2>&1 &")
end
return m

View File

@ -0,0 +1,28 @@
<script type="text/javascript">
//<![CDATA[
XHR.poll(3, '<%=url([[admin]], [[services]], [[mosdns]], [[status]])%>', null,
function(x, data) {
var tb = document.getElementById('mosdns_status');
if (data && tb) {
if (data.running) {
var links = '<em><b><font color=green>MosDNS <%:RUNNING%></font></b></em>';
tb.innerHTML = links;
} else {
tb.innerHTML = '<em><b><font color=red>MosDNS <%:NOT RUNNING%></font></b></em>';
}
}
}
);
//]]>
</script>
<style>
.mar-10 {
margin-left: 50px;
margin-right: 10px;
}
</style>
<fieldset class="cbi-section">
<p id="mosdns_status">
<em><%:Collecting data...%></em>
</p>
</fieldset>

View File

@ -0,0 +1,77 @@
msgid "Basic Setting"
msgstr "基本设置"
msgid "Manual Configuration"
msgstr "手动配置"
msgid "MosDNS is a 'programmable' DNS forwarder."
msgstr "MosDNS 是一个插件化的 DNS 转发/分流器。"
msgid "RUNNING"
msgstr "运行中"
msgid "NOT RUNNING"
msgstr "未运行"
msgid "Collecting data..."
msgstr "获取数据中..."
msgid "Enable"
msgstr "启用"
msgid "Enable DNS Redirect"
msgstr "启用 DNS 重定向"
msgid "View the YAML Configuration file used by this MosDNS. You can edit it as you own need; Beware the listening port 5335 was hardcoded into the init script, do not change that."
msgstr "查看 MosDNS 所使用的 YAML 配置文件。你可以根据自己的需要进行编辑但请注意监听端口5335是硬编码在启动脚本中的不要更改"
msgid "Geodata Update"
msgstr "数据库更新"
msgid "Update Time (Every Day)"
msgstr "更新时间(每天)"
msgid "Update Cycle"
msgstr "更新周期"
msgid "Every Day"
msgstr "每天"
msgid "Every Monday"
msgstr "每周一"
msgid "Every Tuesday"
msgstr "每周二"
msgid "Every Wednesday"
msgstr "每周三"
msgid "Every Thursday"
msgstr "每周四"
msgid "Every Friday"
msgstr "每周五"
msgid "Every Saturday"
msgstr "每周六"
msgid "Every Sunday"
msgstr "每周日"
msgid "Database Update"
msgstr "数据库更新"
msgid "Check And Update"
msgstr "检查并更新"
msgid "Enable Auto Database Update"
msgstr "启用数据库自动更新"
msgid "Enable Config Update"
msgstr "启用配置文件同步"
msgid "Enable AutoConfiguration"
msgstr "启用自动化配置"
msgid "Turning it on will make the necessary adjustments to other plug-in settings."
msgstr "开启这个选项会允许本插件对其他插件的设置进行必要的设置,目前仅支持 SSRP VSSR PASSWALL。"

1
luci-app-mosdns/po/zh_Hans Symbolic link
View File

@ -0,0 +1 @@
zh-cn

View File

@ -0,0 +1,10 @@
config mosdns 'mosdns'
option not_first_start '0'
option enabled '0'
option geo_auto_update '0'
option geo_update_week_time 'all'
option geo_update_day_time '2'
option redirect '1'
option autoconf '1'
option syncconfig '1'

View File

@ -0,0 +1,162 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2020 IrineSistiana
START=91
USE_PROCD=1
##### ONLY CHANGE THIS BLOCK ######
PROG=/usr/bin/mosdns # where is mosdns
RES_DIR=/etc/mosdns/ # resource dir / working dir / the dir where you store ip/domain lists
CONF=./config.yaml # where is the config file, it can be a relative path to $RES_DIR
CRON_FILE=/etc/crontabs/root
##### ONLY CHANGE THIS BLOCK ######
inital_conf() {
config_load "mosdns"
config_get "enabled" "mosdns" "enabled" "0"
}
service_triggers() {
procd_add_reload_trigger "mosdns"
}
restore_setting() {
redirect=$(uci -q get mosdns.mosdns.redirect)
if [ $redirect -eq 1 ]; then
sed -i "/list server/d" /etc/config/dhcp
sed -i "/dhcp_option/d" /etc/config/dhcp
uci set dhcp.@dnsmasq[0].noresolv='0'
uci del dhcp.@dnsmasq[0].cachesize
uci set dhcp.@dnsmasq[0].filter_aaaa='1'
uci commit dhcp
fi
autoconf="$(uci -q get mosdns.mosdns.autoconf)"
if [ $autoconf -eq 1 ]; then
uci set shadowsocksr.@global[0].pdnsd_enable='1'
uci set shadowsocksr.@global[0].tunnel_forward='8.8.4.4:53'
uci commit shadowsocksr
uci set passwall.@global[0].dns_mode='pdnsd'
uci set passwall.@global[0].dns_forward='8.8.8.8'
uci set passwall.@global[0].dns_cache='1'
uci commit passwall
uci set vssr.@global[0].pdnsd_enable='1'
uci commit vssr
fi
}
prepare_setting() {
redirect=$(uci -q get mosdns.mosdns.redirect)
if [ $redirect -eq 1 ]; then
sed -i "/list server/d" /etc/config/dhcp
uci add_list dhcp.@dnsmasq[0].server='127.0.0.1#5335'
uci set dhcp.@dnsmasq[0].rebind_protection='0'
lanip="$(uci get network.lan.ipaddr)"
sed -i "/dhcp_option/d" /etc/config/dhcp
sed -i "/dhcpv6/a\\\tlist dhcp_option '6,$lanip'" /etc/config/dhcp
uci set dhcp.@dnsmasq[0].noresolv="1"
uci set dhcp.@dnsmasq[0].cachesize='0'
uci set dhcp.@dnsmasq[0].filter_aaaa='0'
uci commit dhcp
fi
autoconf="$(uci -q get mosdns.mosdns.autoconf)"
if [ $autoconf -eq 1 ]; then
uci set shadowsocksr.@global[0].pdnsd_enable='0'
uci del shadowsocksr.@global[0].tunnel_forward
uci commit shadowsocksr
uci set passwall.@global[0].dns_mode='nonuse'
uci del passwall.@global[0].dns_forward
uci del passwall.@global[0].dns_cache
uci commit passwall
uci set vssr.@global[0].pdnsd_enable='0'
uci commit vssr
fi
}
restart_others() {
/etc/init.d/network reload
/etc/init.d/dnsmasq reload
ssrp="$(uci get shadowsocksr.@global[0].global_server)"
count1="$(ps | grep ssrplus | grep -v 'grep' | wc -l)"
if [ $ssrp != "nil" ] && [ $count1 -ne 0 ]; then
/etc/init.d/shadowsocksr restart
fi
pw="$(uci get passwall.@global[0].enabled)"
count2="$(ps | grep passwall | grep -v 'grep' | wc -l)"
if [ $pw -eq 1 ] && [ $count2 -ne 0 ]; then
/etc/init.d/passwall restart
fi
vssr="$(uci get vssr.@global[0].global_server)"
count3="$(ps | grep vssr | grep -v 'grep' | wc -l)"
if [ $vssr != "nil" ] && [ $count3 -ne 0 ]; then
/etc/init.d/vssr restart
fi
}
reload_service() {
stop
sleep 2s
echo "MosDNS is restarted!"
start
}
setcron() {
chmod 755 /etc/mosdns/mosupdater.sh
[ "$(tail -n1 /etc/crontabs/root | wc -l)" -eq 0 ] && [ -n "$(cat /etc/crontabs/root 2>/dev/null)" ] && echo >>/etc/crontabs/root
[ -z "$(grep "mosupdater.sh" "$CRON_FILE" 2>/dev/null)" ] && {
[ "$(uci -q get mosdns.mosdns.geo_auto_update)" -eq 1 ] && echo "0 $(uci -q get mosdns.mosdns.geo_update_day_time) * * $(uci -q get mosdns.mosdns.geo_update_week_time) /etc/mosdns/mosupdater.sh" >>$CRON_FILE
}
crontab $CRON_FILE
}
delcron() {
sed -i '/mosupdater.sh/d' $CRON_FILE 2>/dev/null
/etc/init.d/cron restart
}
start_service() {
# Reading config
inital_conf
if [ "$enabled" -eq 0 ]; then
firstblood=$(uci -q get mosdns.mosdns.not_first_start)
[ "${firstblood}" = "0" ] && restore_setting
[ "${firstblood}" = "0" ] && restart_others
uci set mosdns.mosdns.not_first_start='1'
uci commit mosdns
echo "MosDNS has turned off"
return 1
fi
delcron
setcron
procd_open_instance mosdns
procd_set_param command $PROG -dir $RES_DIR -c $CONF
procd_set_param user root
procd_set_param stdout 1
procd_set_param stderr 1
procd_set_param respawn "${respawn_threshold:-3600}" "${respawn_timeout:-5}" "${respawn_retry:-5}"
procd_close_instance mosdns
prepare_setting
restart_others
echo "MosDNS turn on"
echo "enabled="$enabled""
}
stop_service() {
killall -q mosdns
echo "MosDNS turn off"
echo "enabled="$enabled""
config_load "mosdns"
enabled=$(uci -q get mosdns.mosdns.enabled)
[ "${enabled}" = "0" ] && restore_setting
restart_others
delcron
}

View File

@ -0,0 +1,95 @@
log:
level: error
file: ''
plugin:
- tag: main_server
type: server
args:
entry:
- _no_ecs
- lazy_cache
- main_sequence
server:
- protocol: udp
addr: '127.0.0.1:5335'
- protocol: tcp
addr: '127.0.0.1:5335'
- tag: main_sequence
type: sequence
args:
exec:
- if:
- query_is_local_domain
- '!_query_is_common'
exec:
- forward_local
- _end
- if:
- query_is_non_local_domain
exec:
- if:
- _qtype_AAAA
exec:
- _block_with_empty_response
- _end
- forward_remote
- _end
- primary:
- forward_local
- if:
- '!response_has_local_ip'
exec:
- _drop_response
secondary:
- if:
- _qtype_AAAA
exec:
- _block_with_empty_response
- _end
- forward_remote
fast_fallback: 150
always_standby: true
- tag: forward_local
type: fast_forward
args:
upstream:
- addr: 119.29.29.29
- addr: 101.226.4.6
- tag: forward_remote
type: fast_forward
args:
upstream:
- addr: 'tls://8.8.4.4'
idle_timeout: 60
max_conns: 10
- addr: 'tls://101.101.101.101'
idle_timeout: 20
max_conns: 10
- tag: lazy_cache
type: cache
args:
size: 512000
lazy_cache_ttl: 31536000
- tag: query_is_local_domain
type: query_matcher
args:
domain:
- 'ext:./geosite.dat:cn'
- tag: query_is_non_local_domain
type: query_matcher
args:
domain:
- 'ext:./geosite.dat:geolocation-!cn'
- tag: response_has_local_ip
type: response_matcher
args:
ip:
- 'ext:./geoip.dat:cn'

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,16 @@
#!/bin/bash -e
set -o pipefail
rm -rf /tmp/mosdns
mkdir /tmp/mosdns
wget https://cdn.jsdelivr.net/gh/Loyalsoldier/geoip@release/geoip-only-cn-private.dat -nv -O /tmp/mosdns/geoip.dat
wget https://cdn.jsdelivr.net/gh/Loyalsoldier/domain-list-custom@release/geosite.dat -nv -O /tmp/mosdns/geosite.dat
find /tmp/mosdns/* -size -20k -exec rm {} \;
syncconfig=$(uci -q get mosdns.mosdns.syncconfig)
if [ $syncconfig -eq 1 ]; then
wget https://cdn.jsdelivr.net/gh/QiuSimons/openwrt-mos@master/luci-app-mosdns/root/etc/mosdns/config.yaml -nv -O /tmp/mosdns/config.yaml
find /tmp/mosdns/* -size -2k -exec rm {} \;
fi
chmod -R 755 /tmp/mosdns
cp -rf /tmp/mosdns/* /etc/mosdns
rm -rf /tmp/mosdns
exit 0

View File

@ -0,0 +1,11 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@mosdns[-1]
add ucitrack mosdns
set ucitrack.@mosdns[-1].init=mosdns
commit ucitrack
EOF
rm -f /tmp/luci-*
exit 0

View File

@ -0,0 +1,11 @@
{
"luci-app-mosdns": {
"description": "Grant UCI access for luci-app-mosdns",
"read": {
"uci": [ "mosdns" ]
},
"write": {
"uci": [ "mosdns" ]
}
}
}

View File

@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-netspeedtest
PKG_VERSION:=1.6
PKG_RELEASE:=20210415
PKG_RELEASE:=20210511
PKG_LICENSE:=GPLv2
PKG_MAINTAINER:=sirpdboy
@ -23,9 +23,6 @@ define Package/$(PKG_NAME)
PKGARCH:=all
endef
define Package/$(PKG_NAME)/description
LuCI support Network speed test intranet and Extranet
endef
define Build/Compile
endef
@ -40,7 +37,7 @@ define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/
cp -pR ./root/* $(1)/
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n
po2lmo ./po/zh-cn/netspeedtest.po $(1)/usr/lib/lua/luci/i18n/netspeedtest.lmo
po2lmo ./po/zh-cn/netspeedtest.po $(1)/usr/lib/lua/luci/i18n/netspeedtest.zh-cn.lmo
endef
$(eval $(call BuildPackage,$(PKG_NAME)))

View File

@ -1,2 +1,123 @@
[![若部分图片无法正常显示,请挂上机场浏览或点这里到末尾看修复教程](https://visitor-badge.glitch.me/badge?page_id=sirpdboy-visitor-badge)](#解决-github-网页上图片显示失败的问题) [![](https://img.shields.io/badge/TG群-点击加入-FFFFFF.svg)](https://t.me/joinchat/AAAAAEpRF88NfOK5vBXGBQ)
<a href="#readme">
<img src="https://img.vim-cn.com/a1/8713845a4aa922ac96619b0d2fb3d6919d37fc.png" alt="图飞了😂" title="NetSpeedTest" align="right" height="180" />
</a>
欢迎来到sirpdboy的源码仓库
=
Welcome to sirpdboy's git source of packages
-
[luci-app-NetSpeedTest — 网络速度测试1.5完整版](https://github.com/sirpdboy/NetSpeedTest)
======================
[![](https://img.shields.io/badge/-目录:-696969.svg)](#readme) [![](https://img.shields.io/badge/-写在前面-F5F5F5.svg)](#写在前面-) [![](https://img.shields.io/badge/-编译说明-F5F5F5.svg)](#编译说明-) [![](https://img.shields.io/badge/-说明-F5F5F5.svg)](#说明-) [![](https://img.shields.io/badge/-捐助-F5F5F5.svg)](#捐助-)
**认真阅读完毕** 本页面,本页面包含注意事项和如何使用。
a new netspeedtest luci app bese luci-app-netspeedtest
-
## 写在前面:[![](https://img.shields.io/badge/-写在前面-F5F5F5.svg)](#写在前面-)
一直在找OPENWRT上测试速度的插件苦寻不到于是有了它!
此插件可进行内外和外网网络速度测试。
1.内网测速基于iperf3 插件服务端路由器如果没有安装请先安装此ipk插件。
2.测速的终端使用机器必须和测速服务器在同一个局域网络中!
3.客户端使用步骤:
启动测速服务器端-->下载测试客户端-->运行测速客户端-->输入服务端IP地址-->查看结果。
5.客户端运行国内端下载中有“iperf3测速客户端”运行它输入服务器IP即可。
国外原版,需要手动进入 CMD命令模式再输入命令iperf3.exe -c 服务器IP
6.网络测速iperf3客户端下载地址https://sipdboy.lanzoui.com/b01c3esih 密码:cpd6
8.外网测速使用speedtest.net测速内核需要依赖speedtest,另外感谢superspeed和user1121114685因为借用了你们的灵感
9.外网测速最后测试阶段感谢佐大:佐须之男 测试查问题!
10.新插件难免有bug 请不要大惊小怪。欢迎提交bug。
11.安装需要依赖: python3 iperf3 。
## 编译说明 [![](https://img.shields.io/badge/-编译说明-F5F5F5.svg)](#编译说明-)
将NetSpeedTest 主题添加至 LEDE/OpenWRT 源码的方法。
## 下载源码方法一:
编辑源码文件夹根目录feeds.conf.default并加入如下内容:
```Brach
# feeds获取源码
src-git netspeedtest https://github.com/sirpdboy/netspeedtest
```
```Brach
# 更新feeds并安装主题
scripts/feeds update netspeedtest
scripts/feeds install luci-app-netspeedtest
```
## 下载源码方法二:
```Brach
# 下载源码
git clone https://github.com/sirpdboy/netspeedtest package/netspeedtest
make menuconfig
```
## 配置菜单
```Brach
make menuconfig
# 找到 LuCI -> Applications, 选择 luci-app-netspeedtest, 保存后退出。
```
## 编译
```Brach
# 编译固件
make package/netspeedtest/luci-app-netspeedtest/{clean,compile} V=s
```
## 说明 [![](https://img.shields.io/badge/-说明-F5F5F5.svg)](#说明-)
源码来源https://github.com/sirpdboy/netspeedtest/luci-app-netspeedtest
你可以随意使用其中的源码,但请注明出处。
============================
# My other project
网络速度测试 https://github.com/sirpdboy/netspeedtest
定时关机重启 : https://github.com/sirpdboy/luci-app-autopoweroff
关机功能插件 : https://github.com/sirpdboy/luci-app-poweroffdevice
opentopd主题 : https://github.com/sirpdboy/luci-theme-opentopd
opentoks 主题: https://github.com/sirpdboy/luci-theme-opentoks [仿KOOLSAHRE主题]
btmob 主题: https://github.com/sirpdboy/luci-theme-btmob
系统高级设置 : https://github.com/sirpdboy/luci-app-advanced
## 捐助 [![](https://img.shields.io/badge/-捐助-F5F5F5.svg)](#捐助-)
**如果你觉得此项目对你有帮助,请捐助我们,以使项目能持续发展,更加完善。··请作者喝杯咖啡~~~**
**你们的支持就是我的动力!**
### 捐助方式
| <img src="https://img.shields.io/badge/-支付宝-F5F5F5.svg" href="#赞助支持本项目-" height="25" alt="图飞了😂"/> | <img src="https://img.shields.io/badge/-微信-F5F5F5.svg" height="25" alt="图飞了😂" href="#赞助支持本项目-"/> |
| :-----------------: | :-------------: |
|<img src="https://img.vim-cn.com/fd/8e2793362ac3510094961b04407beec569b2b4.png" width="150" height="150" alt="图飞了😂" href="#赞助支持本项目-"/>|<img src="https://img.vim-cn.com/c7/675730a88accebf37a97d9e84e33529322b6e9.png" width="150" height="150" alt="图飞了😂" href="#赞助支持本项目-"/>|
<a href="#readme">
<img src="https://img.shields.io/badge/-返回顶部-orange.svg" alt="图飞了😂" title="返回顶部" align="right"/>
</a>
###### [解决 Github 网页上图片显示失败的问题](https://blog.csdn.net/qq_38232598/article/details/91346392)
[![](https://img.shields.io/badge/TG群-点击加入-FFFFFF.svg)](https://t.me/joinchat/AAAAAEpRF88NfOK5vBXGBQ)
#### 原作者sirpdboy 修复了编译错误

View File

@ -1 +0,0 @@
zh-cn

View File

@ -0,0 +1 @@
zh-cn

View File

@ -0,0 +1,17 @@
# Copyright (C) 2016 Openwrt.org
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI support for NginxManager From sundaqiang
LUCI_DEPENDS:=+luci-nginx +luci-ssl-nginx +luci-ssl-openssl
LUCI_PKGARCH:=all
PKG_VERSION:=1.0
PKG_RELEASE:=20211030
PKG_MAINTAINER:=sundaqiang
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,18 @@
# luci-app-nginx-manager<65><72>Nginx<6E><78><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD>openwrt<EFBFBD><EFBFBD>nginx
### ע<><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
1. <20><><EFBFBD><EFBFBD>Ĭ<EFBFBD>ϵ<EFBFBD>uhttpd<70><64>Ϊ·<CEAA>ɺ<EFBFBD>̨<EFBFBD><CCA8>web<65><62><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>+luci-nginx +luci-ssl-nginx +luci-ssl-openssl<73><6C><EFBFBD><EFBFBD><EFBFBD>һ<D2BB><E1BFAA>·<EFBFBD>ɺ<EFBFBD>̨<EFBFBD><CCA8>https<70><73><EFBFBD><EFBFBD>
3. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD>ϵ<EFBFBD>uhttpd<70><64><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE>uhttpd<70><64><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫɾ<D2AA><C9BE>uhttpd<70><64><EFBFBD><EFBFBD><EFBFBD>ڱ<EFBFBD><DAB1><EFBFBD>ǰ<EFBFBD>ڸ<EFBFBD>Ŀ¼ִ<C2BC><D6B4><EFBFBD><EFBFBD><EFBFBD>²<EFBFBD><C2B2><EFBFBD><EFBFBD><EFBFBD>
```bash
sed -i 's/+uhttpd +uhttpd-mod-ubus //g' feeds/luci/collections/luci/Makefile
```
### Ч<><D0A7>չʾ
![nginx-manager][1]
[1]: https://raw.githubusercontent.com/sundaqiang/openwrt-packages/master/img/nginx-manager.png

View File

@ -0,0 +1,39 @@
module("luci.controller.nginx-manager", package.seeall)
function index()
nixio.fs.rename ("/etc/nginx/uci.conf", "/etc/nginx/ucibak.conf")
if not nixio.fs.access("/etc/nginx/nginx.conf") then
nixio.fs.copyr("/var/lib/nginx/uci.conf", "/etc/nginx/nginx.conf")
luci.sys.call("/etc/init.d/nginx restart")
end
file=nixio.fs.readfile("/etc/uwsgi/vassals/luci-webui.ini")
if tonumber(file:match("limit%pas[%p%s]+(%d+)")) < 5000 then
file=file:gsub("limit%pas[%p%s]+(%d+)","limit-as = 5000")
nixio.fs.writefile("/etc/uwsgi/vassals/luci-webui.ini", file)
luci.sys.call("/etc/init.d/uwsgi restart")
end
nixio.fs.writefile("/etc/config/nginx-manager", "")
x = luci.model.uci.cursor()
x:set("nginx-manager", "main", "nginx")
x:set("nginx-manager", "main", "name", "main")
x:set("nginx-manager", "main", "filepath", "/etc/nginx/nginx.conf")
for path in nixio.fs.dir("/etc/nginx/conf.d") do
if path:find(".conf$") ~= nil then
name = path:gsub(".conf", "")
x:set("nginx-manager", name, "nginx")
x:set("nginx-manager", name, "name", name)
x:set("nginx-manager", name, "filepath", "/etc/nginx/conf.d/" .. path)
end
end
x:commit("nginx-manager")
entry({"admin", "services", "nginx-manager"}, cbi("nginx-manager"), _("Nginx Manager"), 95).dependent = true
entry({"admin", "services", "nginx-manager", "setstatus"}, call("setstatus")).leaf = true
end
function setstatus()
local e = {}
local mode = luci.http.formvalue('mode')
e.code=luci.sys.call("/etc/init.d/nginx " .. mode)
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end

View File

@ -0,0 +1,43 @@
local fs = require "nixio.fs"
local m = Map("nginx-manager",translate("Nginx Manager"), translate("A simple Nginx manager") .. [[<br /><br /><a href="https://github.com/sundaqiang/openwrt-packages" target="_blank">Powered by sundaqiang</a>]])
s = m:section(TypedSection, "nginx", translate("Web site list"))
s.template = "nginx-manager/index"
s.addremove = true
s.anonymous = false
s:tab("general", translate("General Info"))
s:tab("server", translate("Configuration File"))
s:taboption("general", DummyValue, "name", translate("name"))
s:taboption("general", DummyValue, "filepath", translate("File Path"))
file=s:taboption("server", TextValue, "")
file.template = "cbi/tvalue"
file.rows = 25
file.wrap = "off"
file.rmempty = true
function s.create(self,section)
path="/etc/nginx/conf.d/" .. section .. ".conf"
fs.copyr("/etc/nginx/conf.d/templates", path)
TypedSection.create(self,section)
self.map:set(section, "name", section)
self.map:set(section, "filepath", path)
return true
end
function s.remove(self,section)
path="/etc/nginx/conf.d/" .. section .. ".conf"
fs.remove(path)
TypedSection.remove(self,section)
end
function sync_value_to_file(value, file)
value = value:gsub("\r\n?", "\n")
local old_value = fs.readfile(file)
if value ~= old_value then
fs.writefile(file, value)
end
end
function file.cfgvalue(self,section)
return fs.readfile(self.map:get(section, "filepath")) or ""
end
function file.write(self, section, value)
sync_value_to_file(value, self.map:get(section, "filepath"))
end
return m

View File

@ -0,0 +1,65 @@
<fieldset class="cbi-section" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
<% if self.title and #self.title > 0 then -%>
<legend><%=self.title%></legend>
<%- end %>
<% if self.description and #self.description > 0 then -%>
<div class="cbi-section-descr"><%=self.description%></div>
<%- end %>
<div class="cbi-value" style="border-bottom: 1px solid #ddd;border-radius: 0px">
<label class="cbi-value-title"><%= translate("Restart the nginx") %></label>
<div class="cbi-value-field" style="padding:unset">
<input class="btn cbi-button cbi-button-reload" id="restart" type="button" size="0" onclick="check_status('restart')" value="<%:Restart%>" />
</div>
<label class="cbi-value-title"><%= translate("Reload the nginx") %></label>
<div class="cbi-value-field" style="padding:unset">
<input class="btn cbi-button cbi-button-reload" id="reload" type="button" size="0" onclick="check_status('reload')" value="<%:Reload%>" />
</div>
</div>
<% local isempty = true for i, k in ipairs(self:cfgsections()) do -%>
<%- section = k; isempty = false -%>
<% if not self.anonymous then -%>
<div class="cbi-section-remove" style="display: flex;flex-flow: row nowrap;justify-content: space-between">
<span style="font-size:1.15rem;color:#32325d;font-weight:bold;letter-spacing:0.1rem;padding:1rem 1.5rem;"><%=section:upper()%></span>
<input type="submit" name="cbi.rts.<%=self.config%>.<%=k%>" onclick="this.form.cbi_state='del-section'; return true" value="<%:Delete%>" class="cbi-button" />
</div>
<%- end %>
<%+cbi/tabmenu%>
<fieldset class="cbi-section-node<% if self.tabs then %> cbi-section-node-tabbed<% end %>" id="cbi-<%=self.config%>-<%=section%>" style="border-bottom: 1px solid #ddd;border-radius: 0px">
<%+cbi/ucisection%>
</fieldset>
<%- end %>
<% if isempty then -%>
<em><%:This section contains no values yet%><br /><br /></em>
<%- end %>
<% if self.addremove then -%>
<% if self.template_addremove then include(self.template_addremove) else -%>
<div class="cbi-section-create">
<% if self.anonymous then -%>
<input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" value="<%:Add%>" />
<%- else -%>
<% if self.invalid_cts then -%><div class="cbi-section-error"><% end %>
<input type="text" class="cbi-section-create-name" id="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" data-type="uciname" data-optional="true" />
<input type="submit" class="cbi-button cbi-button-add" onclick="this.form.cbi_state='add-section'; return true" value="<%:Add%>" />
<% if self.invalid_cts then -%>
<br /><%:Invalid%></div>
<%- end %>
<%- end %>
</div>
<%- end %>
<%- end %>
</fieldset>
<style>.cbi-value-field {padding: 11.2px;}.cbi-tabmenu {border-bottom: unset !important;}</style>
<script type="text/javascript">
function check_status(mode) {
const tb = document.getElementById(mode);
tb.disabled = true;
XHR.get('<%=url([[admin]], [[services]], [[nginx-manager]], [[setstatus]])%>', {mode: mode}, (x, r) => {
tb.disabled = false;
});
}
</script>

View File

@ -0,0 +1,26 @@
msgid "Nginx Manager"
msgstr "Nginx管理器"
msgid "A simple Nginx manager"
msgstr "一个简易的Nginx管理器"
msgid "Web site list"
msgstr "网站列表"
msgid "Restart the nginx"
msgstr "重新启动Nginx"
msgid "Reload the nginx"
msgstr "重新加载Nginx"
msgid "Reload"
msgstr "重新加载"
msgid "Configuration File"
msgstr "配置文件"
msgid "General Info"
msgstr "基础信息"
msgid "File Path"
msgstr "文件路径"

View File

@ -0,0 +1 @@
zh-cn

View File

@ -0,0 +1,17 @@
server {
listen 8080; #bind prot 绑定的端口
root /www; #directory 网站路径
ssl_session_timeout 5m;
gzip on;
gzip_types text/plain application/json application/javascript application/x-javascript text/css application/xml text/javascript;
gzip_proxied any;
gzip_vary on;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.0;
location / {
index index.html index.htm; #默认文件
try_files $uri $uri/ /index.html;
}
}

View File

@ -0,0 +1,11 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@nginx-manager[-1]
add ucitrack nginx-manager
set ucitrack.@nginx-manage[-1].init=nginx
commit ucitrack
EOF
rm -f /tmp/luci-indexcache
exit 0

View File

@ -0,0 +1,11 @@
{
"luci-app-nginx-manager": {
"description": "Grant UCI access for luci-app-nginx-manager",
"read": {
"uci": [ "nginx-manager" ]
},
"write": {
"uci": [ "nginx-manager" ]
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -142,6 +142,12 @@ local status = api.uci_get_type("global_other", "status", "")
</div>
</div>
<% end %>
<div class="cbi-value">
<label class="cbi-value-title"></label>
<div class="cbi-value-field">
<iframe src="https://ip.skk.moe/simple" style="width: 100%; border: 0"></iframe></div>
</div>
</div>
</fieldset>
</fieldset>

View File

@ -0,0 +1,16 @@
# Copyright (C) 2016 Openwrt.org
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI support for NginxManager From sundaqiang
LUCI_PKGARCH:=all
PKG_VERSION:=1.0
PKG_RELEASE:=20211102
PKG_MAINTAINER:=sundaqiang
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,27 @@
# luci-app-supervisord<72><64><EFBFBD><EFBFBD><EFBFBD>̹<EFBFBD><CCB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Luci<EFBFBD>ļ򵥵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> [supervisord](https://github.com/ochinchina/supervisord)
### <20><><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>̹<EFBFBD><CCB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>pm2
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>Dz<EFBFBD><C7B2>ֲ<EFBFBD><D6B2><EFBFBD><EFBFBD>ǵ<EFBFBD><C7B5><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD>ij<EFBFBD>Ʒ<EFBFBD><C6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٵ<EFBFBD><D9B5><EFBFBD>ʵ<EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- nodejs<6A><73>python<6F>ij<EFBFBD><C4B3><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̼<EFBFBD><CCBC>Ѿ<EFBFBD><D1BE>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>nodejs<6A><73>python
- <20><><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>Ҫֱ<D2AA>ӵ㰴ť<E3B0B4><C5A5><EFBFBD>¡<EFBFBD><C2A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD>ȥ<EFBFBD><C8A5>Ŀ<EFBFBD><C4BF><EFBFBD>ض<EFBFBD><D8B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
- <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>˵<EFBFBD><CBB5>:
```ini
;<3B><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>||<7C>ָ<D6B8><EEA3AC><EFBFBD><EFBFBD>
;backupfile=/usr/bin/xxxxx||/etc/yyyyy
backupfile=
;<3B><>ȡ<EFBFBD><EFBFBD><E6B1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEA3AC><EFBFBD><EFBFBD>
;getversions=xxxxx version
getversions=
```
### Ч<><D0A7>չʾ
![supervisord-1][1]
![supervisord-2][2]
[1]: https://raw.githubusercontent.com/sundaqiang/openwrt-packages/master/img/supervisord-1.png
[2]: https://raw.githubusercontent.com/sundaqiang/openwrt-packages/master/img/supervisord-2.png

View File

@ -0,0 +1,234 @@
module("luci.controller.supervisord", package.seeall)
function index()
if not nixio.fs.access("/etc/config/supervisord") then return end
entry({"admin", "services", "supervisord"}, cbi("supervisord"), _("Supervisord"), 95).dependent = true
entry({"admin", "services", "supervisord", "status"}, call("status")).leaf = true
entry({"admin", "services", "supervisord", "getver"}, call("getver")).leaf = true
entry({"admin", "services", "supervisord", "update"}, call("update")).leaf = true
entry({"admin", "services", "supervisord", "gettask"}, call("gettask")).leaf = true
entry({"admin", "services", "supervisord", "starttask"}, call("starttask")).leaf = true
entry({"admin", "services", "supervisord", "restarttask"}, call("restarttask")).leaf = true
entry({"admin", "services", "supervisord", "stoptask"}, call("stoptask")).leaf = true
entry({"admin", "services", "supervisord", "removetask"}, call("removetask")).leaf = true
entry({"admin", "services", "supervisord", "addtask"}, call("addtask")).leaf = true
entry({"admin", "services", "supervisord", "savetask"}, call("savetask")).leaf = true
entry({"admin", "services", "supervisord", "getlog"}, call("getlog")).leaf = true
end
function Split(str, delim, maxNb)
-- Eliminate bad cases...
if string.find(str, delim) == nil then
return { str }
end
if maxNb == nil or maxNb < 1 then
maxNb = 0 -- No limit
end
local result = {}
local pat = "(.-)" .. delim .. "()"
local nb = 0
local lastPos
for part, pos in string.gfind(str, pat) do
nb = nb + 1
result[nb] = part
lastPos = pos
if nb == maxNb then break end
end
-- Handle the last field
if nb ~= maxNb then
result[nb + 1] = string.sub(str, lastPos)
end
return result
end
function status()
local e = {}
e.running = luci.sys.call("ps | grep supervisord | grep -v grep >/dev/null") == 0
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function getver()
local e = {}
local c=luci.model.uci.cursor()
local d=c:get("supervisord", "main", "filepath")
e.nowver=luci.sys.exec(d .. " version")
e.newver=luci.sys.exec("uclient-fetch -qO- 'https://api.github.com/repos/ochinchina/supervisord/releases/latest' | jsonfilter -e '@.tag_name'")
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function update()
local e = {}
local c=luci.model.uci.cursor()
local d=c:get("supervisord", "main", "filepath")
local version = luci.http.formvalue('version')
local arch = nixio.uname().machine or ""
version = version:gsub("\n", "")
if nixio.fs.access("/usr/lib/os-release") then
LEDE_BOARD = luci.sys.exec("echo -n $(grep 'LEDE_BOARD' /usr/lib/os-release | awk -F '[\\042\\047]' '{print $2}')")
end
if nixio.fs.access("/etc/openwrt_release") then
DISTRIB_TARGET = luci.sys.exec("echo -n $(grep 'DISTRIB_TARGET' /etc/openwrt_release | awk -F '[\\042\\047]' '{print $2}')")
end
arch=luci.util.trim(arch)
if arch == "x86_64" then
arch = "64-bit"
end
filename = "supervisord_" .. version:gsub("v", "") .. "_Linux_" .. arch .. ".tar.gz"
nixio.fs.remove("/tmp/" .. filename)
u=c:get("supervisord", "main", "usechinamirror")
if u then
u="https://ghproxy.com/"
else
u=""
end
e.error=luci.sys.call("uclient-fetch -qO- -O '/tmp/" .. filename .. "' '" .. u .. "https://github.com/ochinchina/supervisord/releases/download/" .. version .. "/" .. filename .. "'")
if e.error == 0 then
e.error=luci.sys.exec("tar -xzvf '/tmp/" .. filename .. "' -C /tmp")
if e.error then
e.error=nixio.fs.mover("/tmp/" .. filename:gsub(".tar.gz", "") .. "/supervisord", d)
if e.error then
e.error=0
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
else
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
else
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
end
function gettask()
local e = {}
local name = luci.http.formvalue('name')
local data = luci.sys.exec("supervisord ctl status " .. name)
e.status=string.gsub(string.sub(data, 34, 50), " ", "")
e.description=string.sub(data, 51)
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function starttask()
local e = {}
local name = luci.http.formvalue('name')
local data = luci.sys.exec("supervisord ctl start " .. name)
if string.find(data,"started") ~= nil then
e.code=1
else
e.code=0
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function restarttask()
local e = {}
local name = luci.http.formvalue('name')
local data = luci.sys.exec("supervisord ctl stop " .. name .. " && supervisord ctl start " .. name)
if string.find(data,"started") ~= nil then
e.code=1
else
e.code=0
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function stoptask()
local e = {}
local name = luci.http.formvalue('name')
local data = luci.sys.exec("supervisord ctl stop " .. name)
if string.find(data,"stopped") ~= nil then
e.code=1
else
e.code=0
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function removetask()
local e = {}
local name = luci.http.formvalue('name')
e.code=nixio.fs.remove('/etc/supervisord/program/' .. name .. '.ini')
if e.code then
luci.sys.call("supervisord ctl reload")
e.code=1
else
e.code=0
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function addtask()
local e = {}
local name = luci.http.formvalue('name')
if nixio.fs.access('/etc/supervisord/program/' .. name .. '.ini') then
e.code=2
luci.http.prepare_content("application/json")
luci.http.write_json(e)
return
end
file=nixio.fs.readfile("/etc/supervisord/program/templates")
file=file:gsub("demo", name)
e.code=nixio.fs.writefile('/etc/supervisord/program/' .. name .. '.ini', file)
if e.code then
luci.sys.call("supervisord ctl reload")
e.code=1
e.data=file
else
e.code=0
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function savetask()
local e = {}
local name = luci.http.formvalue('name')
local data = luci.http.formvalue('data')
data = data:gsub("\r\n?", "\n")
file = '/etc/supervisord/program/' .. name .. '.ini'
e.code=nixio.fs.writefile (file, data)
if e.code then
sysupgrade=nixio.fs.readfile("/etc/sysupgrade.conf")
if not sysupgrade:find(file) then
sysupgrade=sysupgrade .. '\n' .. file
end
backupfile=data:match("backupfile=([%a%d%p]+)")
backupfile=Split(backupfile, "||")
for k, v in ipairs(backupfile) do
if not sysupgrade:find(v:gsub("%p", "%%%1")) then
sysupgrade=sysupgrade .. '\n' .. v
end
end
nixio.fs.writefile ("/etc/sysupgrade.conf", sysupgrade)
luci.sys.call("supervisord ctl reload")
e.code=1
else
e.code=0
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function getlog()
local e = {}
local name = luci.http.formvalue('name')
if name=="main" then
local data = nixio.fs.readfile ('/etc/supervisord/supervisord.conf')
data = string.match(data, "logfile=([%a%d%p]+)")
e.data=nixio.fs.readfile (data)
else
local data = nixio.fs.readfile ('/etc/supervisord/program/' .. name .. '.ini')
data = string.match(data, "stdout_logfile=([%a%d%p]+)")
e.data=nixio.fs.readfile (data)
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end

View File

@ -0,0 +1,70 @@
local fs = require "nixio.fs"
local sys = require "luci.sys"
local m = Map("supervisord",translate("Supervisord"), translate("A golang development process management") .. [[<br /><br /><a href="https://github.com/sundaqiang/openwrt-packages" target="_blank">Powered by sundaqiang</a>]])
m:section(SimpleSection).template = "supervisord/index"
s = m:section(TypedSection, "supervisord")
s.addremove = false
s.anonymous = true
s:tab("general", translate("General Settings"))
s:tab("advanced", translate("Configuration File"))
s:tab("list", translate("Task List"))
s:tab("log", translate("Log List"))
f = s:taboption("general", Flag, "enabled", translate("Enabled"))
f.rmempty = false
v = s:taboption("general", Value, "filepath", translate("File Path"))
v.rmempty = false
v = s:taboption("general", Flag, "usechinamirror", translate("Use China Mirror"))
v.rmempty = false
b = s:taboption("general", Button, "")
b.template = "supervisord/version"
file=s:taboption("advanced", TextValue, "")
file.template = "cbi/tvalue"
file.rows = 15
file.wrap = "off"
file.rmempty = false
l=s:taboption("list", DummyValue, "")
l.template = "supervisord/list"
l.list={}
index=1
for filelist in fs.dir("/etc/supervisord/program") do
if filelist:find(".ini$") ~= nil then
name=fs.readfile("/etc/supervisord/program/" .. filelist)
l.list[index]={}
l.list[index][1]=name:match("program:(%a+)")
l.list[index][2]="/etc/supervisord/program/" .. filelist
local cmd=name:match("directory=([%a%d%p ]+)") .. "/" .. name:match("getversions=([%a%d%p ]+)")
l.list[index][3]=sys.exec(cmd)
index=index+1
end
end
g=s:taboption("log", DummyValue, "")
g.template = "supervisord/log"
g.list=l.list
function s.create(self,section)
return TypedSection.create(self,section)
end
function s.remove(self,section)
return TypedSection.remove(self,section)
end
function sync_value_to_file(self, section, value, file)
value = value:gsub("\r\n?", "\n")
local old_value = fs.readfile(file)
if value ~= old_value then
fs.writefile(file, value)
self.map:set(section, "amend", "1")
end
end
function file.cfgvalue(self,section)
return fs.readfile("/etc/supervisord/supervisord.conf") or ""
end
function file.write(self, section, value)
sync_value_to_file(self, section, value, "/etc/supervisord/supervisord.conf")
end
return m

View File

@ -0,0 +1,21 @@
<script type="text/javascript">
XHR.poll(3, '<%=url([[admin]], [[services]], [[supervisord]], [[status]])%>', null,
function(x, data) {
var tb = document.getElementById('status');
if (data && tb) {
if (data.running) {
var links = '<em><b><font color=green>Supervisord <%:RUNNING%></font></b></em>';
tb.innerHTML = links;
} else {
tb.innerHTML = '<em><b><font color=red>Supervisord <%:NOT RUNNING%></font></b></em>';
}
}
}
);
</script>
<style></style>
<fieldset class="cbi-section">
<p id="status">
<em><%:Collecting data...%></em>
</p>
</fieldset>

View File

@ -0,0 +1,163 @@
<%local fs = require "nixio.fs"%>
<%+cbi/valueheader%>
<div class="cbi-section-node">
<table class="cbi-section-table" id="task-list">
<tbody>
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell" style="width:120px!important"><%:Name%></th>
<th class="cbi-section-table-cell" style="width:120px!important"><%:Versions%></th>
<th class="cbi-section-table-cell" style="width:100px!important"><%:Status%></th>
<th class="cbi-section-table-cell" style="width:300px!important"><%:Description%></th>
<th class="cbi-section-table-cell"><%:Configuration File%></th>
<th class="cbi-section-table-cell" style="width:355px!important"><%:Action%></th>
</tr>
<% for _,item in pairs(self.list) do %>
<tr class="cbi-section-table-row" id="<%=item[2]:gsub('/etc/supervisord/program/', ""):gsub('.ini', "")%>-main">
<td class="cbi-value-field">
<%=item[1]%>
</td>
<td class="cbi-value-field">
<%=item[3]%>
</td>
<td class="cbi-value-field" id="<%=item[1]%>-status">
</td>
<td class="cbi-value-field" id="<%=item[1]%>-description">
</td>
<td class="cbi-value-field">
<textarea class="cbi-input-textarea" id="<%=item[1]%>-text" rows="15" wrap="off"><%=fs.readfile(item[2])%></textarea>
</td>
<td class="cbi-value-field">
<input class="cbi-button cbi-input-apply" style="font-size: 100%;background-color: green!important;" type="button" id="<%=item[1]%>-start" disabled
onclick="actions('starttask','<%=item[1]%>')" value="<%:Start%>" size="0">
<input class="cbi-button cbi-input-remove" style="font-size: 100%;background-color: #333333!important;" type="button" id="<%=item[1]%>-stop" disabled
onclick="actions('stoptask','<%=item[1]%>')" value="<%:Stop%>" size="0">
<input class="cbi-button cbi-input-apply" style="font-size: 100%;" type="button"
onclick="actions('restarttask','<%=item[1]%>')" value="<%:Reboot%>" size="0">
<input class="cbi-button cbi-input-remove" style="font-size: 100%;" type="button"
onclick="actions('savetask','<%=item[2]:gsub('/etc/supervisord/program/', ''):gsub('.ini', '')%>')" value="<%:Save%>" size="0">
<input class="cbi-button cbi-button-remove" style="font-size: 100%;" type="button"
onclick="actions('removetask','<%=item[2]:gsub('/etc/supervisord/program/', ''):gsub('.ini', '')%>')" value="<%:Delete%>" size="0">
</td>
</tr>
<% end %>
</tbody>
</table>
<div class="cbi-section-create">
<input type="text" class="cbi-section-create-name" id="addtext" value="" maxlength="20" size="0">
<input class="cbi-button cbi-button-add" onclick="addtask()" type="button" value="<%:Add%>" size="0">
</div>
</div>
<script type="text/javascript">
<% for _,item in pairs(self.list) do -%>
XHR.poll(5, '<%=url([[admin]], [[services]], [[supervisord]], [[gettask]])%>', {name: '<%=item[1]%>'},
function(x, data) {
const st = document.getElementById('<%=item[1]%>-status');
const des = document.getElementById('<%=item[1]%>-description');
if (data) {
st.innerHTML = data.status;
if (data.status == "Exited" || data.status == "Backoff"){
st.style.color="red"
document.getElementById('<%=item[1]%>-start').disabled = false;
document.getElementById('<%=item[1]%>-stop').disabled = true;
}else{
st.style.color="green"
document.getElementById('<%=item[1]%>-start').disabled = true;
document.getElementById('<%=item[1]%>-stop').disabled = false;
}
des.innerHTML = data.description;
}
}
)
<% end %>
function addtask(){
const name = document.getElementById("addtext").value
const isletter = /^[a-zA-Z]+$/.test(name);
if (!isletter) {
alert("<%:Only letters can be used for names!%>")
return
}
if (name.length > 20) {
alert("<%:Cannot exceed 20 characters!%>")
return
}
XHR.get('<%=url([[admin]], [[services]], [[supervisord]], [[addtask]])%>', {name: name},
function(x, data) {
if (data.code == 0) {
alert("<%:Creation failed. Please try again!%>")
return
}else if (data.code == 1){
const currentRows = document.getElementById("task-list").rows.length;
const insertTr = document.getElementById("task-list").insertRow(currentRows);
insertTr.className = 'cbi-section-table-row';
insertTr.id = name + '-main';
insertTr.innerHTML = "<td class='cbi-value-field'>"+name+"</td><td class='cbi-value-field' id='"+name+"-status'></td><td class='cbi-value-field' id='"+name+"-description'></td><td class='cbi-value-field'><textarea class='cbi-input-textarea' id='"+name+"-text' rows='15' wrap='off'>"+data.data+"</textarea></td><td class='cbi-value-field'><input class='cbi-button cbi-input-apply' style='font-size: 100%;background-color: green!important;' type='button' id='"+name+"-start' disabled onclick='actions(&quot;starttask&quot;,&quot;"+name+"&quot;)' value='<%:Start%>' size='0'><input class='cbi-button cbi-input-remove' style='font-size: 100%;background-color: #333333!important;' type='button' id='"+name+"-stop' disabled onclick='actions(&quot;stoptask&quot;,&quot;"+name+"&quot;)' value='<%:Stop%>' size='0'><input class='cbi-button cbi-input-apply' style='font-size: 100%;' type='button' onclick='actions(&quot;restarttask&quot;,&quot;"+name+"&quot;)' value='<%:Reboot%>' size='0'><input class='cbi-button cbi-input-remove' style='font-size: 100%;' type='button' onclick='actions(&quot;savetask&quot;,&quot;"+name+"&quot;)' value='<%:Save%>' size='0'><input class='cbi-button cbi-button-remove' style='font-size: 100%;' type='button' onclick='actions(&quot;removetask&quot;,&quot;"+name+"&quot;)' value='<%:Delete%>' size='0'></td>";
document.getElementById("addtext").value="";
XHR.poll(5, '<%=url([[admin]], [[services]], [[supervisord]], [[gettask]])%>', {name: name},
function(x, data) {
const st = document.getElementById(name + '-status');
const des = document.getElementById(name + '-description');
if (data) {
st.innerHTML = data.status;
if (data.status == "Exited" || data.status == "Backoff"){
st.style.color="red"
document.getElementById(name + '-start').disabled = false;
document.getElementById(name + '-stop').disabled = true;
}else{
st.style.color="green"
document.getElementById(name + '-start').disabled = true;
document.getElementById(name + '-stop').disabled = false;
}
des.innerHTML = data.description;
}
}
)
}else if (data.code == 2){
alert("<%:A task with this name already exists!%>")
return
}
}
)
}
function actions(mode,name){
if (mode=="savetask"){
const x = new XHR()
x.post('<%=url([[admin]], [[services]], [[supervisord]], [[savetask]])%>', {name: name, data: $('#' + name + '-text').val()},
function(x) {
if (JSON.parse(x.response).code) {
alert("<%:Save success!%>")
}else{
alert("<%:Save failed!%>")
}
}
)
}else{
if (mode=="removetask") {
const ret=confirm("<%:Are you sure you want to delete this task?%>")
if (!ret) return
}
XHR.get('<%=url([[admin]], [[services]], [[supervisord]], [[mode]])%>'.replace("mode",mode), {name: name},
function(x, data) {
if (data.code) {
if (mode == "starttask"){
document.getElementById(name + '-start').disabled = true;
document.getElementById(name + '-stop').disabled = false;
}
if (mode == "stoptask"){
document.getElementById(name + '-start').disabled = false;
document.getElementById(name + '-stop').disabled = true;
}
if (mode == "removetask"){
document.getElementById(name + '-main').remove();
}
}
}
)
}
}
</script>
<%+cbi/valuefooter%>

View File

@ -0,0 +1,35 @@
<%local fs = require "nixio.fs"%>
<%+cbi/valueheader%>
<div class="cbi-value">
<label class="cbi-value-title">
<p style="color: red">日记列表</p>
</label>
<div class="cbi-value-field">
<select class="cbi-input-select" size="1">
<option value="main">supervisord</option>
<% for _,item in pairs(self.list) do %>
<option value="<%=item[2]:gsub('/etc/supervisord/program/', ''):gsub('.ini', '')%>">
<%=item[2]:gsub('/etc/supervisord/program/', ''):gsub('.ini', '')%>
</option>
<% end %>
</select>
</div>
</div>
<textarea class="cbi-input-textarea" id="log-text" rows="30" wrap="off" readonly></textarea>
<script type="text/javascript">
getlog('main')
$(".cbi-input-select").change(function (e) {
getlog($(this).val())
});
function getlog(name) {
XHR.get('<%=url([[admin]], [[services]], [[supervisord]], [[getlog]])%>', {name: name},
function (x, data) {
if (data.data) {
document.getElementById("log-text").value = data.data;
}
}
)
}
</script>
<%+cbi/valuefooter%>

View File

@ -0,0 +1,56 @@
<%+cbi/valueheader%>
<label class="cbi-value-title"><%= translate("Update the core") %></label>
<div class="cbi-value-field">
<input class="btn cbi-button cbi-button-reload" id="update" type="button" size="0" onclick="check_version()" value="<%:Collecting data...%>" />
<div class="cbi-value-description">
<span class="cbi-value-helpicon"><img src="/luci-static/resources/cbi/help.gif" alt="帮助"></span>
<%:If repeated failures occur, you can download the binaries for the corresponding schemas at the following url.%>
</br>&nbsp;&nbsp;&nbsp;&nbsp;
<%:https://github.com/ochinchina/supervisord/releases%>
</br>&nbsp;&nbsp;&nbsp;&nbsp;
<%:Unpack the package and place it in the top path.%>
</br>&nbsp;&nbsp;&nbsp;&nbsp;
<%:The author binary version number may not have changed.%>
</br>&nbsp;&nbsp;&nbsp;&nbsp;
<%:If you successfully update, the refresh page is still lower than the latest version.%>
</br>&nbsp;&nbsp;&nbsp;&nbsp;
<%:This is normal.%>
</div>
</div>
<script type="text/javascript">
function getver() {
XHR.get('<%=url([[admin]], [[services]], [[supervisord]], [[getver]])%>', null,
function(x, data) {
const tb = document.getElementById('update');
if (data && tb) {
if (data.newver) {
tb.value = '<%:Local version is %>' + data.nowver + '<%:, New version is %>' + data.newver;
tb.setAttribute('newver', data.newver);
}else{
tb.value = '<%:The check failed. Please try again%>';
}
}
}
);
}
getver()
function check_version() {
const tb = document.getElementById('update');
const newver= tb.getAttribute("newver")
if (newver){
tb.disabled = true;
XHR.get('<%=url([[admin]], [[services]], [[supervisord]], [[update]])%>', {version: newver}, (x, r) => {
if (r.error == 0) {
tb.disabled = false;
tb.value = '<%:Local version is %>' + newver + '<%:, New version is %>' + newver;
} else {
tb.disabled = false;
tb.value = '<%:The update failed. Please try again%>';
}
});
}else{
getver()
}
}
</script>
<%+cbi/valuefooter%>

View File

@ -0,0 +1,80 @@
msgid "Supervisord"
msgstr "进程管理器"
msgid "A golang development process management"
msgstr "一款golang开发的进程管理"
msgid "General Settings"
msgstr "基础设置"
msgid "Configuration File"
msgstr "配置文件"
msgid "Task List"
msgstr "任务列表"
msgid "Log List"
msgstr "日志列表"
msgid "Enabled"
msgstr "启用"
msgid "File Path"
msgstr "文件路径"
msgid "Use China Mirror"
msgstr "使用中国镜像"
msgid "Update the core"
msgstr "更新核心"
msgid "If repeated failures occur, you can download the binaries for the corresponding schemas at the following url."
msgstr "如果重复失败您可以从以下url下载对应模式的二进制文件。"
msgid "Unpack the package and place it in the top path."
msgstr "解压后并将其放置在上方设置的路径中。"
msgid "The author binary version number may not have changed."
msgstr "作者二进制版本号可能没有改变。"
msgid "If you successfully update, the refresh page is still lower than the latest version."
msgstr "如果更新成功,刷新页面仍然低于最新版本。"
msgid "This is normal."
msgstr "这是正常的。"
msgid "Local version is"
msgstr "本地版本是"
msgid ", New version is"
msgstr ",最新版本是"
msgid "The check failed. Please try again"
msgstr "检查失败。请再试一次"
msgid "The update failed. Please try again"
msgstr "更新失败。请再试一次"
msgid "Versions"
msgstr "版本"
msgid "Only letters can be used for names!"
msgstr "只有字母可以用来命名!"
msgid "Cannot exceed 20 characters!"
msgstr "不能超过20个字符"
msgid "Creation failed. Please try again!"
msgstr "创建失败了。请再试一次!"
msgid "A task with this name already exists!"
msgstr "已经存在此名称的任务!"
msgid "Save success!"
msgstr "保存成功!"
msgid "Save failed!"
msgstr "保存失败!"
msgid "Are you sure you want to delete this task?"
msgstr "您确定要删除该任务吗?"

View File

@ -0,0 +1 @@
zh-cn

View File

@ -0,0 +1,6 @@
config supervisord 'main'
option filepath '/usr/bin/supervisord'
option enabled '1'
option amend '0'

View File

@ -0,0 +1,42 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2015 OpenWrt.org
START=90
get_config() {
config_get_bool enabled $1 enabled 0
config_get_bool amend $1 amend 0
config_get filepath $1 filepath /usr/bin/supervisord
}
start() {
config_load supervisord
config_foreach get_config supervisord
[ $enabled -eq 0 ] && exit 0
$filepath -c /etc/supervisord/supervisord.conf -d
}
stop() {
config_load supervisord
config_foreach get_config supervisord
$filepath ctl shutdown
}
reload() {
config_load supervisord
config_foreach get_config supervisord
[ $enabled -eq 0 ] && logger -t supervisord disabled to stop && stop && exit 0
status=$(ps | grep supervisord | grep -v grep | grep -v luci | grep -v init | grep -v version | wc -l)
[ $status -eq 0 ] && logger -t supervisord unstarted to start && start && exit 0
if [ $amend -eq 1 ]; then
logger -t supervisord amend to restart
stop
sleep 1
uci set supervisord.main.amend=0
uci commit supervisord
start
else
logger -t supervisord fixed to reload
$filepath ctl reload
fi
}

View File

@ -0,0 +1,60 @@
;更多参数查看https://github.com/ochinchina/supervisord/
;程序名称,没事别乱改
[program:demo]
;程序启动命令,必须
;command=xxxxx
command=
;执行命令的路径,必须
;directory=/usr/bin
directory=
;需要备份文件的完整路径,多个文件以||分割,必须
;backupfile=/usr/bin/xxxxx||/etc/yyyyy
backupfile=
;获取版本号命令,必须
;getversions=xxxxx version
getversions=
;在supervisord启动的时候也自动启动
autostart=true
;启动10秒后没有异常退出就表示进程正常启动了默认为1秒
startsecs=10
;程序退出后自动重启,可选值:[unexpected,true,false]
;默认为unexpected表示进程意外杀死后才重启
autorestart=true
;启动失败自动重试次数默认是3
startretries=3
;用哪个用户启动进程默认是root
user=root
;进程启动优先级默认999值小的优先启动
priority=999
;把stderr重定向到stdout默认false
redirect_stderr=true
;stdout日志文件大小默认1MB
stdout_logfile_maxbytes=1MB
;stdout日志文件备份数默认是10
stdout_logfile_backups=10
;stdout日志文件需要注意当指定目录不存在时无法正常启动所以需手动创建目录
stdout_logfile=/var/log/demo.log
;日志的级别
loglevel=info
;默认为false,进程被杀死时是否向这个进程组发送stop信号包括子进程
stopasgroup=false
;默认为false向进程组发送kill信号包括子进程
killasgroup=false

View File

@ -0,0 +1,40 @@
;更多参数查看https://github.com/ochinchina/supervisord/
[supervisord]
;主日志文件;默认路径是$CWD/supervisord.log
logfile=/var/log/supervisord.log
;最大主日志文件尺寸;默认3MB
logfile_maxbytes=3MB
;主日志文件备份的数量;默认10
logfile_backups=10
;日志等级;默认info;其他:debug,warn,trace
loglevel=debug
;supervisord的pid文件;默认supervisord.pid
pidfile=/var/run/supervisord.pid
;如果为true从前台开始;默认false
nodaemon=false
;最小效用启动文件描述符;默认1024
minfds=1024
;最小效用过程描述符;默认200
minprocs=200
;启用web界面默认仅本地访问且不设置密码
[inet_http_server]
port=127.0.0.1:9001
;username=admin
;password=admin
;启用命令行操作任务需启用web界面且未设置密码
[supervisorctl]
serverurl=http://127.0.0.1:9001
;加载任务配置文件
[include]
files = /etc/supervisord/program/*.ini

View File

@ -0,0 +1,11 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@supervisord[-1]
add ucitrack supervisord
set ucitrack.@supervisord[-1].init=supervisord
commit ucitrack
EOF
rm -f /tmp/luci-indexcache
exit 0

View File

@ -0,0 +1,11 @@
{
"luci-app-supervisord": {
"description": "Grant UCI access for luci-app-supervisord",
"read": {
"uci": [ "supervisord" ]
},
"write": {
"uci": [ "supervisord" ]
}
}
}

17
luci-app-wolplus/Makefile Normal file
View File

@ -0,0 +1,17 @@
# Copyright (C) 2016 Openwrt.org
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI support for wolplus From sundaqiang
LUCI_DEPENDS:=+etherwake
LUCI_PKGARCH:=all
PKG_VERSION:=1.0
PKG_RELEASE:=20201225
PKG_MAINTAINER:=sundaqiang
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,9 @@
# luci-app-wolplus<75><73><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E7BBBD>++<2B><>
һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><EFBFBD><EFBFBD>
### Ч<><D0A7>չʾ
![wolplus][1]
[1]: https://raw.githubusercontent.com/sundaqiang/openwrt-packages/master/img/wolplus.png

View File

@ -0,0 +1,33 @@
module("luci.controller.wolplus", package.seeall)
local t, a
local x = luci.model.uci.cursor()
function index()
if not nixio.fs.access("/etc/config/wolplus") then return end
entry({"admin", "services", "wolplus"}, cbi("wolplus"), _("wolplus"), 95).dependent = true
entry( {"admin", "services", "wolplus", "awake"}, post("awake") ).leaf = true
end
function awake(sections)
lan = x:get("wolplus",sections,"maceth")
mac = x:get("wolplus",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)
end

View File

@ -0,0 +1,35 @@
local i = require "luci.sys"
local t, e
t = Map("wolplus", translate("wolplus"), translate("Wake up your LAN device") .. [[<br /><br /><a href="https://github.com/sundaqiang/openwrt-packages" target="_blank">Powered by sundaqiang</a>]])
t.template = "wolplus/index"
e = t:section(TypedSection, "macclient", translate("macclient"))
e.template = "cbi/tblsection"
e.anonymous = true
e.addremove = true
a = e:option(Value, "name", translate("name"))
a.optional = false
nolimit_mac = e:option(Value, "macaddr", translate("macaddr"))
nolimit_mac.rmempty = false
i.net.mac_hints(function(e, t) nolimit_mac:value(e, "%s (%s)" % {e, t}) end)
nolimit_eth = e:option(Value, "maceth", translate("maceth"))
nolimit_eth.rmempty = false
for t, e in ipairs(i.net.devices()) do if e ~= "lo" then nolimit_eth:value(e) end end
btn = e:option(Button, "_awake",translate("awake"))
btn.inputtitle = translate("awake")
btn.inputstyle = "apply"
btn.disabled = false
btn.template = "wolplus/awake"
function gen_uuid(format)
local uuid = i.exec("echo -n $(cat /proc/sys/kernel/random/uuid)")
if format == nil then
uuid = string.gsub(uuid, "-", "")
end
return uuid
end
function e.create(e, t)
local uuid = gen_uuid()
t = uuid
TypedSection.create(e, t)
end
return t

View File

@ -0,0 +1,3 @@
<%+cbi/valueheader%>
<input class="cbi-button cbi-input-<%=self.inputstyle or "button" %>" style="font-size: 100%;" type="button" onclick="onclick_awake(this.id)" <%=attr("name", section) .. attr("id", cbid) .. attr("value", self.inputtitle)%> />
<%+cbi/valuefooter%>

View File

@ -0,0 +1,22 @@
<% include("cbi/map") %>
<script type="text/javascript">
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]], [[services]], [[wolplus]], [[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 );
}
}
);
}
</script>

View File

@ -0,0 +1,23 @@
msgid "wolplus"
msgstr "网络唤醒++"
msgid "Wake up your LAN device"
msgstr "唤醒你的局域网设备"
msgid "macclient"
msgstr "设备列表"
msgid "name"
msgstr "名称"
msgid "macaddr"
msgstr "客户端MAC"
msgid "maceth"
msgstr "网络接口"
msgid "awake"
msgstr "唤醒"
msgid "Please [Save & Apply] your changes first"
msgstr "请先保存并应用您的设置"

1
luci-app-wolplus/po/zh_Hans Symbolic link
View File

@ -0,0 +1 @@
zh-cn

View File

View File

@ -0,0 +1,11 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@wolplus[-1]
add ucitrack wolplus
set ucitrack.@wolplus[-1].init=wolplus
commit ucitrack
EOF
rm -f /tmp/luci-indexcache
exit 0

View File

@ -0,0 +1,11 @@
{
"luci-app-wolplus": {
"description": "Grant UCI access for luci-app-wolplus",
"read": {
"uci": [ "wolplus" ]
},
"write": {
"uci": [ "wolplus" ]
}
}
}

View File

@ -7,7 +7,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-wrtbwmon
PKG_VERSION:=2.0.8
PKG_VERSION:=2.0.9
PKG_RELEASE:=1
PKG_LICENSE:=Apache-2.0

View File

@ -1,30 +1,15 @@
'use strict';
'require form';
'require fs';
'require uci';
'require rpc';
'require view';
function renameFile(str, tag) {
var dir = dirName(str);
var n = str.lastIndexOf('/'), fn = n > -1 ? str.slice(n + 1) : str;
var n = fn.lastIndexOf('.'), bn = n > -1 ? fn.slice(0, n) : fn;
var n = fn.lastIndexOf('.'), en = n > -1 ? fn.slice(n + 1) : '';
return dir + bn + '.' + tag + (en ? '.' + en : '');
}
function dirName(str) {
var n = str.lastIndexOf('/');
return n > -1 ? str.slice(0, n + 1) : '';
}
return L.view.extend({
lastPath: null,
load: function() {
return uci.load('wrtbwmon').then(L.bind(function() {
this.lastPath = uci.get_first('wrtbwmon', 'wrtbwmon', 'path') || null;
}, this));
},
var callChangeDatabasePath = rpc.declare({
object: 'luci.wrtbwmon',
method: 'change_db_path',
params: [ 'state' ]
});
return view.extend({
render: function() {
var m, s, o;
@ -45,51 +30,9 @@ return L.view.extend({
return m.render();
},
changePath: function() {
return uci.changes().then(L.bind(function(res) {
if (res.wrtbwmon && this.lastPath) {
for (var i = 0; i < res.wrtbwmon.length; i++) {
if (res.wrtbwmon[i][2] == "path") {
var newPath = res.wrtbwmon[i][3];
return fs.stat(dirName(newPath)).then(L.bind(function(res) {
if (res.type == 'directory') {
Promise.all([
fs.exec('/bin/cp', ['-fp', this.lastPath, newPath]),
fs.exec('/bin/cp', ['-fp', renameFile(this.lastPath, '6'), renameFile(newPath, '6')]),
fs.exec('/bin/cp', ['-fp', renameFile(this.lastPath, '46'), renameFile(newPath, '46')])
]);
return true;
}
else {
var err = new Error('Can\'t move files to non-directory path.');
err.name = 'NotDirectoryError';
throw err;
}
}, this)).catch(function(err) {
throw err;
})
}
}
}
return false;
}, this));
},
handleSaveApply: function(ev, mode) {
return this.handleSave(ev).then(L.bind(this.changePath, this)).then(L.bind(function(data) {
L.resolveDefault(L.ui.changes.apply(mode == '0')).then(L.bind(function() {
if (data) {
Promise.all([
fs.exec('/bin/rm', ['-f', this.lastPath]),
fs.exec('/bin/rm', ['-f', renameFile(this.lastPath, '6')]),
fs.exec('/bin/rm', ['-f', renameFile(this.lastPath, '46')])
]);
}
}, this));
}, this)).catch(function(err) {
if (confirm(err + '\n\n' + _('This will revert the changes. Are you sure?'))) {
L.bind(L.ui.changes.revert, L.ui.changes)();
}
});
return callChangeDatabasePath('before')
.then(this.super.bind(this, 'handleSaveApply', arguments))
.then(callChangeDatabasePath.bind(this, 'after'));
}
});

View File

@ -1,8 +1,9 @@
'use strict';
'require fs';
'require ui';
'require view';
return L.view.extend({
return view.extend({
load: function() {
return fs.trimmed('/etc/wrtbwmon.user').catch(function(err) {
ui.addNotification(null, E('p', {}, _('Unable to load the customized hostname file: ' + err.message)));
@ -36,7 +37,7 @@ return L.view.extend({
return E('div', { 'class': 'cbi-page-actions' }, [
E('button', {
'class': 'cbi-button cbi-button-save',
'click': L.ui.createHandlerFn(this, 'handleSave')
'click': ui.createHandlerFn(this, 'handleSave')
}, [ _('Save') ])
]);
}

View File

@ -1,9 +1,11 @@
'use strict';
'require dom';
'require fs';
'require poll';
'require rpc';
'require uci';
'require ui';
'require validation';
'require view';
var cachedData = [];
var luciConfig = '/etc/luci-wrtbwmon.conf';
@ -21,25 +23,41 @@ var callLuciDSLStatus = rpc.declare({
expect: { '': {} }
});
var callGetDatabaseRaw = rpc.declare({
object: 'luci.wrtbwmon',
method: 'get_db_raw',
params: [ 'protocol' ]
});
var callGetDatabasePath = rpc.declare({
object: 'luci.wrtbwmon',
method: 'get_db_path',
params: [ 'protocol' ]
});
var callRemoveDatabase = rpc.declare({
object: 'luci.wrtbwmon',
method: 'remove_db',
params: [ 'protocol' ]
});
function $(tid) {
return document.getElementById(tid);
}
function clickToResetDatabase(settings) {
function clickToResetDatabase(settings, table, updated, updating, ev) {
if (confirm(_('This will delete the database file. Are you sure?'))) {
getPath().then(function(res) {
var db = settings.protocol == 'ipv4' ? res : renameFile(res, '6');
fs.exec('/bin/rm', [db]).then(function() {
updateData($('traffic'), $('updated'), $('updating'), settings, true);
});
})
return callRemoveDatabase(settings.protocol)
.then(function() {
updateData(settings, table, updated, updating, true);
});
}
}
function clickToSaveConfig(keylist, cstrs) {
var data = {};
for(var i = 0; i < keylist.length; i++) {
for (var i = 0; i < keylist.length; i++) {
data[keylist[i]] = cstrs[keylist[i]].getValue();
}
@ -55,26 +73,25 @@ function clickToSaveConfig(keylist, cstrs) {
.then(function() { document.location.reload(); });
}
function clickToSelectInterval(settings, ev) {
function clickToSelectInterval(settings, updating, ev) {
if (ev.target.value > 0) {
settings.interval = parseInt(ev.target.value);
if (!L.Request.poll.active()) L.Request.poll.start();
if (!poll.active()) poll.start();
}
else {
L.Request.poll.stop();
setUpdateMessage($('updating'), -1);
poll.stop();
setUpdateMessage(updating, -1);
}
}
function clickToSelectProtocol(settings, ev) {
function clickToSelectProtocol(settings, table, updated, updating, ev) {
settings.protocol = ev.target.value;
updateData($('traffic'), $('updated'), $('updating'), settings, true);
updateData(settings, table, updated, updating, true);
}
function clickToShowMore(settings, ev) {
var table = $('traffic');
function clickToShowMore(settings, table, ev) {
var t = table.querySelector('.tr.table-totals');
settings.showMore = ev.target.checked
settings.showMore = ev.target.checked
if (t && t.firstElementChild)
t.firstElementChild.textContent = _('TOTAL') + (settings.showMore ? '' : ': ' + (table.childElementCount - 2));
@ -99,7 +116,7 @@ function createOption(args, val) {
]);
if (desc && desc != '')
L.dom.append(frame.lastChild, E('div', { 'class': 'cbi-value-description' }, desc));
dom.append(frame.lastChild, E('div', { 'class': 'cbi-value-description' }, desc));
return [widget, frame];
}
@ -153,14 +170,6 @@ function getDSLBandwidth() {
});
}
function getPath() {
return uci.load('wrtbwmon').then(function() {
var res = uci.get_first('wrtbwmon', 'wrtbwmon', 'path') || '/tmp/usage.db';
uci.unload('wrtbwmon');
return res;
});
}
function handleConfig(ev) {
ui.showModal(_('Configuration'), [
E('p', { 'class': 'spinning' }, _('Loading configuration data...'))
@ -181,7 +190,7 @@ function handleConfig(ev) {
[ui.Textfield, _('Upstream Bandwidth'), '100', {datatype: 'ufloat'}, 'Mbps'],
[ui.Textfield, _('Downstream Bandwidth'), '100', {datatype: 'ufloat'}, 'Mbps'],
[ui.DynamicList, _('Hide MAC Addresses'), [], '', {datatype: 'macaddr'}, '']
]; // [constructor, lable, default_value(, all_values), options, description]
]; // [constructor, label, default_value(, all_values), options, description]
for (var i = 0; i < keylist.length; i++) {
res = createOption(arglist[i], settings[keylist[i]]);
@ -248,7 +257,7 @@ function parseDefaultSettings(file) {
var keylist = ['protocol', 'interval', 'showMore', 'showZero', 'useBits', 'useMultiple', 'useDSL', 'upstream', 'downstream', 'hideMACs'];
var valuelist = ['ipv4', '5', false, true, false, '1000', false, '100', '100', []];
return fs.read(file).then(function(json) {
return fs.read_direct(file).then(function(json) {
var settings;
try {
settings = JSON.parse(json);
@ -258,7 +267,7 @@ function parseDefaultSettings(file) {
}
for (var i = 0; i < keylist.length; i++) {
if(!(keylist[i] in settings))
if (!(keylist[i] in settings))
settings[keylist[i]] = valuelist[i];
}
@ -292,10 +301,13 @@ function progressbar(query, v, m, useBits, useMultiple) {
}
}
function registerTableEventHandlers(settings, table) {
var indicators = $('xhr_poll_status') || $('indicators').getElementsByTagName('span')[0];
indicators.addEventListener('click', function() {
$('selectInterval').value = L.Request.poll.active() ? settings.interval : -1;
function setupThisDOM(settings, table) {
document.addEventListener('poll-stop', function() {
$('selectInterval').value = -1;
});
document.addEventListener('poll-start', function() {
$('selectInterval').value = settings.interval;
});
table.querySelectorAll('.th').forEach(function(e) {
@ -304,6 +316,9 @@ function registerTableEventHandlers(settings, table) {
setSortedColumn(ev.target);
displayTable(table, settings);
});
if (e.classList.contains('showMore'))
settings.showMore ? e.classList.remove('hide') : e.classList.add('hide');
}
});
}
@ -317,8 +332,8 @@ function renameFile(str, tag) {
function resolveCustomizedHostName() {
return fs.stat(hostNameFile).then(function() {
return fs.read(hostNameFile).then(function(rawStr) {
var hostNames = [], arr = rawStr.split(/\r?\n|\r/g), row;
return fs.read_direct(hostNameFile).then(function(raw) {
var hostNames = [], arr = raw.trim().split(/\r?\n/), row;
for (var i = 0; i < arr.length; i++) {
row = arr[i].split(',');
if (row.length == 2 && row[0])
@ -326,7 +341,8 @@ function resolveCustomizedHostName() {
}
return hostNames;
})
}).catch(function() { return []; });
})
.catch(function() { return []; });
}
function resolveHostNameByMACAddr() {
@ -367,7 +383,7 @@ function setSortedColumn(sorting) {
}
function setUpdateMessage(e, sec) {
e.innerHTML = sec < 0 ? '' : ' ' + _('Updating again in %s second(s).').format('<b>' + sec + '</b>');
e.innerHTML = sec < 0 ? '' : _('Updating again in %s second(s).').format('<b>' + sec + '</b>');
}
function sortTable(col, IPVer, flag, x, y) {
@ -384,8 +400,8 @@ function sortTable(col, IPVer, flag, x, y) {
: (a = validation.parseIPv6(a) || [0, 0, 0, 0, 0, 0, 0, 0], b = validation.parseIPv6(b) || [0, 0, 0, 0, 0, 0, 0, 0]);
}
if(Array.isArray(a) && Array.isArray(b)) {
for(var i = 0; i < a.length; i++) {
if (Array.isArray(a) && Array.isArray(b)) {
for (var i = 0; i < a.length; i++) {
if (a[i] != b[i]) {
return (b[i] - a[i]) * flag;
}
@ -396,34 +412,36 @@ function sortTable(col, IPVer, flag, x, y) {
return a == b ? 0 : (a < b ? 1 : -1) * flag;
}
function updateData(table, updated, updating, settings, once) {
if (!(L.Poll.tick % settings.interval) || once) {
getPath().then(function(res) {
function updateData(settings, table, updated, updating, once) {
if (!(poll.tick % settings.interval) || once) {
callGetDatabasePath()
.then(function(res) {
var params = settings.protocol == 'ipv4' ? '-4' : '-6';
fs.exec('/usr/sbin/wrtbwmon', [params, '-f', res]);
return params == '-4' ? res : renameFile(res, '6');
}).then(function(data) {
Promise.all([
fs.exec('/bin/cat', [ data ]),
return fs.exec_direct('/usr/sbin/wrtbwmon', [params, '-f', res.file_4])
})
.then(function() {
return Promise.all([
callGetDatabaseRaw(settings.protocol),
resolveHostNameByMACAddr()
]).then(function(res) {
//console.time('start');
cachedData = parseDatabase(res[0].stdout || '', res[1], settings.showZero, settings.hideMACs);
displayTable(table, settings);
updated.innerHTML = _('Last updated at %s.').format(formatDate(new Date(document.lastModified)));
//console.timeEnd('start');
});
]);
})
.then(function(res) {
//console.time('start');
cachedData = parseDatabase(res[0].data || '', res[1], settings.showZero, settings.hideMACs);
displayTable(table, settings);
updated.textContent = _('Last updated at %s.').format(formatDate(new Date(document.lastModified)));
//console.timeEnd('start');
});
}
updatePerSec(updating, settings.interval);
}
function updatePerSec(e, interval) {
var tick = L.Poll.tick;
var tick = poll.tick;
var sec = tick % interval ? interval - tick % interval : 0;
setUpdateMessage(e, sec);
if(sec == 0) {
if (sec == 0) {
setTimeout(setUpdateMessage.bind(this, e, interval), 100);
}
}
@ -483,7 +501,7 @@ function updateTable(tb, values, placeholder, settings) {
}
//Append the totals or placeholder row.
if(formData.length == 0) {
if (formData.length == 0) {
newNode = document.createElement('div');
newNode.className = 'tr placeholder';
childTD = document.createElement('div');
@ -525,7 +543,17 @@ function updateTable(tb, values, placeholder, settings) {
tb.appendChild(fragment);
}
return L.view.extend({
function initOption(options, selected) {
var res = [], attr = {};
for (var idx in options) {
attr.value = idx;
attr.selected = idx == selected ? '' : null;
res.push(E('option', attr, options[idx]));
}
return res;
}
return view.extend({
load: function() {
return Promise.all([
parseDefaultSettings(luciConfig),
@ -534,8 +562,29 @@ return L.view.extend({
},
render: function(data) {
var settings = data[0];
var node = E('div', { 'class': 'cbi-map' }, [
var settings = data[0],
labelUpdated = E('label'),
labelUpdating = E('label'),
table = E('div', { 'class': 'table', 'id': 'traffic' }, [
E('div', { 'class': 'tr table-titles' }, [
E('div', { 'class': 'th', 'id': 'thClient' }, _('Clients')),
E('div', { 'class': 'th showMore hide', 'id': 'thMAC' }, _('MAC')),
E('div', { 'class': 'th', 'id': 'thDownload' }, _('Download')),
E('div', { 'class': 'th', 'id': 'thUpload' }, _('Upload')),
E('div', { 'class': 'th', 'id': 'thTotalDown' }, _('Total Down')),
E('div', { 'class': 'th', 'id': 'thTotalUp' }, _('Total Up')),
E('div', { 'class': 'th sorted', 'id': 'thTotal' }, _('Total')),
E('div', { 'class': 'th showMore hide', 'id': 'thFirstSeen' }, _('First Seen')),
E('div', { 'class': 'th showMore hide', 'id': 'thLastSeen' }, _('Last Seen'))
]),
E('div', {'class': 'tr placeholder'}, [
E('div', { 'class': 'td' }, E('em', {}, _('Collecting data...')))
])
]);
poll.add(updateData.bind(this, settings, table, labelUpdated, labelUpdating, false), 1);
setupThisDOM(settings, table);
return E('div', { 'class': 'cbi-map' }, [
E('h2', {}, _('Usage - Details')),
E('div', { 'class': 'cbi-section' }, [
E('div', { 'id': 'control_panel' }, [
@ -543,25 +592,26 @@ return L.view.extend({
E('label', {}, _('Protocol:')),
E('select', {
'id': 'selectProtocol',
'change': clickToSelectProtocol.bind(this, settings)
}, [
E('option', { 'value': 'ipv4' }, 'ipv4'),
E('option', { 'value': 'ipv6' }, 'ipv6')
])
'change': clickToSelectProtocol.bind(this, settings, table, labelUpdated, labelUpdating)
}, initOption({
'ipv4': 'ipv4',
'ipv6': 'ipv6'
}, settings.protocol))
]),
E('div', {}, [
E('label', { 'for': 'showMore' }, _('Show More Columns:')),
E('input', {
'id': 'showMore',
'type': 'checkbox',
'click': clickToShowMore.bind(this, settings)
'click': clickToShowMore.bind(this, settings, table),
'checked': settings.showMore ? '' : null
}),
]),
E('div', {}, [
E('button', {
'class': 'btn cbi-button cbi-button-reset important',
'id': 'resetDatabase',
'click': clickToResetDatabase.bind(this, settings)
'click': clickToResetDatabase.bind(this, settings, table, labelUpdated, labelUpdating)
}, _('Reset Database')),
' ',
E('button', {
@ -571,22 +621,19 @@ return L.view.extend({
])
]),
E('div', {}, [
E('div', {}, [
E('div', { 'id': 'updated' }),
E('div', { 'id': 'updating' })
]),
E('div', {}, [ labelUpdated, labelUpdating ]),
E('div', {}, [
E('label', { 'for': 'selectInterval' }, _('Auto update every:')),
E('select', {
'id': 'selectInterval',
'change': clickToSelectInterval.bind(this, settings)
}, [
E('option', { 'value': '-1' }, _('Disabled')),
E('option', { 'value': '2' }, _('2 seconds')),
E('option', { 'value': '5' }, _('5 seconds')),
E('option', { 'value': '10' }, _('10 seconds')),
E('option', { 'value': '30' }, _('30 seconds'))
])
'change': clickToSelectInterval.bind(this, settings, labelUpdating)
}, initOption({
'-1': _('Disabled'),
'2': _('2 seconds'),
'5': _('5 seconds'),
'10': _('10 seconds'),
'30': _('30 seconds')
}, settings.interval))
])
]),
E('div', { 'id': 'progressbar_panel', 'class': 'table' }, [
@ -609,40 +656,9 @@ return L.view.extend({
))
]),
]),
E('div', { 'class': 'table', 'id': 'traffic' }, [
E('div', { 'class': 'tr table-titles' }, [
E('div', { 'class': 'th', 'id': 'thClient' }, _('Clients')),
E('div', { 'class': 'th showMore hide', 'id': 'thMAC' }, _('MAC')),
E('div', { 'class': 'th', 'id': 'thDownload' }, _('Download')),
E('div', { 'class': 'th', 'id': 'thUpload' }, _('Upload')),
E('div', { 'class': 'th', 'id': 'thTotalDown' }, _('Total Down')),
E('div', { 'class': 'th', 'id': 'thTotalUp' }, _('Total Up')),
E('div', { 'class': 'th sorted', 'id': 'thTotal' }, _('Total')),
E('div', { 'class': 'th showMore hide', 'id': 'thFirstSeen' }, _('First Seen')),
E('div', { 'class': 'th showMore hide', 'id': 'thLastSeen' }, _('Last Seen'))
]),
E('div', {'class': 'tr placeholder'}, [
E('div', { 'class': 'td' }, E('em', {}, _('Collecting data...')))
])
])
table
])
]);
return Promise.all([
node.querySelector('[id="traffic"]'),
node.querySelector('[id="updated"]'),
node.querySelector('[id="updating"]'),
node.querySelector('[id="selectInterval"]').value = settings.interval,
node.querySelector('[id="selectProtocol"]').value = settings.protocol,
node.querySelector('[id="showMore"]').checked = settings.showMore,
node.querySelectorAll('.showMore').forEach(function(e) { settings.showMore ? e.classList.remove('hide') : e.classList.add('hide'); })
])
.then(function(data) {
L.Poll.add(updateData.bind(this, data[0], data[1], data[2], settings, false), 1);
return data[0];
})
.then(registerTableEventHandlers.bind(this, settings))
.then(function() { return node; });
},
handleSaveApply: null,

View File

@ -43,9 +43,6 @@ div > label + select {
flex: 1 1 35%;
text-align: right;
}
#updated, #updating {
display: inline;
}
#thClient {
width: 17%;
}

View File

@ -1,105 +1,105 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:175
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:585
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:184
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:634
msgid "10 seconds"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:175
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:583
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:184
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:632
msgid "2 seconds"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:175
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:586
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:184
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:635
msgid "30 seconds"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:175
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:584
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:184
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:633
msgid "5 seconds"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:577
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:626
msgid "Auto update every:"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:199
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:208
msgid "Cancel"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:497
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:612
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:517
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:570
msgid "Clients"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:122
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:623
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:139
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:581
msgid "Collecting data..."
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:46
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:165
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:208
#: luasrc/controller/wrtbwmon.lua:16
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:64
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:174
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:217
#: root/usr/share/luci/menu.d/luci-app-wrtbwmon.json:25
msgid "Configuration"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:568
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:620
msgid "Configure Options"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:193
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:202
msgid "Configure the default values for luci-app-wrtbwmon."
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:39
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:24
msgid "Database path"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:176
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:185
msgid "Default More Columns"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:174
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:183
msgid "Default Protocol"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:175
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:184
msgid "Default Refresh Interval"
msgstr ""
#: luasrc/controller/wrtbwmon.lua:13
#: root/usr/share/luci/menu.d/luci-app-wrtbwmon.json:16
msgid "Details"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:175
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:582
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:184
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:631
msgid "Disabled"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:614
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:572
msgid "Download"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:182
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:191
msgid "Downstream Bandwidth"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:592
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:641
msgid "Downstream:"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/custom.js:17
#: htdocs/luci-static/resources/view/wrtbwmon/custom.js:18
msgid "Each line must have the following format:"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:619
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:577
msgid "First Seen"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:33
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:18
msgid "General settings"
msgstr ""
@ -107,154 +107,150 @@ msgstr ""
msgid "Grant access to LuCI app wrtbwmon"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:183
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:192
msgid "Hide MAC Addresses"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:179
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:188
msgid "IEC - 1024"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:36
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:21
msgid "Keep running in the background"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:620
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:578
msgid "Last Seen"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:411
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:432
msgid "Last updated at %s."
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:166
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:175
msgid "Loading configuration data..."
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:613
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:571
msgid "MAC"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:179
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:188
msgid "Multiple of Unit"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:541
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:592
msgid "Protocol:"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:563
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:615
msgid "Reset Database"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:179
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:188
msgid "SI - 1000"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/custom.js:40
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:205
#: htdocs/luci-static/resources/view/wrtbwmon/custom.js:41
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:214
msgid "Save"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:47
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:65
msgid "Saving configuration data..."
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:551
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:602
msgid "Show More Columns:"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:177
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:186
msgid "Show Zeros"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:80
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:496
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:97
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:516
msgid "TOTAL"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:39
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:24
msgid ""
"This box is used to select the Database path, which is /tmp/usage.db by "
"default."
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:29
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:49
msgid "This will delete the database file. Are you sure?"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:90
msgid "This will revert the changes. Are you sure?"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:618
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:576
msgid "Total"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:616
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:574
msgid "Total Down"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:617
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:575
msgid "Total Up"
msgstr ""
#: luasrc/controller/wrtbwmon.lua:10
#: root/usr/share/luci/menu.d/luci-app-wrtbwmon.json:3
msgid "Traffic Status"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:178
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:187
msgid "Transfer Speed in Bits"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/custom.js:8
#: htdocs/luci-static/resources/view/wrtbwmon/custom.js:9
msgid "Unable to load the customized hostname file:"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:52
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:70
msgid "Unable to save %s: %s"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:368
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:386
msgid "Updating again in %s second(s)."
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:615
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:573
msgid "Upload"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:181
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:190
msgid "Upstream Bandwidth"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:601
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:650
msgid "Upstream:"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:31
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:16
msgid "Usage - Configuration"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/custom.js:15
#: htdocs/luci-static/resources/view/wrtbwmon/custom.js:16
msgid "Usage - Custom User File"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:537
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:588
msgid "Usage - Details"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:180
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:189
msgid "Use DSL Bandwidth"
msgstr ""
#: luasrc/controller/wrtbwmon.lua:19
#: root/usr/share/luci/menu.d/luci-app-wrtbwmon.json:34
msgid "User file"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:174
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:183
msgid "ipv4"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:174
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:183
msgid "ipv6"
msgstr ""

View File

@ -1,105 +1,105 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\n"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:175
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:585
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:184
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:634
msgid "10 seconds"
msgstr "10秒"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:175
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:583
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:184
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:632
msgid "2 seconds"
msgstr "2秒"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:175
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:586
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:184
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:635
msgid "30 seconds"
msgstr "30秒"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:175
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:584
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:184
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:633
msgid "5 seconds"
msgstr "5秒"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:577
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:626
msgid "Auto update every:"
msgstr "自动刷新:"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:199
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:208
msgid "Cancel"
msgstr "取消"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:497
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:612
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:517
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:570
msgid "Clients"
msgstr "客户端"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:122
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:623
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:139
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:581
msgid "Collecting data..."
msgstr "收集数据中..."
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:46
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:165
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:208
#: luasrc/controller/wrtbwmon.lua:16
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:64
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:174
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:217
#: root/usr/share/luci/menu.d/luci-app-wrtbwmon.json:25
msgid "Configuration"
msgstr "配置"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:568
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:620
msgid "Configure Options"
msgstr "配置选项"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:193
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:202
msgid "Configure the default values for luci-app-wrtbwmon."
msgstr "配置luci-app-wrtbwmon的默认值。"
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:39
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:24
msgid "Database path"
msgstr "数据路径"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:176
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:185
msgid "Default More Columns"
msgstr "默认显示更多列"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:174
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:183
msgid "Default Protocol"
msgstr "默认协议"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:175
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:184
msgid "Default Refresh Interval"
msgstr "默认刷新间隔"
#: luasrc/controller/wrtbwmon.lua:13
#: root/usr/share/luci/menu.d/luci-app-wrtbwmon.json:16
msgid "Details"
msgstr "流量信息"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:175
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:582
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:184
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:631
msgid "Disabled"
msgstr "禁用"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:614
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:572
msgid "Download"
msgstr "下载"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:182
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:191
msgid "Downstream Bandwidth"
msgstr "下行带宽"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:592
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:641
msgid "Downstream:"
msgstr "下行:"
#: htdocs/luci-static/resources/view/wrtbwmon/custom.js:17
#: htdocs/luci-static/resources/view/wrtbwmon/custom.js:18
msgid "Each line must have the following format:"
msgstr "每行需要满足以下格式:"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:619
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:577
msgid "First Seen"
msgstr "初次记录"
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:33
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:18
msgid "General settings"
msgstr "通用设置"
@ -107,154 +107,153 @@ msgstr "通用设置"
msgid "Grant access to LuCI app wrtbwmon"
msgstr "授予访问LuCI应用程序wrtbwmon的权限"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:183
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:192
msgid "Hide MAC Addresses"
msgstr "隐藏MAC地址"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:179
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:188
msgid "IEC - 1024"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:36
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:21
msgid "Keep running in the background"
msgstr "保持后台运行"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:620
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:578
msgid "Last Seen"
msgstr "最后记录"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:411
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:432
msgid "Last updated at %s."
msgstr "最后更新于%s。"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:166
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:175
msgid "Loading configuration data..."
msgstr "载入配置数据..."
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:613
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:571
msgid "MAC"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:179
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:188
msgid "Multiple of Unit"
msgstr "单位之间倍数"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:541
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:592
msgid "Protocol:"
msgstr "协议:"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:563
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:615
msgid "Reset Database"
msgstr "重置"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:179
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:188
msgid "SI - 1000"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/custom.js:40
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:205
#: htdocs/luci-static/resources/view/wrtbwmon/custom.js:41
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:214
msgid "Save"
msgstr "保存"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:47
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:65
msgid "Saving configuration data..."
msgstr "保存配置数据..."
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:551
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:602
msgid "Show More Columns:"
msgstr "显示更多列:"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:177
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:186
msgid "Show Zeros"
msgstr "显示0流量"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:80
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:496
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:97
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:516
msgid "TOTAL"
msgstr "总共"
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:39
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:24
msgid ""
"This box is used to select the Database path, which is /tmp/usage.db by "
"default."
msgstr "该选项用于选择数据存储路径,默认路径为/tmp/usage.db。"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:29
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:49
msgid "This will delete the database file. Are you sure?"
msgstr "该操作将删除数据统计文件,确定执行该操作?"
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:90
msgid "This will revert the changes. Are you sure?"
msgstr "更改将会重置,确定吗?"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:618
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:576
msgid "Total"
msgstr "总计"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:616
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:574
msgid "Total Down"
msgstr "总下载"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:617
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:575
msgid "Total Up"
msgstr "总上传"
#: luasrc/controller/wrtbwmon.lua:10
#: root/usr/share/luci/menu.d/luci-app-wrtbwmon.json:3
msgid "Traffic Status"
msgstr "流量监控"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:178
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:187
msgid "Transfer Speed in Bits"
msgstr "以bits显示传输速度"
#: htdocs/luci-static/resources/view/wrtbwmon/custom.js:8
#: htdocs/luci-static/resources/view/wrtbwmon/custom.js:9
msgid "Unable to load the customized hostname file:"
msgstr "不能载入自定义用户名文件:"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:52
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:70
msgid "Unable to save %s: %s"
msgstr "不能保存%s: %s"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:368
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:386
msgid "Updating again in %s second(s)."
msgstr "下次更新将于%s秒之后。"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:615
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:573
msgid "Upload"
msgstr "上传"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:181
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:190
msgid "Upstream Bandwidth"
msgstr "上传带宽"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:601
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:650
msgid "Upstream:"
msgstr "上行"
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:31
#: htdocs/luci-static/resources/view/wrtbwmon/config.js:16
msgid "Usage - Configuration"
msgstr "文件设置"
#: htdocs/luci-static/resources/view/wrtbwmon/custom.js:15
#: htdocs/luci-static/resources/view/wrtbwmon/custom.js:16
msgid "Usage - Custom User File"
msgstr "用户文件配置"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:537
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:588
msgid "Usage - Details"
msgstr "流量详情"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:180
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:189
msgid "Use DSL Bandwidth"
msgstr "使用DSL带宽"
#: luasrc/controller/wrtbwmon.lua:19
#: root/usr/share/luci/menu.d/luci-app-wrtbwmon.json:34
msgid "User file"
msgstr "用户文件"
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:174
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:183
msgid "ipv4"
msgstr ""
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:174
#: htdocs/luci-static/resources/view/wrtbwmon/details.js:183
msgid "ipv6"
msgstr ""
#~ msgid "This will revert the changes. Are you sure?"
#~ msgstr "更改将会重置,确定吗?"

View File

@ -0,0 +1,124 @@
#!/bin/sh
. "$IPKG_INSTROOT/usr/share/libubox/jshn.sh"
renamefile() {
local base=$(basename -- "$1")
local ext=$([ -z "${base/*.*/}" ] && echo ".${base##*.}" || echo '')
local base="${base%.*}"
echo "$(dirname $1)/${base}$2$ext" && return
}
_get_db_path() {
local db db_4 db_6 db_46
db="$(uci -q get wrtbwmon.general.path)"
db_4=$(renamefile "${db:-/tmp/usage.db}" "")
db_6=$(renamefile "${db:-/tmp/usage.db}" ".6")
db_46=$(renamefile "${db:-/tmp/usage.db}" ".46")
json_init
json_add_string file_4 "$db_4"
json_add_string file_6 "$db_6"
json_add_string file_46 "$db_46"
json_dump
json_cleanup
}
_get_db_raw() {
json_init
json_add_string file "$1"
json_add_string data "$(cat "$1")"
json_dump
json_cleanup
}
_remove_db() {
local result
rm "$1" && result=1 || result=0
json_init
json_add_boolean result "$result"
json_dump
json_cleanup
}
_change_db_path() {
json_init
json_load "$(_get_db_path)"
json_get_var db_4 'file_4'
json_get_var db_6 'file_6'
json_get_var db_46 'file_46'
json_cleanup
if [ "$1" = "before" ]; then
mv "$db_4" /tmp/usage.db.tmp
mv "$db_6" /tmp/usage.6.db.tmp
mv "$db_46" /tmp/usage.46.db.tmp
elif [ "$1" = "after" ]; then
mv -f /tmp/usage.db.tmp "$db_4"
mv -f /tmp/usage.6.db.tmp "$db_6"
mv -f /tmp/usage.46.db.tmp "$db_46"
fi
json_init
json_add_boolean result $([ "$?" = 0 ] && echo 1 || echo 0 )
json_dump
json_cleanup
}
case "$1" in
list)
json_init
json_add_object remove_db
json_add_string protocol "protocol"
json_close_object
json_add_object get_db_raw
json_add_string protocol "protocol"
json_close_object
json_add_object get_db_path
json_close_object
json_add_object change_db_path
json_add_string state "state"
json_close_object
json_dump
json_cleanup
;;
call)
case "$2" in
remove_db)
read -r input
json_init
json_load "$input"
json_get_var protocol 'protocol'
json_cleanup
json_load "$(_get_db_path)"
json_get_var db_s $([ "$protocol" = "ipv4" ] && echo file_4 || echo file_6)
json_cleanup
_remove_db "$db_s"
;;
get_db_raw)
read -r input
json_init
json_load "$input"
json_get_var protocol 'protocol'
json_cleanup
json_load "$(_get_db_path)"
json_get_var db_s $([ "$protocol" = "ipv4" ] && echo file_4 || echo file_6)
json_cleanup
_get_db_raw "$db_s"
;;
get_db_path)
read -r input
json_init
json_load "$input"
json_get_var protocol 'protocol'
json_cleanup
_get_db_path
;;
change_db_path)
read -r input
json_init
json_load "$input"
json_get_var state 'state'
json_cleanup
_change_db_path "$state"
;;
esac
;;
esac

View File

@ -2,24 +2,31 @@
"luci-app-wrtbwmon": {
"description": "Grant access to LuCI app wrtbwmon",
"read": {
"ubus": {
"luci.wrtbwmon": [
"get_db_raw",
"get_db_path"
]
},
"file": {
"/tmp/usage.db": [ "read" ],
"/etc/wrtbwmon.user": [ "read" ],
"/usr/sbin/wrtbwmon": [ "exec" ],
"/bin/cp": [ "exec" ],
"/etc/luci-wrtbwmon.conf": [ "read" ]
},
"uci": [ "wrtbwmon", "luci-app-wrtbwmon" ]
"uci": [ "wrtbwmon" ]
},
"write": {
"ubus": {
"luci.wrtbwmon": [
"remove_db",
"change_db_path"
]
},
"file": {
"/bin/cat": [ "exec" ],
"/bin/rm": [ "exec" ],
"/bin/cp": [ "exec" ],
"/etc/luci-wrtbwmon.conf": [ "write" ],
"/etc/wrtbwmon.user": [ "write" ]
},
"uci": [ "wrtbwmon", "luci-app-wrtbwmon" ]
"uci": [ "wrtbwmon" ]
}
}
}

80
mosdns/Makefile Normal file
View File

@ -0,0 +1,80 @@
# SPDX-License-Identifier: GPL-3.0-only
#
# Copyright (C) 2021 ImmortalWrt.org
include $(TOPDIR)/rules.mk
PKG_NAME:=mosdns
PKG_VERSION:=293b018
PKG_RELEASE:=$(AUTORELEASE)
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/IrineSistiana/mosdns/tar.gz/$(PKG_VERSION)?
PKG_HASH:=skip
PKG_LICENSE:=GPL-3.0
PKG_LICENSE_FILE:=LICENSE
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
PKG_CONFIG_DEPENDS:= \
CONFIG_MOSDNS_COMPRESS_GOPROXY \
CONFIG_MOSDNS_COMPRESS_UPX
PKG_BUILD_DEPENDS:=golang/host
PKG_BUILD_PARALLEL:=1
PKG_USE_MIPS16:=0
GO_PKG:=github.com/IrineSistiana/mosdns
GO_PKG_LDFLAGS:=-s -w
GO_PKG_LDFLAGS_X:=main.version=$(PKG_VERSION)
include $(INCLUDE_DIR)/package.mk
include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk
define Package/mosdns/Default
SECTION:=net
CATEGORY:=Network
SUBMENU:=IP Addresses and Names
TITLE:=A plug-in DNS forwarder/splitter
URL:=https://github.com/IrineSistiana/mosdns
endef
define Package/mosdns
$(call Package/mosdns/Default)
DEPENDS:=$(GO_ARCH_DEPENDS)
endef
define Package/mosdns/config
config MOSDNS_COMPRESS_GOPROXY
bool "Compiling with GOPROXY proxy"
default n
config MOSDNS_COMPRESS_UPX
bool "Compress executable files with UPX"
default y
endef
ifeq ($(CONFIG_MOSDNS_COMPRESS_GOPROXY),y)
export GO111MODULE=on
export GOPROXY=https://goproxy.baidu.com
endif
define Build/Prepare
$(call Build/Prepare/Default)
endef
GO_PKG_TARGET_VARS:=$(filter-out CGO_ENABLED=%,$(GO_PKG_TARGET_VARS)) CGO_ENABLED=0
define Build/Compile
$(call GoPackage/Build/Compile)
ifneq ($(CONFIG_MOSDNS_COMPRESS_UPX),)
$(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/mosdns
endif
endef
define Package/mosdns/install
$(call GoPackage/Package/Install/Bin,$(1))
endef
$(eval $(call GoBinPackage,mosdns))
$(eval $(call BuildPackage,mosdns))

View File

@ -0,0 +1,34 @@
# nas-packages-luci
luci for [nas-packages](https://github.com/linkease/nas-packages)
## 使用方法
### 增加feed源
```shell
echo >> feeds.conf.default
echo 'src-git nas https://github.com/linkease/nas-packages.git;master' >> feeds.conf.default
echo 'src-git nas_luci https://github.com/linkease/nas-packages-luci.git;main' >> feeds.conf.default
./scripts/feeds update nas nas_luci
./scripts/feeds install -a -p nas
./scripts/feeds install -a -p nas_luci
```
### 集成软件包
```shell
make menuconfig
```
选择软件包
```plain
LuCI --->
3. Applications --->
<*> luci-app-ddnsto.................................. LuCI support for ddnsto
<*> luci-app-linkease.................................. LuCI support for linkease
```
### 构建固件
```shell
make
```

View File

@ -6,9 +6,9 @@
include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI support for ddnsto
LUCI_DEPENDS:=ddnsto
LUCI_DEPENDS:=+ddnsto
LUCI_PKGARCH:=all
PKG_VERSION:=1.0.0
PKG_VERSION:=1.0.1
PKG_RELEASE:=1
include $(TOPDIR)/feeds/luci/luci.mk

View File

@ -7,11 +7,12 @@
{
if (st.running)
{
tb.innerHTML = '<br/><%:The DDNS.to service is running.%>';
tb.innerHTML = '<br/><em style=\"color:green\"><%:The DDNS.to service is running.%></em>'
+ "<br/><br/><input class=\"btn cbi-button cbi-button-apply\" type=\"button\" value=\" <%:Click to open DDNS.to%> \" onclick=\"window.open('https://www.ddnsto.com/app/#/login/')\"/>";
}
else
{
tb.innerHTML = '<br/><em><%:The DDNS.to service is not running.%></em>';
tb.innerHTML = '<br/><em style=\"color:red\"><%:The DDNS.to service is not running.%></em>';
}
}
}

Some files were not shown because too many files have changed in this diff Show More