update 2023-08-05 20:01:09

This commit is contained in:
github-actions[bot]
2023-08-05 20:01:09 +08:00
parent 2660741f61
commit 0cc038fef1
53 changed files with 4768 additions and 2509 deletions

View File

@ -1,22 +0,0 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-pushbot
PKG_VERSION:=3.60
PKG_RELEASE:=1
PKG_MAINTAINER:=tty228 <tty228@yeah.net> zzsj0928
LUCI_TITLE:=LuCI support for Pushbot
LUCI_PKGARCH:=all
LUCI_DEPENDS:=+iputils-arping +curl +jq
define Package/$(PKG_NAME)/conffiles
/etc/config/pushbot
/usr/bin/pushbot/api/diy.json
/usr/bin/pushbot/api/ipv4.list
/usr/bin/pushbot/api/ipv6.list
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -1,93 +0,0 @@
# 改名公告
#### 2021年04月25日 起luci-app-serverchand 改名为 luci-app-pushbot
如需拉取编译
请把:
`# git clone https://github.com/zzsj0928/luci-app-serverchand package/luci-app-serverchand`
改为
`git clone https://github.com/zzsj0928/luci-app-pushbot package/luci-app-pushbot`
并把 .config 中
`CONFIG_PACKAGE_luci-app-serverchand=y`
改为
`CONFIG_PACKAGE_luci-app-pushbot=y`
注意本次改名需要提前备份serverchand配置并于PushBot中重新配置。
再次谢谢各位支持
# 申明
- 本插件由[tty228/luci-app-serverchan](https://github.com/tty228/luci-app-serverchan)原创.
- 因微信推送存在诸多弊端(无法分开聊天工具与功能性消息推送,通知内不显示内容,内容需要点开才能查看等),
- 故由 然后七年 @zzsj0928 重新修改为本插件为钉钉机器人API使用。
- 本插件工作在openwrt
- 本插件支持:钉钉推送,企业微信推送,PushPlus推送,微信推送,企业微信应用推送,飞书推送,钉钉机器人推送,企业微信机器人推送,飞书机器人推送,一对多推送,Bark推送(仅iOS),PushDeer,PushDeer自架
- 自20210911之后的版本支持Bark群组群组名默认为设备名
- 自20210901之后的版本增加依赖jq请重新编译或在安装前同步安装jq
# 显示效果
## 通知栏:直接显示推送主题,一目了然,按设备不同,分组显示
<img src="https://raw.githubusercontent.com/zzsj0928/ReadmeContents/main/Serverchand/Msg.Notification.jpg" width="500">
## 消息列表:直接显示最新推送的标题
<img src="https://raw.githubusercontent.com/zzsj0928/ReadmeContents/main/Serverchand/Msg.List.jpg" width="500">
## 消息内容:直接显示所有推送信息,不用二次点开再查看
<img src="https://raw.githubusercontent.com/zzsj0928/ReadmeContents/main/Serverchand/MsgContentDetials.jpeg" width="500">
# 下载
- [luci-app-pushbot](https://github.com/zzsj0928/luci-app-pushbot/releases)
-----------------------------------------------------
#####################################################
-----------------------------------------------------
# 以下为原插件简介:
# 简介
- 用于 OpenWRT/LEDE 路由器上进行 Server酱 微信/Telegram 推送的插件
- 基于 serverchan 提供的接口发送信息Server酱说明http://sc.ftqq.com/1.version
- **基于斐讯 k3 制作,不同系统不同设备,请自行修改部分代码,无测试条件无法重现的 bug 不考虑修复**
- 依赖 iputils-arping + curl 命令,安装前请 `opkg update`,小内存路由谨慎安装
- 使用主动探测设备连接的方式检测设备在线状态以避免WiFi休眠机制主动探测较为耗时**如遇设备休眠频繁,请自行调整超时设置**
- 流量统计功能依赖 wrtbwmon ,自行选装或编译,该插件与 Routing/NAT 、Flow Offloading 冲突开启无法获取流量自行选择L大版本直接编译 luci-app-wrtbwmon
#### 主要功能
- 路由 ip/ipv6 变动推送
- 设备别名
- 设备上线推送
- 设备离线推送及流量使用情况
- CPU 负载、温度监视
- 定时推送设备运行状态
- MAC 白名单、黑名单、按接口检测设备
- 免打扰
- 无人值守任务
#### 说明
- 潘多拉系统、或不支持 sh 的系统,请将脚本开头 `#!/bin/sh` 改为 `#!/bin/bash`,或手动安装 `sh`
- 追新是没有意义的,没有问题没必要更新,上班事情忙完了,摸鱼又不会摸,只能靠写几行 bug ,才能缓解无聊这样子
#### 已知问题
- 直接关闭接口时,该接口的离线设备会忽略检测
- 部分设备无法读取到设备名,脚本使用 `cat /var/dhcp.leases` 命令读取设备名,如果 dhcp 中不存在设备名则无法读取设备名如二级路由设备、静态ip设备请使用设备名备注
# Download
- [luci-app-serverchan](https://github.com/tty228/luci-app-serverchan/releases)
- [wrtbwmon](https://github.com/brvphoenix/wrtbwmon)
- [luci-app-wrtbwmon](https://github.com/brvphoenix/luci-app-wrtbwmon)
#### ps
- 新功能看情况开发
- 王者荣耀新赛季,不思进取中
- 欢迎各种代码提交
- 提交bug时请尽量带上设备信息日志与描述如执行`/usr/bin/serverchan/serverchan`后的提示、日志信息、/tmp/serverchan/ipAddress 文件信息)
- 三言两句恕我无能为力
- 武汉加油

View File

@ -1,32 +0,0 @@
module("luci.controller.pushbot",package.seeall)
function index()
if not nixio.fs.access("/etc/config/pushbot") then
return
end
entry({"admin", "services", "pushbot"}, alias("admin", "services", "pushbot", "setting"),_("全能推送"), 30).dependent = true
entry({"admin", "services", "pushbot", "setting"}, cbi("pushbot/setting"),_("配置"), 40).leaf = true
entry({"admin", "services", "pushbot", "advanced"}, cbi("pushbot/advanced"),_("高级设置"), 50).leaf = true
entry({"admin", "services", "pushbot", "client"}, form("pushbot/client"), "在线设备", 80)
entry({"admin", "services", "pushbot", "log"}, form("pushbot/log"),_("日志"), 99).leaf = true
entry({"admin", "services", "pushbot", "get_log"}, call("get_log")).leaf = true
entry({"admin", "services", "pushbot", "clear_log"}, call("clear_log")).leaf = true
entry({"admin", "services", "pushbot", "status"}, call("act_status")).leaf = true
end
function act_status()
local e={}
e.running=luci.sys.call("busybox ps|grep -v grep|grep -c pushbot >/dev/null")==0
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function get_log()
luci.http.write(luci.sys.exec(
"[ -f '/tmp/pushbot/pushbot.log' ] && cat /tmp/pushbot/pushbot.log"))
end
function clear_log()
luci.sys.call("echo '' > /tmp/pushbot/pushbot.log")
end

View File

@ -1,124 +0,0 @@
local nt = require "luci.sys".net
local fs=require"nixio.fs"
m=Map("pushbot",translate("提示"),
translate("如果你不了解这些选项的含义,请不要修改这些选项。"))
s = m:section(TypedSection, "pushbot", "高级设置")
s.anonymous = true
s.addremove = false
a=s:option(Value,"up_timeout",translate('设备上线检测超时s'))
a.default = "2"
a.optional=false
a.datatype="uinteger"
a=s:option(Value,"down_timeout",translate('设备离线检测超时s'))
a.default = "20"
a.optional=false
a.datatype="uinteger"
a=s:option(Value,"timeout_retry_count",translate('离线检测次数'))
a.default = "2"
a.optional=false
a.datatype="uinteger"
a.description = translate("若无二级路由设备,信号强度良好,可以减少以上数值<br/>因夜间 wifi 休眠较为玄学,遇到设备频繁推送断开,烦请自行调整参数<br/>..╮(╯_╰╭..")
a=s:option(Value,"thread_num",translate('最大并发进程数'))
a.default = "3"
a.datatype="uinteger"
a=s:option(Value, "soc_code", "自定义温度读取命令")
a.rmempty = true
a:value("",translate("默认"))
a:value("pve",translate("PVE 虚拟机"))
a.description = translate("请尽量避免使用特殊符号,如双引号、$、!等,执行结果需为数字,用于温度对比")
a=s:option(Value,"pve_host",translate("宿主机地址"))
a.rmempty=true
a.default="10.0.0.2"
a.description = translate("请确认已经设置好密钥登陆,否则会引起脚本无法运行等错误!<br/>PVE 安装 sensors 命令自行百度<br/>密钥登陆例:<br/>opkg update #更新列表<br/>opkg install openssh-client openssh-keygen #安装openssh客户端<br/>ssh-keygen -t rsa # 生成密钥文件(自行设定密码等信息)<br/>ssh root@10.0.0.2 \"tee -a ~/.ssh/id_rsa.pub\" < ~/.ssh/id_rsa.pub # 传送公钥到 PVE<br/>ssh root@10.0.0.2 \"cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys\" # 写入公钥到 PVE<br/>ssh -i ~/.ssh/id_rsa root@10.0.0.2 sensors # 测试温度命令")
a:depends({soc_code="pve"})
a=s:option(Value,"pve_port",translate("SSH端口"))
a.rmempty=true
a.default="22"
a.description = translate("默认为22如有自定义请填写自定义SSH端口")
a:depends({soc_code="pve"})
a=s:option(Button,"soc",translate("测试温度命令"))
a.inputtitle = translate("输出信息")
a.write = function()
luci.sys.call("/usr/bin/pushbot/pushbot soc")
luci.http.redirect(luci.dispatcher.build_url("admin","services","pushbot","advanced"))
end
if nixio.fs.access("/tmp/pushbot/soc_tmp") then
e=s:option(TextValue,"soc_tmp")
e.rows=2
e.readonly=true
e.cfgvalue = function()
return luci.sys.exec("cat /tmp/pushbot/soc_tmp && rm -f /tmp/pushbot/soc_tmp")
end
end
a=s:option(Flag,"err_enable",translate("无人值守任务"))
a.default=0
a.rmempty=true
a.description = translate("请确认脚本可以正常运行,否则可能造成频繁重启等错误!")
a=s:option(Flag,"err_sheep_enable",translate("仅在免打扰时段重拨"))
a.default=0
a.rmempty=true
a.description = translate("避免白天重拨 ddns 域名等待解析,此功能不影响断网检测<br/>因夜间跑流量问题,该功能可能不稳定")
a:depends({err_enable="1"})
a= s:option(DynamicList, "err_device_aliases", translate("关注列表"))
a.rmempty = true
a.description = translate("只会在列表中设备都不在线时才会执行<br/>免打扰时段一小时后关注设备五分钟低流量约100kb/m将视为离线")
nt.mac_hints(function(mac, name) a :value(mac, "%s (%s)" %{ mac, name }) end)
a:depends({err_enable="1"})
a=s:option(ListValue,"network_err_event",translate("网络断开时"))
a.default=""
a:depends({err_enable="1"})
a:value("",translate("无操作"))
a:value("1",translate("重启路由器"))
a:value("2",translate("重新拨号"))
a:value("3",translate("修改相关设置项,尝试自动修复网络"))
a.description = translate("选项 1 选项 2 不会修改设置,并最多尝试 2 次。<br/>选项 3 会将设置项备份于 /usr/bin/pushbot/configbak 目录,并在失败后还原。<br/>【!!无法保证兼容性!!】不熟悉系统设置项,不会救砖请勿使用")
a=s:option(ListValue,"system_time_event",translate("定时重启"))
a.default=""
a:depends({err_enable="1"})
a:value("",translate("无操作"))
a:value("1",translate("重启路由器"))
a:value("2",translate("重新拨号"))
a= s:option(Value, "autoreboot_time", "系统运行时间大于")
a.rmempty = true
a.default = "24"
a.datatype="uinteger"
a:depends({system_time_event="1"})
a.description = translate("单位为小时")
a=s:option(Value, "network_restart_time", "网络在线时间大于")
a.rmempty = true
a.default = "24"
a.datatype="uinteger"
a:depends({system_time_event="2"})
a.description = translate("单位为小时")
a=s:option(Flag,"public_ip_event",translate("重拨尝试获取公网 ip"))
a.default=0
a.rmempty=true
a:depends({err_enable="1"})
a.description = translate("重拨时不会推送 ip 变动通知,并会导致你的域名无法及时更新 ip 地址<br/>请确认你可以通过重拨获取公网 ip否则这不仅徒劳无功还会引起频繁断网<br/>移动等大内网你就别挣扎了!!")
a= s:option(Value, "public_ip_retry_count", "当天最大重试次数")
a.rmempty = true
a.default = "10"
a.datatype="uinteger"
a:depends({public_ip_event="1"})
return m

View File

@ -1,6 +0,0 @@
f = SimpleForm("pushbot")
luci.sys.call("/usr/bin/pushbot/pushbot client")
f.reset = false
f.submit = false
f:append(Template("pushbot/pushbot_client"))
return f

View File

@ -1,5 +0,0 @@
f = SimpleForm("pushbot")
f.reset = false
f.submit = false
f:append(Template("pushbot/pushbot_log"))
return f

View File

@ -1,552 +0,0 @@
local nt = require "luci.sys".net
local fs=require"nixio.fs"
local e=luci.model.uci.cursor()
local net = require "luci.model.network".init()
local sys = require "luci.sys"
local ifaces = sys.net:devices()
m=Map("pushbot",translate("PushBot"),
translate("「全能推送」英文名「PushBot」是一款从服务器推送报警信息和日志到各平台的工具。<br>支持钉钉推送企业微信推送PushPlus推送。<br>本插件由tty228/luci-app-serverchan创建然后七年修改为全能推送自用。<br /><br />如果你在使用中遇到问题,请到这里提交:")
.. [[<a href="https://github.com/zzsj0928/luci-app-pushbot" target="_blank">]]
.. translate("github 项目地址")
.. [[</a>]]
)
m:section(SimpleSection).template = "pushbot/pushbot_status"
s=m:section(NamedSection,"pushbot","pushbot",translate(""))
s:tab("basic", translate("基本设置"))
s:tab("content", translate("推送内容"))
s:tab("crontab", translate("定时推送"))
s:tab("disturb", translate("免打扰"))
s.addremove = false
s.anonymous = true
--基本设置
a=s:taboption("basic", Flag,"pushbot_enable",translate("启用"))
a.default=0
a.rmempty = true
--精简模式
a = s:taboption("basic", MultiValue, "lite_enable", translate("精简模式"))
a:value("device", translate("精简当前设备列表"))
a:value("nowtime", translate("精简当前时间"))
a:value("content", translate("只推送标题"))
a.widget = "checkbox"
a.default = nil
a.optional = true
--推送模式
a=s:taboption("basic", ListValue,"jsonpath",translate("推送模式"))
a.default="/usr/bin/pushbot/api/dingding.json"
a.rmempty = true
a:value("/usr/bin/pushbot/api/dingding.json",translate("钉钉"))
a:value("/usr/bin/pushbot/api/ent_wechat.json",translate("企业微信"))
a:value("/usr/bin/pushbot/api/feishu.json",translate("飞书"))
a:value("/usr/bin/pushbot/api/bark.json",translate("Bark"))
a:value("/usr/bin/pushbot/api/pushplus.json",translate("PushPlus"))
a:value("/usr/bin/pushbot/api/pushdeer.json",translate("PushDeer"))
a:value("/usr/bin/pushbot/api/diy.json",translate("自定义推送"))
a=s:taboption("basic", Value,"dd_webhook",translate('Webhook'), translate("钉钉机器人 Webhook").."只输入access_token=后面的即可<br>调用代码获取<a href='https://developers.dingtalk.com/document/robots/custom-robot-access' target='_blank'>点击这里</a><br><br>")
a.rmempty = true
a:depends("jsonpath","/usr/bin/pushbot/api/dingding.json")
a=s:taboption("basic", Value, "we_webhook", translate("Webhook"),translate("企业微信机器人 Webhook").."只输入key=后面的即可<br>调用代码获取<a href='https://work.weixin.qq.com/api/doc/90000/90136/91770' target='_blank'>点击这里</a><br><br>")
a.rmempty = true
a:depends("jsonpath","/usr/bin/pushbot/api/ent_wechat.json")
a=s:taboption("basic", Value,"pp_token",translate('PushPlus Token'), translate("PushPlus Token").."<br>调用代码获取<a href='http://pushplus.plus/doc/' target='_blank'>点击这里</a><br><br>")
a.rmempty = true
a:depends("jsonpath","/usr/bin/pushbot/api/pushplus.json")
a=s:taboption("basic", ListValue,"pp_channel",translate('PushPlus Channel'))
a.rmempty = true
a:depends("jsonpath","/usr/bin/pushbot/api/pushplus.json")
a:value("wechat",translate("wechatPushPlus微信公众号"))
a:value("cp",translate("cp企业微信应用"))
a:value("webhook",translate("webhook第三方webhook"))
a:value("sms",translate("sms短信"))
a:value("mail",translate("mail邮箱"))
a.description = translate("第三方webhook企业微信、钉钉、飞书、server酱<br>sms短信/mail邮箱PushPlus暂未开放<br>具体channel设定参见<a href='http://pushplus.plus/doc/extend/webhook.html' target='_blank'>点击这里</a>")
a=s:taboption("basic", Value,"pp_webhook",translate('PushPlus Custom Webhook'), translate("PushPlus 自定义Webhook").."<br>第三方webhook或企业微信调用<br>具体自定义Webhook设定参见<a href='http://pushplus.plus/doc/extend/webhook.html' target='_blank'>点击这里</a><br><br>")
a.rmempty = true
a:depends("pp_channel","cp")
a:depends("pp_channel","webhook")
a=s:taboption("basic", Flag,"pp_topic_enable",translate("PushPlus 一对多推送"))
a.default=0
a.rmempty = true
a:depends("pp_channel","wechat")
a=s:taboption("basic", Value,"pp_topic",translate('PushPlus Topic'), translate("PushPlus 群组编码").."<br>一对多推送时指定的群组编码<br>具体群组编码Topic设定参见<a href='http://www.pushplus.plus/push2.html' target='_blank'>点击这里</a><br><br>")
a.rmempty = true
a:depends("pp_topic_enable","1")
a=s:taboption("basic", Value,"pushdeer_key",translate('PushDeer Key'), translate("PushDeer Key").."<br>调用代码获取<a href='http://www.pushdeer.com/' target='_blank'>点击这里</a><br><br>")
a.rmempty = true
a:depends("jsonpath","/usr/bin/pushbot/api/pushdeer.json")
a=s:taboption("basic", Flag,"pushdeer_srv_enable",translate("自建 PushDeer 服务器"))
a.default=0
a.rmempty = true
a:depends("jsonpath","/usr/bin/pushbot/api/pushdeer.json")
a=s:taboption("basic", Value,"pushdeer_srv",translate('PushDeer Server'), translate("PushDeer 自建服务器地址").."<br>如https://your.domain:port<br>具体自建服务器设定参见:<a href='http://www.pushdeer.com/selfhosted.html' target='_blank'>点击这里</a><br><br>")
a.rmempty = true
a:depends("pushdeer_srv_enable","1")
a=s:taboption("basic", Value,"fs_webhook",translate('WebHook'), translate("飞书 WebHook").."<br>调用代码获取<a href='https://www.feishu.cn/hc/zh-CN/articles/360024984973' target='_blank'>点击这里</a><br><br>")
a.rmempty = true
a:depends("jsonpath","/usr/bin/pushbot/api/feishu.json")
a=s:taboption("basic", Value,"bark_token",translate('Bark Token'), translate("Bark Token").."<br>调用代码获取<a href='https://github.com/Finb/Bark' target='_blank'>点击这里</a><br><br>")
a.rmempty = true
a:depends("jsonpath","/usr/bin/pushbot/api/bark.json")
a=s:taboption("basic", Flag,"bark_srv_enable",translate("自建 Bark 服务器"))
a.default=0
a.rmempty = true
a:depends("jsonpath","/usr/bin/pushbot/api/bark.json")
a=s:taboption("basic", Value,"bark_srv",translate('Bark Server'), translate("Bark 自建服务器地址").."<br>如https://your.domain:port<br>具体自建服务器设定参见:<a href='https://github.com/Finb/Bark' target='_blank'>点击这里</a><br><br>")
a.rmempty = true
a:depends("bark_srv_enable","1")
a=s:taboption("basic", Value,"bark_sound",translate('Bark Sound'), translate("Bark 通知声音").."<br>如silence.caf<br>具体设定参见:<a href='https://github.com/Finb/Bark/tree/master/Sounds' target='_blank'>点击这里</a><br><br>")
a.rmempty = true
a.default = "silence.caf"
a:depends("jsonpath","/usr/bin/pushbot/api/bark.json")
a=s:taboption("basic", Flag,"bark_icon_enable",translate(" Bark 通知图标"))
a.default=0
a.rmempty = true
a:depends("jsonpath","/usr/bin/pushbot/api/bark.json")
a=s:taboption("basic", Value,"bark_icon",translate('Bark Icon'), translate("Bark 通知图标").."(仅 iOS15 或以上支持)<br>如http://day.app/assets/images/avatar.jpg<br>具体设定参见:<a href='https://github.com/Finb/Bark#%E5%85%B6%E4%BB%96%E5%8F%82%E6%95%B0' target='_blank'>点击这里</a><br><br>")
a.rmempty = true
a.default = "http://day.app/assets/images/avatar.jpg"
a:depends("bark_icon_enable","1")
a=s:taboption("basic", Value,"bark_level",translate('Bark Level'), translate("Bark 时效性通知").."<br>可选参数值:<br/>active不设置时的默认值系统会立即亮屏显示通知。<br/>timeSensitive时效性通知可在专注状态下显示通知。<br/>passive仅将通知添加到通知列表不会亮屏提醒。")
a.rmempty = true
a.default = "active"
a:depends("jsonpath","/usr/bin/pushbot/api/bark.json")
a=s:taboption("basic", TextValue, "diy_json", translate("自定义推送"))
a.optional = false
a.rows = 28
a.wrap = "soft"
a.cfgvalue = function(self, section)
return fs.readfile("/usr/bin/pushbot/api/diy.json")
end
a.write = function(self, section, value)
fs.writefile("/usr/bin/pushbot/api/diy.json", value:gsub("\r\n", "\n"))
end
a:depends("jsonpath","/usr/bin/pushbot/api/diy.json")
a=s:taboption("basic", Button,"__add",translate("发送测试"))
a.inputtitle=translate("发送")
a.inputstyle = "apply"
function a.write(self, section)
luci.sys.call("cbi.apply")
luci.sys.call("/usr/bin/pushbot/pushbot test &")
end
a=s:taboption("basic", Value,"device_name",translate('本设备名称'))
a.rmempty = true
a.description = translate("在推送信息标题中会标识本设备名称,用于区分推送信息的来源设备")
a=s:taboption("basic", Value,"sleeptime",translate('检测时间间隔'))
a.rmempty = true
a.optional = false
a.default = "60"
a.datatype = "and(uinteger,min(10))"
a.description = translate("越短的时间时间响应越及时,但会占用更多的系统资源")
a=s:taboption("basic", ListValue,"oui_data",translate("MAC设备信息数据库"))
a.rmempty = true
a.default=""
a:value("",translate("关闭"))
a:value("1",translate("简化版"))
a:value("2",translate("完整版"))
a:value("3",translate("网络查询"))
a.description = translate("需下载 4.36m 原始数据,处理后完整版约 1.2M,简化版约 250kb <br/>若无梯子,请勿使用网络查询")
a=s:taboption("basic", Flag,"oui_dir",translate("下载到内存"))
a.rmempty = true
a:depends("oui_data","1")
a:depends("oui_data","2")
a.description = translate("懒得做自动更新了,下载到内存中,重启会重新下载 <br/>若无梯子,还是下到机身吧")
a=s:taboption("basic", Flag,"reset_regularly",translate("每天零点重置流量数据"))
a.rmempty = true
a=s:taboption("basic", Flag,"debuglevel",translate("开启日志"))
a.rmempty = true
a= s:taboption("basic", DynamicList, "device_aliases", translate("设备别名"))
a.rmempty = true
a.description = translate("<br/> 请输入设备 MAC 和设备别名,用“-”隔开,如:<br/> XX:XX:XX:XX:XX:XX-我的手机")
--设备状态
a=s:taboption("content", ListValue,"pushbot_ipv4",translate("IPv4 变更通知"))
a.rmempty = true
a.default=""
a:value("",translate("关闭"))
a:value("1",translate("通过接口获取"))
a:value("2",translate("通过URL获取"))
a = s:taboption("content", ListValue, "ipv4_interface", translate("接口名称"))
a.rmempty = true
a:depends({pushbot_ipv4="1"})
for _, iface in ipairs(ifaces) do
if not (iface == "lo" or iface:match("^ifb.*")) then
local nets = net:get_interface(iface)
nets = nets and nets:get_networks() or {}
for k, v in pairs(nets) do
nets[k] = nets[k].sid
end
nets = table.concat(nets, ",")
a:value(iface, ((#nets > 0) and "%s (%s)" % {iface, nets} or iface))
end
end
a.description = translate("<br/>一般选择 wan 接口,多拨环境请自行选择")
a=s:taboption("content", TextValue, "ipv4_list", translate("IPv4 API列表"))
a.optional = false
a.rows = 8
a.wrap = "soft"
a.cfgvalue = function(self, section)
return fs.readfile("/usr/bin/pushbot/api/ipv4.list")
end
a.write = function(self, section, value)
fs.writefile("/usr/bin/pushbot/api/ipv4.list", value:gsub("\r\n", "\n"))
end
a.description = translate("<br/>会因服务器稳定性、连接频繁等原因导致获取失败<br/>如接口可以正常获取 IP不推荐使用<br/>从以上列表中随机地址访问")
a:depends({pushbot_ipv4="2"})
a=s:taboption("content", ListValue,"pushbot_ipv6",translate("IPv6 变更通知"))
a.rmempty = true
a.default="disable"
a:value("0",translate("关闭"))
a:value("1",translate("通过接口获取"))
a:value("2",translate("通过URL获取"))
a = s:taboption("content", ListValue, "ipv6_interface", translate("接口名称"))
a.rmempty = true
a:depends({pushbot_ipv6="1"})
for _, iface in ipairs(ifaces) do
if not (iface == "lo" or iface:match("^ifb.*")) then
local nets = net:get_interface(iface)
nets = nets and nets:get_networks() or {}
for k, v in pairs(nets) do
nets[k] = nets[k].sid
end
nets = table.concat(nets, ",")
a:value(iface, ((#nets > 0) and "%s (%s)" % {iface, nets} or iface))
end
end
a.description = translate("<br/>一般选择 wan 接口,多拨环境请自行选择")
a=s:taboption("content", TextValue, "ipv6_list", translate("IPv6 API列表"))
a.optional = false
a.rows = 8
a.wrap = "soft"
a.cfgvalue = function(self, section)
return fs.readfile("/usr/bin/pushbot/api/ipv6.list")
end
a.write = function(self, section, value)
fs.writefile("/usr/bin/pushbot/api/ipv6.list", value:gsub("\r\n", "\n"))
end
a.description = translate("<br/>会因服务器稳定性、连接频繁等原因导致获取失败<br/>如接口可以正常获取 IP不推荐使用<br/>从以上列表中随机地址访问")
a:depends({pushbot_ipv6="2"})
a=s:taboption("content", Flag,"pushbot_up",translate("设备上线通知"))
a.default=1
a.rmempty = true
a=s:taboption("content", Flag,"pushbot_down",translate("设备下线通知"))
a.default=1
a.rmempty = true
a=s:taboption("content", Flag,"cpuload_enable",translate("CPU 负载报警"))
a.default=1
a.rmempty = true
a= s:taboption("content", Value, "cpuload", "负载报警阈值")
a.default = 2
a.rmempty = true
a:depends({cpuload_enable="1"})
a=s:taboption("content", Flag,"temperature_enable",translate("CPU 温度报警"))
a.default=1
a.rmempty = true
a.description = translate("请确认设备可以获取温度,如需修改命令,请移步高级设置")
a= s:taboption("content", Value, "temperature", "温度报警阈值")
a.rmempty = true
a.default = "80"
a.datatype="uinteger"
a:depends({temperature_enable="1"})
a.description = translate("<br/>设备报警只会在连续五分钟超过设定值时才会推送<br/>而且一个小时内不会再提醒第二次")
a=s:taboption("content", Flag,"client_usage",translate("设备异常流量"))
a.default=0
a.rmempty = true
a= s:taboption("content", Value, "client_usage_max", "每分钟流量限制")
a.default = "10M"
a.rmempty = true
a:depends({client_usage="1"})
a.description = translate("设备异常流量警报byte你可以追加 K 或者 M")
a=s:taboption("content", Flag,"client_usage_disturb",translate("异常流量免打扰"))
a.default=1
a.rmempty = true
a:depends({client_usage="1"})
a = s:taboption("content", DynamicList, "client_usage_whitelist", translate("异常流量关注列表"))
nt.mac_hints(function(mac, name) a:value(mac, "%s (%s)" %{ mac, name }) end)
a.rmempty = true
a:depends({client_usage_disturb="1"})
a.description = translate("请输入设备 MAC")
--LoginNoti
a=s:taboption("content", Flag,"web_logged",translate("Web 登录提醒"))
a.default=0
a.rmempty = true
a=s:taboption("content", Flag,"ssh_logged",translate("SSH 登录提醒"))
a.default=0
a.rmempty = true
a=s:taboption("content", Flag,"web_login_failed",translate("Web 错误尝试提醒"))
a.default=0
a.rmempty = true
a=s:taboption("content", Flag,"ssh_login_failed",translate("SSH 错误尝试提醒"))
a.default=0
a.rmempty = true
a= s:taboption("content", Value, "login_max_num", "错误尝试次数")
a.default = "3"
a.datatype="and(uinteger,min(1))"
a:depends("web_login_failed","1")
a:depends("ssh_login_failed","1")
a.description = translate("超过次数后推送提醒")
a=s:taboption("content", Flag,"web_login_black",translate("自动拉黑"))
a.default=0
a.rmempty = true
a:depends("web_login_failed","1")
a:depends("ssh_login_failed","1")
a.description = translate("直到重启前都不会重置次数,请先添加白名单")
a= s:taboption("content", Value, "ip_black_timeout", "拉黑时间(秒)")
a.default = "86400"
a.datatype="and(uinteger,min(0))"
a:depends("web_login_black","1")
a.description = translate("0 为永久拉黑,慎用<br>如不幸误操作,请更改设备 IP 进入 LUCI 界面清空规则")
a=s:taboption("content", DynamicList, "ip_white_list", translate("白名单 IP 列表"))
a.datatype = "ipaddr"
a.rmempty = true
luci.ip.neighbors({family = 4}, function(entry)
if entry.reachable then
a:value(entry.dest:string())
end
end)
a:depends("web_logged","1")
a:depends("ssh_logged","1")
a:depends("web_login_failed","1")
a:depends("ssh_login_failed","1")
a.description = translate("忽略白名单登陆提醒和拉黑操作,暂不支持掩码位表示")
a=s:taboption("content", TextValue, "ip_black_list", translate("IP 黑名单列表"))
a.optional = false
a.rows = 8
a.wrap = "soft"
a.cfgvalue = function(self, section)
return fs.readfile("/usr/bin/pushbot/api/ip_blacklist")
end
a.write = function(self, section, value)
fs.writefile("/usr/bin/pushbot/api/ip_blacklist", value:gsub("\r\n", "\n"))
end
a:depends("web_login_black","1")
--定时推送
a=s:taboption("crontab", ListValue,"crontab",translate("定时任务设定"))
a.rmempty = true
a.default=""
a:value("",translate("关闭"))
a:value("1",translate("定时发送"))
a:value("2",translate("间隔发送"))
a=s:taboption("crontab", ListValue,"regular_time",translate("发送时间"))
a.rmempty = true
for t=0,23 do
a:value(t,translate("每天"..t..""))
end
a.default=8
a.datatype=uinteger
a:depends("crontab","1")
a=s:taboption("crontab", ListValue,"regular_time_2",translate("发送时间"))
a.rmempty = true
a:value("",translate("关闭"))
for t=0,23 do
a:value(t,translate("每天"..t..""))
end
a.default="关闭"
a.datatype=uinteger
a:depends("crontab","1")
a=s:taboption("crontab", ListValue,"regular_time_3",translate("发送时间"))
a.rmempty = true
a:value("",translate("关闭"))
for t=0,23 do
a:value(t,translate("每天"..t..""))
end
a.default="关闭"
a.datatype=uinteger
a:depends("crontab","1")
a=s:taboption("crontab", ListValue,"interval_time",translate("发送间隔"))
a.rmempty = true
for t=1,23 do
a:value(t,translate(t.."小时"))
end
a.default=6
a.datatype=uinteger
a:depends("crontab","2")
a.description = translate("<br/>从 00:00 开始,每 * 小时发送一次")
a= s:taboption("crontab", Value, "send_title", translate("推送标题"))
a:depends("crontab","1")
a:depends("crontab","2")
a.placeholder = "OpenWrt By tty228 路由状态:"
a.description = translate("<br/>使用特殊符号可能会造成发送失败")
a=s:taboption("crontab", Flag,"router_status",translate("系统运行情况"))
a.default=1
a:depends("crontab","1")
a:depends("crontab","2")
a=s:taboption("crontab", Flag,"router_temp",translate("设备温度"))
a.default=1
a:depends("crontab","1")
a:depends("crontab","2")
a=s:taboption("crontab", Flag,"router_wan",translate("WAN信息"))
a.default=1
a:depends("crontab","1")
a:depends("crontab","2")
a=s:taboption("crontab", Flag,"client_list",translate("客户端列表"))
a.default=1
a:depends("crontab","1")
a:depends("crontab","2")
a=s:taboption("crontab", Value,"google_check_timeout",translate("全球互联检测超时时间"))
a.rmempty = true
a.optional = false
a.default = "10"
a.datatype = "and(uinteger,min(3))"
a.description = translate("过短的时间可能导致检测不准确")
e=s:taboption("crontab", Button,"_add",translate("手动发送"))
e.inputtitle=translate("发送")
e:depends("crontab","1")
e:depends("crontab","2")
e.inputstyle = "apply"
function e.write(self, section)
luci.sys.call("cbi.apply")
luci.sys.call("/usr/bin/pushbot/pushbot send &")
end
--免打扰
a=s:taboption("disturb", ListValue,"pushbot_sheep",translate("免打扰时段设置"),translate("在指定整点时间段内,暂停推送消息<br/>免打扰时间中,定时推送也会被阻止。"))
a.rmempty = true
a:value("",translate("关闭"))
a:value("1",translate("模式一:脚本挂起"))
a:value("2",translate("模式二:静默模式"))
a.description = translate("模式一停止一切检测,包括无人值守。")
a=s:taboption("disturb", ListValue,"starttime",translate("免打扰开始时间"))
a.rmempty = true
for t=0,23 do
a:value(t,translate("每天"..t..""))
end
a.default=0
a.datatype=uinteger
a:depends({pushbot_sheep="1"})
a:depends({pushbot_sheep="2"})
a=s:taboption("disturb", ListValue,"endtime",translate("免打扰结束时间"))
a.rmempty = true
for t=0,23 do
a:value(t,translate("每天"..t..""))
end
a.default=8
a.datatype=uinteger
a:depends({pushbot_sheep="1"})
a:depends({pushbot_sheep="2"})
a=s:taboption("disturb", ListValue,"macmechanism",translate("MAC过滤"))
a:value("",translate("disable"))
a:value("allow",translate("忽略列表内设备"))
a:value("block",translate("仅通知列表内设备"))
a:value("interface",translate("仅通知此接口设备"))
a.rmempty = true
a = s:taboption("disturb", DynamicList, "pushbot_whitelist", translate("忽略列表"))
nt.mac_hints(function(mac, name) a :value(mac, "%s (%s)" %{ mac, name }) end)
a.rmempty = true
a:depends({macmechanism="allow"})
a.description = translate("AA:AA:AA:AA:AA:AA\\|BB:BB:BB:BB:BB:B 可以将多个 MAC 视为同一用户<br/>任一设备在线后不再推送,设备全部离线时才会推送,避免双 wifi 频繁推送")
a = s:taboption("disturb", DynamicList, "pushbot_blacklist", translate("关注列表"))
nt.mac_hints(function(mac, name) a:value(mac, "%s (%s)" %{ mac, name }) end)
a.rmempty = true
a:depends({macmechanism="block"})
a.description = translate("AA:AA:AA:AA:AA:AA\\|BB:BB:BB:BB:BB:B 可以将多个 MAC 视为同一用户<br/>任一设备在线后不再推送,设备全部离线时才会推送,避免双 wifi 频繁推送")
a = s:taboption("disturb", ListValue, "pushbot_interface", translate("接口名称"))
a:depends({macmechanism="interface"})
a.rmempty = true
for _, iface in ipairs(ifaces) do
if not (iface == "lo" or iface:match("^ifb.*")) then
local nets = net:get_interface(iface)
nets = nets and nets:get_networks() or {}
for k, v in pairs(nets) do
nets[k] = nets[k].sid
end
nets = table.concat(nets, ",")
a:value(iface, ((#nets > 0) and "%s (%s)" % {iface, nets} or iface))
end
end
a=s:taboption("disturb", ListValue,"macmechanism2",translate("MAC过滤2"))
a:value("",translate("disable"))
a:value("MAC_online",translate("列表内任意设备在线时免打扰"))
a:value("MAC_offline",translate("列表内设备都离线后免打扰"))
a.rmempty = true
a = s:taboption("disturb", DynamicList, "MAC_online_list", translate("在线免打扰列表"))
nt.mac_hints(function(mac, name) a:value(mac, "%s (%s)" %{ mac, name }) end)
a.rmempty = true
a:depends({macmechanism2="MAC_online"})
a = s:taboption("disturb", DynamicList, "MAC_offline_list", translate("任意离线免打扰列表"))
nt.mac_hints(function(mac, name) a:value(mac, "%s (%s)" %{ mac, name }) end)
a.rmempty = true
a:depends({macmechanism2="MAC_offline"})
return m

View File

@ -1,33 +0,0 @@
<%
local dsp = require "luci.dispatcher"
-%>
<script type="text/javascript">
//<![CDATA[
function clearlog(btn) {
XHR.get('<%=dsp.build_url("admin/services/pushbot/clear_log")%>', null,
function(x, data) {
if(x && x.status == 200) {
var log_textarea = document.getElementById('log_textarea');
log_textarea.innerHTML = "";
log_textarea.scrollTop = log_textarea.scrollHeight;
}
}
);
}
XHR.poll(2, '<%=dsp.build_url("admin/services/pushbot/get_log")%>', null,
function(x, data) {
if(x && x.status == 200 && document.getElementById("checkbox1").checked == true) {
var log_textarea = document.getElementById('log_textarea');
log_textarea.innerHTML = x.responseText;
log_textarea.scrollTop = log_textarea.scrollHeight;
}
}
);
//]]>
</script>
<fieldset class="cbi-section" id="_log_fieldset">
<input type="checkbox" id="checkbox1" style="vertical-align:middle;height: auto;"checked><%:自动刷新%></input>
<input class="cbi-button cbi-input-remove" type="button" onclick="clearlog()" value="<%:清除日志%>" />
<textarea id="log_textarea" class="cbi-input-textarea" style="width: 100%;margin-top: 10px;" data-update="change" rows="30" wrap="off" readonly="readonly"></textarea>
</fieldset>

View File

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

View File

@ -1,10 +0,0 @@
config pushbot 'pushbot'
option pushbot_enable '0'
option sleeptime '60'
option pushbot_ipv6 '0'
option pushbot_up '1'
option pushbot_down '1'
option cpuload_enable '1'
option cpuload '2'
option temperature_enable '0'

View File

@ -1,26 +0,0 @@
#!/bin/sh /etc/rc.common
START=99
STOP=10
start() {
state=`pgrep -f "/usr/bin/pushbot/pushbot"`
if [ ! -z "$state" ]; then
restart
else
/usr/bin/pushbot/pushbot &
fi
echo "pushbot is starting now ..."
}
stop() {
kill -9 `pgrep -f "/usr/bin/pushbot/pushbot"` 2>/dev/null
echo "pushbot exit ..."
}
restart(){
stop
sleep 1
start
echo "restarted."
}

View File

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

View File

@ -1,36 +0,0 @@
{
"_api": "这是Bark推送 post 模板信息 api 文件",
"_api": "【Bark推送】",
"url": "${bark_srv}/push",
"data": "@${tempjsonpath}",
"content_type": "Content-Type: application/json; charset=utf-8",
"str_title_start": "【",
"str_title_end": "】",
"str_linefeed": "\\n",
"str_splitline": "\\n\\n",
"str_space": " ",
"str_tab": " ",
"table_tab": "",
"font_green": "",
"font_green2": "",
"font_red": "",
"font_blue": "",
"font_purple": "",
"font_end": "",
"font_end2": "",
"percentsym": "",
"boldstar": "",
"type": {
"device_key": "\"${bark_token}\"",
"title": "\"${1}\"",
"body": "\"${nowtime}${str_linefeed}${2}\"",
"ext_params": {
"group": "\"${device_name}\"",
"isArchive": "1",
"icon": "\"${bark_icon}\"",
"level": "\"${bark_level}\""
},
"sound": "\"${bark_sound}\""
}
}

View File

@ -1,32 +0,0 @@
{
"_api": "这是 Pushbot:钉钉 api 文件",
"_api": "【钉钉推送】",
"url": "\"https://oapi.dingtalk.com/robot/send?access_token=${dd_webhook}\"",
"data": "@${tempjsonpath}",
"content_type": "Content-Type:application/json",
"str_title_start": "**",
"str_title_end": "**",
"str_linefeed": "\\n\\n",
"str_splitline": "\\n\\n---\\n\\n",
"str_space": " ",
"str_tab": " ",
"table_tab": "<font color=#76CCFF>┋</font>",
"font_green": "<font color=#92D050>",
"font_green2": "<font color=#92D050>",
"font_red": "<font color=#FF6666>",
"font_blue": "<font color=#76CCFF>",
"font_purple": "<font color=#6A65FF>",
"font_end": "</font>",
"font_end2": "</font>",
"percentsym": "",
"boldstar": "**",
"type":
{
"msgtype": "\"markdown\"",
"markdown": {
"title": "\"${1}\"",
"text": "\"${str_title_start}${font_purple}${1}${font_end}${str_title_end}${str_linefeed}${nowtime}${str_linefeed}${2}${str_linefeed}${font_purple}${1}${font_end}\""
}
}
}

View File

@ -1,50 +0,0 @@
{
"_//": "-------------------------------------------------------------------------------",
"_readme": "这是 自定义 api 文件,这里以 telegram 为例",
"_readme": "特殊符号请使用斜杠转义,变量使用 ${var} 表示",
"_//": "-------------------------------------------------------------------------------",
"_api": "【DIY 推送】",
"_url": "api 地址",
"_data": "生成的 json 文件路径,一般不需要改,如 api 不支持 json请参考 serverchan 推送接口",
"_content_type": "post 内容类型,这里为 json",
"_//": "-------------------------------------------------------------------------------",
"_str_title_start": "标题粗体字开始符号",
"_str_title_end": "标题粗体字结束符号",
"_str_linefeed": "换行符号",
"_str_splitline": "换行+分隔符",
"_str_space": "空格",
"_str_tab": "TAB用在行首生成文字区块",
"_//": "-------------------------------------------------------------------------------",
"_type":
{
"_readme": "type 对象因为需要转义变量,前后必须使用 斜杠+双引号 转义",
"_readme": "参照上文说明,填写下文相关参数"
},
"_//": "-------------------------------------------------------------------------------",
"url": "https://api.telegram.org/bot${tg_token}/sendMessage",
"data": "@${tempjsonpath}",
"content_type": "Content-Type: application/json",
"str_title_start": "<b>",
"str_title_end": "</b>",
"str_linefeed": "\\n",
"str_splitline": "\\n----\\n",
"str_space": " ",
"str_tab": " ",
"table_tab": "<font color=#76CCFF>┋</font>",
"font_green": "<font color=#92D050>",
"font_green2": "<font color=#92D050>",
"font_red": "<font color=#FF6666>",
"font_blue": "<font color=#76CCFF>",
"font_purple": "<font color=#6A65FF>",
"font_end": "</font>",
"font_end2": "</font>",
"percentsym": "25",
"boldstar": "**",
"type":
{
"text":"\"${str_title_start}${1}${str_title_end}${str_splitline}${nowtime}${2}\"",
"chat_id":"\"${chat_id}\"",
"parse_mode":"\"HTML\""
}
}

View File

@ -1,32 +0,0 @@
{
"_api": "这是企业微信 markdown 模板信息 api 文件",
"_api": "【企业微信】",
"url": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${we_webhook}",
"data": "@${tempjsonpath}",
"content_type": "Content-Type: application/json",
"str_title_start": "#### ",
"str_title_end": "",
"str_linefeed": "\\n",
"str_splitline": "\\n------\\n",
"str_space": " ",
"str_tab": " ",
"table_tab": "<font color=#76CCFF>┋</font>",
"font_green": "<font color=#92D050>",
"font_green2": "<font color=#92D050>",
"font_red": "<font color=#FF6666>",
"font_blue": "<font color=#76CCFF>",
"font_purple": "<font color=#6A65FF>",
"font_end": "</font>",
"font_end2": "</font>",
"percentsym": "",
"boldstar": "**",
"type":
{
"msgtype": "\"markdown\"",
"markdown": {
"title": "\"${1}\"",
"content": "\"${str_title_start}${font_purple}${1}${font_end}${str_title_end}${str_linefeed}${nowtime}${str_linefeed}${2}\""
}
}
}

View File

@ -1,61 +0,0 @@
{
"_api": "这是飞书推送 post 模板信息 api 文件",
"_api": "【飞书推送】",
"url": "https://open.feishu.cn/open-apis/bot/v2/hook/${fs_webhook}",
"data": "@${tempjsonpath}",
"content_type": "Content-Type: application/json",
"str_title_start": "**",
"str_title_end": "**",
"str_linefeed": "\\n",
"str_splitline": "\\n\\n",
"str_space": " ",
"str_tab": " ",
"table_tab": "",
"font_green": "",
"font_green": "",
"font_red": "",
"font_blue": "",
"font_purple": "",
"font_end": "",
"font_end2": "",
"percentsym": "",
"boldstar": "**",
"type":
{
"msg_type": "\"interactive\"",
"card": {
"config": {
"wide_screen_mode": "true"
},
"header": {
"template": "\"purple\"",
"title": {
"content": "\"${1}\"",
"tag": "\"plain_text\""
}
},
"elements": [
{
"tag": "\"div\"",
"text": {
"content": "\"${nowtime}${str_linefeed}${2}\"",
"tag": "\"lark_md\""
}
},
{
"tag": "\"hr\""
},
{
"elements": [
{
"content": "\"来自${device_name}\"",
"tag": "\"lark_md\""
}
],
"tag": "\"note\""
}
]
}
}
}

View File

@ -1,6 +0,0 @@
www.cip.cc
ipv4.ddnspod.com
ifcfg.cn
speed.neu.edu.cn/getIP.php
ddns.oray.com/checkip
www.net.cn/static/customercare/yourip.asp

View File

@ -1,5 +0,0 @@
ip.sb
ipv6.ddnspod.com
api-ipv6.ip.sb/ip
speed.neu6.edu.cn/getIP.php
v6.myip.la/json

View File

@ -1,31 +0,0 @@
{
"_api": "这是 PushDeer推送 api 文件",
"_api": "【PushDeer推送】",
"url": "${pushdeer_srv}/message/push",
"data": "@${tempjsonpath}",
"content_type": "Content-Type:application/json",
"str_title_start": "**【",
"str_title_end": "】**",
"str_linefeed": "\\n\\n",
"str_splitline": "\\n\\n---\\n\\n",
"str_space": " ",
"str_tab": " ",
"table_tab": "┋",
"font_green": "",
"font_green2": "",
"font_red": "",
"font_blue": "",
"font_purple": "",
"font_end": "",
"font_end2": "",
"percentsym": "",
"boldstar": "**",
"type":
{
"pushkey": "\"${pushdeer_key}\"",
"type": "\"markdown\"",
"text": "\"${1}\"",
"desp": "\"${nowtime}${str_linefeed}${2}\""
}
}

View File

@ -1,34 +0,0 @@
{
"_api": "这是 Pushbot:PushPlus api 文件",
"_api": "【PushPlus推送】",
"url": "http://www.pushplus.plus/send",
"data": "@${tempjsonpath}",
"content_type": "Content-Type:application/json",
"str_title_start": "#### ",
"str_title_end": "",
"str_linefeed": "\\n\\n",
"str_splitline": "\\n----\\n",
"str_space": " ",
"str_tab": " ",
"table_tab": "",
"font_green": "<font color=#92D050>",
"font_green2": "",
"font_red": "<font color=#FF6666>",
"font_blue": "<font color=#76CCFF>",
"font_purple": "<font color=#6A65FF>",
"font_end": "</font>",
"font_end2": "",
"percentsym": "",
"boldstar": "",
"type":
{
"token": "\"${pp_token}\"",
"channel": "\"${pp_channel}\"",
"webhook": "\"${pp_webhook}\"",
"topic": "\"${pp_topic}\"",
"title": "\"${1}\"",
"content": "\"${2}\"",
"template": "\"markdown\""
}
}

File diff suppressed because it is too large Load Diff

View File

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

24
luci-app-wechatpush/Makefile Executable file
View File

@ -0,0 +1,24 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-wechatpush
PKG_VERSION:=3.3.2
PKG_RELEASE:=12
PKG_MAINTAINER:=tty228 <tty228@yeah.net>
LUCI_TITLE:=LuCI support for wechatpush
LUCI_PKGARCH:=all
LUCI_DEPENDS:=+iputils-arping +curl +jq +bash
define Package/$(PKG_NAME)/conffiles
/etc/config/wechatpush
/usr/share/wechatpush/api/diy.json
/usr/share/wechatpush/api/logo.jpg
/usr/share/wechatpush/api/ipv4.list
/usr/share/wechatpush/api/ipv6.list
/usr/share/wechatpush/api/device_aliases.list
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,92 @@
## 简介
[![Lastest Release](https://img.shields.io/github/release/tty228/luci-app-wechatpush.svg?style=flat)](https://github.com/tty228/luci-app-wechatpush/releases)
[![GitHub All Releases](https://img.shields.io/github/downloads/tty228/luci-app-wechatpush/total)](https://github.com/tty228/luci-app-wechatpush/releases)
[中文文档](README.md) | [English](README_en.md)
这是一款用于 OpenWRT 路由器上进行 微信/Telegram 推送的插件
推送服务支持列表:
| 推送应用 | 方式 | 接口说明 |
| :-------- | :----- | :----- |
| 微信 | Server酱 | https://sct.ftqq.com/
| 微信 | 推送加 | http://www.pushplus.plus/
| 微信 | WxPusher | https://wxpusher.zjiecode.com/docs
| 企业微信 | 应用推送 | https://work.weixin.qq.com/api/doc/90000/90135/90248
| Telegram | bot | https://t.me/BotFather
精力有限如需要钉钉推送、飞书推送、Bark 推送等请尝试另一个分支 https://github.com/zzsj0928/luci-app-pushbot ,或使用自定义 API 设置
因插件一开始只支持 Server酱故此插件命名为 luci-app-serverchan但后续已经越来越臃肿想改很久了趁这次升级 js 插件更名为 luci-app-wechatpush
v3.0.0 安装时会自动从 luci-app-serverchan 移植配置信息,并删除原插件,如有缺漏,请在 /etc/config/serverchan.bak 查看,安装后可能需刷新浏览器页面,否则 luci 页面入口不会更换为新插件 URL此功能择期移除
v2.06.2 之后的版本不再支持 LuCI 18.06,如需编译,请使用 openwrt-18.06 分支,拉取源码时请使用 `git clone -b openwrt-18.06 https://github.com/tty228/luci-app-wechatpush.git` 命令
## 主要功能
- [x] 路由 IP、IPv6 变动推送
- [x] 设备 上线、离线 推送
- [x] 设备在线列表及流量使用情况
- [x] CPU 负载、温度监视、PVE 宿主机温度监控
- [x] 路由运行状态定时推送
- [x] 路由 Web、SSH 登录提示,自动拉黑、端口敲门
- [x] 无人值守任务
## 说明
**关于安装:**
插件依赖 iputils-arping + curl + jq + bash对于内存有限的路由器请酌情安装**在安装之前,请先运行 `opkg update` 命令,以便在安装过程中安装依赖。**
基于 X86 OpenWrt v23.05.0 制作,不同系统不同设备,可能会遇到各种问题,**如获取到错误的温度信息、页面显示错误、报错等,自行适配**
**关于主机名:**
对于设备未宣告主机名、光猫拨号上网、OpenWrt 作为旁路网关等各类情况导致的获取主机名失败,可以通过以下方式设置主机名
- 使用设备名备注
- 在高级设置处配置从光猫获取
- 开启 MAC 设备数据库
**关于设备在线状态:**
默认使用 ping/arping 来主动探测设备在线状态,以对抗 Wi-Fi 休眠机制,主动探测较为耗时但可以获得较为精准的设备在线状态
- 如遇设备休眠频繁,请在高级设置处自行调整超时设置
- 如果不需要太过精准的设备在线信息,只需要其余功能,可以在高级设置中关闭主动探测
**关于流量统计信息:**
流量统计功能依赖 wrtbwmon ,需自行选装或编译,**该插件与 Routing/NAT 、Flow Offloading 、代理上网等插件冲突,开启后将会无法获取流量,请自行选择**
**关于 bug 提交:**
提交 bug 时请尽量带上以下信息
- 设备信息及插件版本号
- 执行 `/usr/share/wechatpush/wechatpush` 后的提示信息
- 报错后的日志信息、`/tmp/wechatpush/` 目录下的文件信息
- `bash -x /usr/share/wechatpush/wechatpush t1` 的详细运行信息
## 下载
| 支持的 OpenWrt 版本 | 下载地址 |
| :-------- | :----- |
| openwrt-19.07.0 ... latest | [![Lastest Release](https://img.shields.io/github/release/tty228/luci-app-wechatpush.svg?style=flat)](https://github.com/tty228/luci-app-wechatpush/releases)
| openwrt-18.06 | [![Release v2.06.2](https://img.shields.io/badge/release-v2.06.2-lightgrey.svg)](https://github.com/tty228/luci-app-wechatpush/releases/tag/v2.06.2)
## 捐赠
如果你觉得此项目对你有帮助,请捐助我们,使项目能持续发展和更加完善。
![image](https://github.com/tty228/Python-100-Days/blob/master/res/WX.jpg)

View File

@ -0,0 +1,81 @@
# Introduction
[![Lastest Release](https://img.shields.io/github/release/tty228/luci-app-wechatpush.svg?style=flat)](https://github.com/tty228/luci-app-wechatpush/releases)
[![GitHub All Releases](https://img.shields.io/github/downloads/tty228/luci-app-wechatpush/total)](https://github.com/tty228/luci-app-wechatpush/releases)
[中文文档](README.md) | [English](README_en.md)
A plugin for OpenWRT routers to push various information to a mobile phone via WeChat or Telegram.
Supported services:
| Push application | Method | description |
| :-------- | :----- | :----- |
| WeChat | Server Chan | https://sct.ftqq.com/
| WeChat | PushPlus | http://www.pushplus.plus/
| WeChat | WxPusher | https://wxpusher.zjiecode.com/docs
| WeChat for Enterprise | Application Push | https://work.weixin.qq.com/api/doc/90000/90135/90248
| Telegram | bot | https://t.me/BotFather
Limited resources are available. If you need services such as DingTalk push, Feishu push, Bark push, etc., please try another branch at https://github.com/zzsj0928/luci-app-pushbot, or use custom API settings.
## Main Features
- [x] Push notifications for changes in router IP and IPv6.
- [x] Push notifications for device online/offline status.
- [x] Device online list and traffic usage.
- [x] CPU load and temperature monitoring, PVE host temperature monitoring.
- [x] Periodic push notifications for router status.
- [x] Web and SSH login prompts for the router, automatic blacklist and port knocking.
- [x] Unattended tasks.
## Instructions
**Regarding Installation:**
The plugin requires dependencies on iputils-arping + curl + jq + bash. For routers with limited memory, please consider the installation carefully. **Before installing, please run the opkg update command to install dependencies during the installation process.**
Developed based on X86 OpenWrt v23.05.0, different systems and devices may encounter various issues. **If you encounter errors in temperature information retrieval, display errors, or other issues, please adapt accordingly.**
**Regarding Hostnames:**
For devices that do not declare hostnames, devices connected via optical modem dial-up, OpenWrt used as a bypass gateway, and other scenarios where hostname retrieval fails, you can set the hostname using the following methods:
- Use device name remarks.
- Configure to obtain the hostname from the optical modem in advanced settings.
- Enable MAC device database.
**Regarding Device Online Status:**
By default, ping/arping is used to actively detect device online status to counter Wi-Fi sleep mechanism. Active detection takes more time but provides more accurate device online status.
- If devices frequently go into sleep mode, please adjust the timeout settings in advanced settings.
- If you don't require highly precise device online information and only need other features, you can disable active detection in advanced settings.
**Regarding Traffic Statistics:**
Traffic statistics functionality depends on `wrtbwmon`. Please install or compile it yourself. **Enabling this plugin will conflict with Routing/NAT, Flow Offloading, proxy internet access, and other plugins, resulting in the inability to obtain traffic statistics. Please choose accordingly.**
**Regarding Bug Submissions:**
When submitting a bug, please provide the following information if possible:
- Device information and plugin version number.
- Prompt information after executing `/usr/share/wechatpush/wechatpush`.
- Log information and file information in the `/tmp/wechatpush/` directory after encountering an error.
- Detailed execution information of `bash -x /usr/share/wechatpush/wechatpush t1`.
## DownLoad
| Supported OpenWrt Versions | Download Link |
| :-------- | :----- |
| openwrt-19.07.0 ... latest | [![Lastest Release](https://img.shields.io/github/release/tty228/luci-app-wechatpush.svg?style=flat)](https://github.com/tty228/luci-app-wechatpush/releases)
| openwrt-18.06 | [![Release v2.06.2](https://img.shields.io/badge/release-v2.06.2-lightgrey.svg)](https://github.com/tty228/luci-app-wechatpush/releases/tag/v2.06.2)
## Donate
If you feel that this project is helpful to you, please donate to us so that the project can continue to develop and be more perfect.
![image](https://github.com/tty228/Python-100-Days/blob/master/res/WX.jpg)

View File

@ -0,0 +1,200 @@
'use strict';
'require view';
'require fs';
'require ui';
'require uci';
'require rpc';
'require form';
'require tools.widgets as widgets';
'require tools.firewall as fwtool';
return view.extend({
render: function (data) {
var m, s, o;
var programPath = '/usr/share/wechatpush/wechatpush';
m = new form.Map('wechatpush', _(''))
m.description = _("If you are not familiar with the meanings of these options, please do not modify them.<br/><br/>")
s = m.section(form.NamedSection, 'config', 'wechatpush', _(''));
s.anonymous = true
s.addremove = false
o = s.option(form.Value, 'up_timeout', _('Device online detection timeout (s)'));
o.placeholder = "2"
o.optional = false
o.datatype = "uinteger"
o.rmempty = false;
o = s.option(form.Value, "down_timeout", _('Device offline detection timeout (s)'))
o.placeholder = "10"
o.optional = false
o.datatype = "uinteger"
o.rmempty = false;
o = s.option(form.Value, "timeout_retry_count", _('Offline detection count'))
o.placeholder = "2"
o.optional = false
o.datatype = "uinteger"
o.rmempty = false;
o.description = _("If the device has good signal strength and no Wi-Fi sleep issues, you can reduce the above values.<br/>Due to the mysterious nature of Wi-Fi sleep during the night, if you encounter frequent disconnections, please adjust the parameters accordingly.<br/>..╮(╯_╰╭..")
o = s.option(form.Flag, "only_timeout_push", _("Offline timeout applies only to the devices that receive push notifications"))
o.default = 0
o.rmempty = true
o.description = _("When this option is selected, the offline timeout and offline detection count apply only to the devices that require push notifications. Other devices will use default values, which can significantly reduce the time required for detection. However, it may result in inaccurate online time displayed in the online devices list. It is recommended to enable this option only when there are many devices and frequent offline occurrences are observed for specific devices of interest.")
o = s.option(form.Flag, "passive_mode", _("Disable active detection"))
o.default = 0
o.rmempty = true
o.description = _("Disable active detection of client online status. Enabling this feature will no longer prompt device online/offline events.<br/>Suitable for users who are not sensitive to online devices but need other features.")
o = s.option(form.Value, "thread_num", _('Maximum concurrent processes'))
o.placeholder = "3"
o.datatype = "uinteger"
o.rmempty = false;
o.description = _("Do not change the setting value for low-performance devices, or reduce the parameters as appropriate.")
o = s.option(form.Value, "soc_code", _('Custom temperature reading command'))
o.rmempty = true
o.value("", _("Default"))
o.value("pve", _("Proxmox Virtual Environment"))
o.description = _("If you need to use special symbols such as quotes, $, !, etc. in custom commands, you need to escape them yourself.<br/>You can use the command eval echo $(uci get wechatpush.wechatpush.soc_code) to view command output and error information.<br/>The execution result should be a pure number (including decimals) for temperature comparison.<br/>Here is an example that does not require escaping:<br/>cat /sys/class/thermal/thermal_zone0/temp|sort -nr|head -n1|cut -c-2")
o = s.option(form.Value, "server_host", _("Host machine address"))
o.rmempty = true
o.default = "10.0.0.2"
o.depends('soc_code', 'pve');
o = s.option(form.Value, "server_port", _("Host machine SSH port"))
o.rmempty = true
o.default = "22"
o.description = _('The default SSH port is 22. If you have a custom port, please fill in the custom SSH port.<br/>Please make sure you have set up key-based login, otherwise it may cause script errors.<br/>Install the sensors command on PVE by searching on the internet.<br/>Example for key-based login (modify the address and port number accordingly):<br/>opkg update # Update package list<br/>opkg install openssh-client openssh-keygen # Install openssh client<br/>echo -e \"\\n\" | ssh-keygen -t rsa # Generate key file (no passphrase)<br/>pve_host=`uci get wechatpush.config.server_host` || pve_host=\"10.0.0.3\" # Read the PVE host address from the configuration file, If not saved, please fill in by yourself.<br/>pve_port=`uci get wechatpush.config.server_port` || pve_host=\"22\" # Read the PVE host SSH port number from the configuration file, If not saved, please fill in by yourself.<br/>ssh -o StrictHostKeyChecking=yes root@${pve_host} -p ${pve_port} \"tee -a ~/.ssh/OpenWrt_id_rsa.pub\" < ~/.ssh/id_rsa.pub # Transfer public key to PVE<br/>ssh root@${pve_host} -p ${pve_port} \"cat ~/.ssh/OpenWrt_id_rsa.pub >> ~/.ssh/authorized_keys\" # Write public key to PVE<br/>ssh -i /root/.ssh/id_rsa root@${pve_host} -p ${pve_port} sensors # To avoid script errors during the initial connection, please use a private key to connect to PVE and test the temperature command for its proper functioning.<br/>For users who frequently flash firmware, please add /root/.ssh/ to the backup list to avoid duplicate operations.');
o.depends('soc_code', 'pve');
o = s.option(form.Button, '_soc', _('Test temperature command'), _('You may need to save the configuration before sending.'));
o.inputstyle = 'action';
o.onclick = function () {
var _this = this;
return fs.exec(programPath, ['soc']).then(function (res) {
if (!res.stdout) {
throw new Error(_('Returned temperature value is empty'));
}
_this.description = res.stdout.trim();
return _this.map.reset();
}).catch(function (err) {
_this.description = _('Fetch failed') + err.message;
return _this.map.reset();
});
};
o = s.option(form.MultiValue, 'device_info_helper', _('Assist in obtaining device information'));
o.value('gateway_info', _('Retrieve hostname list from modem'));
o.value('scan_local_ip', _('Scan local IP'));
o.modalonly = true;
o.description = _('When OpenWrt is used as a bypass gateway and cannot obtain device hostnames or a complete list of local network devices.<br/>the \"Retrieve hostname list from modem\" option has only been tested with HG5143F/HN8145V China Telecom gateways and may not be universally applicable.<br/>The \"Scan local IP\" option may not retrieve hostnames, so please use device name annotations in conjunction with it.');
o = s.option(form.Value, "gateway_host_url", _('Optical modem login URL'));
o.rmempty = true;
o.default = "http://192.168.1.1/cgi-bin/luci";
o.depends({ device_info_helper: "gateway_info", '!contains': true });
o = s.option(form.Value, "gateway_info_url", _('Device list JSON URL'));
o.rmempty = true;
o.default = "http://192.168.1.1/cgi-bin/luci/admin/allInfo";
o.description = _('Use F12 console to capture<br/>ip, devName, model are mandatory fields. Example JSON file information:<br/>{\"pc1\":{\"devName\":\"RouterOS\",\"model\":\"\",\"type\":\"pc\",\"ip\":\"192.168.1.7\"}}');
o.depends({ device_info_helper: "gateway_info", '!contains': true });
o = s.option(form.Value, "gateway_logout_url", _('Optical modem logout URL'))
o.rmempty = true
o.default = "http://192.168.1.1/cgi-bin/luci/admin/logout"
o.description = _("Not a mandatory field, but it may affect other users logging into the web management page, e.g., HG5143F")
o.depends({ device_info_helper: "gateway_info", '!contains': true });
o = s.option(form.Value, "gateway_username_id", _('Login page account input box ID'))
o.rmempty = true
o.default = "username"
o.depends({ device_info_helper: "gateway_info", '!contains': true });
o = s.option(form.Value, "gateway_password_id", _('Login page password input box ID'))
o.rmempty = true
o.default = "psd"
o.description = _("Right-click in the browser and select 'Inspect Element'")
o.depends({ device_info_helper: "gateway_info", '!contains': true });
o = s.option(form.Value, "gateway_username", _('Optical modem login account'))
o.rmempty = true
o.default = "useradmin"
o.depends({ device_info_helper: "gateway_info", '!contains': true });
o = s.option(form.Value, "gateway_password", _('Optical modem login password'))
o.rmempty = true
o.description = _("Use a regular account, no need for super password")
o.depends({ device_info_helper: "gateway_info", '!contains': true });
o = s.option(form.Value, "scan_ip_range", _('IP range to be scanned'))
o.rmempty = true
o.placeholder = _('192.168.1.1-100');
o.depends({ device_info_helper: "scan_local_ip", '!contains': true });
o = s.option(form.Value, 'device_info_helper_sleeptime', _('Interval for capturing info'));
o.rmempty = false;
o.placeholder = '600';
o.datatype = 'and(uinteger,min(60))'
o.description = _("Generally, frequent capturing is not necessary. Adjust it as needed.")
o.depends({ device_info_helper: "gateway_info", '!contains': true });
o.depends({ device_info_helper: "scan_local_ip", '!contains': true });
o = s.option(form.Flag, "unattended_enable", _("Unattended tasks"))
o.default = 0
o.rmempty = true
o.description = _("Please make sure the script can run properly, otherwise it may cause frequent restarts and other errors!")
o = s.option(form.Flag, 'zerotier_helper', _('Restart zerotier after IP change'));
o.description = _('An old issue with zerotier<br/>Cannot reconnect after disconnection, emmm, I don\'t know if it has been fixed now.');
o.depends('unattended_enable', '1');
o = s.option(form.Flag, "unattended_only_on_disturb_time", _("Redial only during Do-Not-Disturb period"))
o.default = 0
o.rmempty = true
o.description = _("Avoid redialing network during the day to prevent waiting for DDNS domain resolution. This feature does not affect disconnection detection.<br/>Due to the issue of certain apps consuming excessive data at night, this feature may be unstable.")
o.depends('unattended_enable', '1');
o = s.option(form.DynamicList, "unattended_device_aliases", _("Followed device list"))
o.rmempty = true
o.description = _("Will only be executed when none of the devices in the list are online.<br/>After an hour of Do-Not-Disturb period, if the devices in the focus list have low traffic (around 100kb/m) for five minutes, they will be considered offline.")
//nt.mac_hints(function(mac, name) o :value(mac, "%s (%s)" %{ mac, name }) end)
o.depends('unattended_enable', '1');
o = s.option(form.ListValue, "network_disconnect_event", _("When the network is disconnected"))
o.default = ""
o.value("", _("No operation"))
o.value("1", _("Restart the router"))
o.value("2", _("Redialing network"))
o.description = _("The restart operation will occur ten minutes after the network disconnection and will be attempted a maximum of two times. If the option to log in to the optical modem is available, this operation will attempt to restart the optical modem.<br/>【!!This feature cannot guarantee compatibility!!】")
o.depends('unattended_enable', '1');
o = s.option(form.ListValue, "unattended_autoreboot_mode", _("Scheduled reboot"))
o.default = ""
o.value("", _("No operation"))
o.value("1", _("Restart the router"))
o.value("2", _("Redialing network"))
o.depends('unattended_enable', '1');
o = s.option(form.Value, "autoreboot_system_uptime", _("System uptime greater than"))
o.rmempty = true
o.default = "24"
o.datatype = "uinteger"
o.description = _("Unit: hours")
o.depends('unattended_autoreboot_mode', '1');
o = s.option(form.Value, "autoreboot_network_uptime", _("Network uptime greater than"))
o.rmempty = true
o.default = "24"
o.datatype = "uinteger"
o.description = _("Unit: hours")
o.depends('unattended_autoreboot_mode', '2');
return m.render();
}
});

View File

@ -0,0 +1,264 @@
'use strict';
'require view';
'require fs';
'require ui';
return view.extend({
load: function () {
return L.resolveDefault(fs.exec_direct('/usr/libexec/wechatpush-call', ['get_client'], 'json'), { devices: [] });
},
render: function (data) {
var devices = data.devices;
var totalDevices = devices.length;
var headers = [_('Hostname'), _('IPv4 address'), _('MAC address'), _('Interfaces'), _('Online time'), _('Details')];
var columns = ['name', 'ip', 'mac', 'interface', 'uptime', 'usage'];
var visibleColumns = [];
var hasData = false;
for (var i = 0; i < columns.length; i++) {
var column = columns[i];
var hasColumnData = false;
for (var j = 0; j < devices.length; j++) {
if (devices[j][column] !== '') {
hasColumnData = true;
hasData = true;
break;
}
}
if (hasColumnData) {
visibleColumns.push(i);
}
}
var style = `
.device-table {
width: 80%;
border-collapse: collapse;
}
.device-table th,
.device-table td {
padding: 0.5rem;
text-align: center;
border: 1px solid #ccc;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.device-table td:first-child {
word-wrap: break-word;
}
.device-table th {
background-color: #f2f2f2;
font-weight: bold;
color: #666;
cursor: pointer;
}
.device-table tbody tr:nth-of-type(even) {
background-color: #f9f9f9;
}
.sortable {
cursor: pointer;
position: relative;
}
.sortable::after {
content: '';
position: absolute;
right: -10px;
top: 50%;
transform: translateY(-50%);
width: 0;
height: 0;
border-style: solid;
border-width: 5px 5px 0 5px;
border-color: #aaa transparent transparent transparent;
opacity: 0.6;
}
.sortable.asc::after {
border-color: #666 transparent transparent transparent;
}
.sortable.desc::after {
border-color: transparent transparent #666 transparent;
}
.device-table .hide {
display: none;
}
@media (max-width: 767px) {
.device-table th:nth-of-type(4),
.device-table td:nth-of-type(4) {
display: none;
}
.device-table th,
.device-table td {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.device-table td:first-child {
max-width: 150px;
}
}
`;
function createTable() {
var table = document.createElement('table');
table.classList.add('device-table');
var thead = document.createElement('thead');
var tr = document.createElement('tr');
for (var i = 0; i < headers.length; i++) {
var th = document.createElement('th');
th.textContent = headers[i];
if (visibleColumns.includes(i)) {
th.classList.add('sortable');
th.dataset.column = columns[i];
} else {
th.classList.add('hide');
}
tr.appendChild(th);
}
thead.appendChild(tr);
table.appendChild(thead);
var tbody = document.createElement('tbody');
devices.forEach(function (device) {
var row = document.createElement('tr');
for (var i = 0; i < columns.length; i++) {
if (visibleColumns.includes(i)) {
var cell = document.createElement('td');
cell.textContent = device[columns[i]];
row.appendChild(cell);
}
}
tbody.appendChild(row);
});
table.appendChild(tbody);
return table;
}
var container = document.createElement('div');
container.appendChild(document.createElement('h2')).textContent = _('当前共 ') + totalDevices + _(' 台设备在线');
container.appendChild(createTable());
container.appendChild(document.createElement('style')).textContent = style;
function sortTable(column) {
var table = container.querySelector('.device-table');
var tbody = table.querySelector('tbody');
var rows = Array.from(tbody.querySelectorAll('tr'));
var isAscending = true;
if (table.classList.contains('sorted') && table.dataset.sortColumn === column) {
isAscending = !table.classList.contains('asc');
}
rows.sort(function (row1, row2) {
var value1 = row1.querySelector('td:nth-of-type(' + (visibleColumns.indexOf(column) + 1) + ')').textContent.toLowerCase();
var value2 = row2.querySelector('td:nth-of-type(' + (visibleColumns.indexOf(column) + 1) + ')').textContent.toLowerCase();
if (value1 < value2) {
return isAscending ? -1 : 1;
} else if (value1 > value2) {
return isAscending ? 1 : -1;
}
return 0;
});
tbody.innerHTML = '';
rows.forEach(function (row) {
tbody.appendChild(row);
});
table.classList.remove('sorted', 'asc', 'desc');
if (isAscending) {
table.classList.add('sorted', 'asc');
} else {
table.classList.add('sorted', 'desc');
}
table.dataset.sortColumn = column;
}
container.addEventListener('click', function (event) {
if (
event.target.tagName === 'TH' &&
event.target.parentNode.rowIndex === 0
) {
var columnIndex = event.target.cellIndex;
var table = container.querySelector('.device-table');
var tbody = table.querySelector('tbody');
var rows = Array.from(tbody.querySelectorAll('tr'));
rows.sort(function (row1, row2) {
var value1 = row1.cells[columnIndex].textContent.trim();
var value2 = row2.cells[columnIndex].textContent.trim();
if (columnIndex === 0) {
return value1.length - value2.length;
} else if (columnIndex === 1) {
value1 = ipToNumber(value1);
value2 = ipToNumber(value2);
} else if (columnIndex === 4) {
value1 = parseOnlineTime(value1);
value2 = parseOnlineTime(value2);
}
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
}
return 0;
});
rows.forEach(function (row) {
tbody.appendChild(row);
});
}
});
function ipToNumber(ipAddress) {
var parts = ipAddress.split('.');
var number = 0;
for (var i = 0; i < parts.length; i++) {
number = number * 256 + parseInt(parts[i]);
}
return number;
}
function parseOnlineTime(time) {
var regex = /(\d+)\s+(小时|分钟|秒)/g;
var matches = time.matchAll(regex);
var minutes = 0;
for (var match of matches) {
var value = parseInt(match[1]);
var unit = match[2];
if (unit === '小时') {
minutes += value * 60;
} else if (unit === '分钟') {
minutes += value;
}
}
return minutes;
}
return container;
},
handleSave: null,
handleSaveApply: null,
handleReset: null
});

View File

@ -0,0 +1,696 @@
'use strict';
'require view';
'require fs';
'require ui';
'require uci';
'require rpc';
'require form';
'require poll';
'require tools.widgets as widgets';
'require tools.firewall as fwtool';
var callServiceList = rpc.declare({
object: 'service',
method: 'list',
params: ['name'],
expect: { '': {} }
});
function getServiceStatus() {
return L.resolveDefault(callServiceList('wechatpush'), {}).then(function (res) {
console.log(res);
var isRunning = false;
try {
isRunning = res['wechatpush']['instances']['instance1']['running'];
} catch (e) { }
return isRunning;
});
}
function renderStatus(isRunning) {
var spanTemp = '<em><span style="color:%s"><strong>%s %s</strong></span></em>';
var renderHTML;
if (isRunning) {
renderHTML = String.format(spanTemp, 'green', _('wechatpush'), _('RUNNING'));
} else {
renderHTML = String.format(spanTemp, 'red', _('wechatpush'), _('NOT RUNNING'));
}
return renderHTML;
}
var cbiRichListValue = form.ListValue.extend({
renderWidget: function(section_id, option_index, cfgvalue) {
var choices = this.transformChoices();
var widget = new ui.Dropdown((cfgvalue != null) ? cfgvalue : this.default, choices, {
id: this.cbid(section_id),
sort: this.keylist,
optional: true,
select_placeholder: this.select_placeholder || this.placeholder,
custom_placeholder: this.custom_placeholder || this.placeholder,
validate: L.bind(this.validate, this, section_id),
disabled: (this.readonly != null) ? this.readonly : this.map.readonly
});
return widget.render();
},
value: function(value, title, description) {
if (description) {
form.ListValue.prototype.value.call(this, value, E([], [
E('span', { 'class': 'hide-open' }, [ title ]),
E('div', { 'class': 'hide-close', 'style': 'min-width:25vw' }, [
E('strong', [ title ]),
E('br'),
E('span', { 'style': 'white-space:normal' }, description)
])
]));
}
else {
form.ListValue.prototype.value.call(this, value, title);
}
}
});
return view.extend({
callHostHints: rpc.declare({
object: 'luci-rpc',
method: 'getHostHints',
expect: { '': {} }
}),
load: function () {
return Promise.all([
this.callHostHints()
]);
},
render: function (data) {
if (fwtool.checkLegacySNAT())
return fwtool.renderMigration();
else
return this.renderForwards(data);
},
renderForwards: function (data) {
var hosts = data[0],
m, s, o,
programPath = '/usr/share/wechatpush/wechatpush';
m = new form.Map('wechatpush', _('WeChat push'), _('A tool that can push device messages from OpenWrt to a mobile phone via WeChat or Telegram.<br /><br />If you encounter any issues while using it, please submit them here:') + '<a href="https://github.com/tty228/luci-app-wechatpush" target="_blank">' + _('GitHub Project Address') + '</a>');
s = m.section(form.TypedSection);
s.anonymous = true;
s.render = function () {
var statusView = E('p', { id: 'service_status' }, _('Collecting data ...'));
poll.add(function () {
return L.resolveDefault(getServiceStatus()).then(function (res) {
statusView.innerHTML = renderStatus(res);
});
});
setTimeout(function () {
poll.start();
}, 100);
return E('div', { class: 'cbi-section', id: 'status_bar' }, [
statusView
]);
}
s = m.section(form.NamedSection, 'config', 'wechatpush', _(''));
s.tab('basic', _('Basic Settings'));
s.tab('content', _('Push Content'));
s.tab('ipset', _('Auto Ban'));
s.tab('crontab', _('Scheduled Push'));
s.tab('disturb', _('Do Not Disturb'));
s.addremove = false;
s.anonymous = true;
// 基本设置
o = s.taboption('basic', form.Flag, 'enable', _('Enabled'));
o = s.taboption('basic', cbiRichListValue, 'jsonpath', _('Push Mode'));
o.value('/usr/share/wechatpush/api/serverchan.json', _('WeChat serverchan'),
_('Using serverchan API, simple configuration, supports multiple push methods'));
o.value('/usr/share/wechatpush/api/qywx_mpnews.json', _('WeChat Work Image Message'),
_('Using WeChat Work application message, more complex configuration, and starting from June 20, 2022, additional configuration for trusted IP is required. Trusted IP cannot be shared. This channel is no longer recommended.'));
o.value('/usr/share/wechatpush/api/qywx_markdown.json', _('WeChat Work Markdown Version'),
_('WeChat Work application message in plain text format, no need to click the title to view the content, same as above'));
o.value('/usr/share/wechatpush/api/wxpusher.json', _('wxpusher'),
_('Another channel for WeChat push, the configuration is relatively simple, and only supports official accounts'));
o.value('/usr/share/wechatpush/api/pushplus.json', _('pushplus'),
_('Another channel for WeChat push, the configuration is relatively simple, and it supports multiple push methods'));
o.value('/usr/share/wechatpush/api/telegram.json', _('Telegram'),
_('Telegram Bot Push'));
o.value('/usr/share/wechatpush/api/diy.json', _('Custom Push'),
_('By modifying the JSON file, you can use a custom API'));
o = s.taboption('basic', form.Value, 'sckey', _('「wechatpush」sendkey'));
o.description = _('Get Instructions') + ' <a href="https://sct.ftqq.com/" target="_blank">' + _('Click here') + '</a>';
o.rmempty = false;
o.depends('jsonpath', '/usr/share/wechatpush/api/serverchan.json');
o = s.taboption('basic', form.Value, 'corpid', _('corpid'));
o.description = _('Get Instructions') + ' <a href="https://work.weixin.qq.com/api/doc/10013" target="_blank">' + _('Click here') + '</a>';
o.rmempty = false;
o.depends('jsonpath', '/usr/share/wechatpush/api/qywx_mpnews.json');
o.depends('jsonpath', '/usr/share/wechatpush/api/qywx_markdown.json');
o = s.taboption('basic', form.Value, 'userid', _('userid'));
o.rmempty = false;
o.description = _('Send to All App Users, enter @all');
o.depends('jsonpath', '/usr/share/wechatpush/api/qywx_mpnews.json');
o.depends('jsonpath', '/usr/share/wechatpush/api/qywx_markdown.json');
o = s.taboption('basic', form.Value, 'agentid', _('agentid'));
o.rmempty = false;
o.depends('jsonpath', '/usr/share/wechatpush/api/qywx_mpnews.json');
o.depends('jsonpath', '/usr/share/wechatpush/api/qywx_markdown.json');
o = s.taboption('basic', form.Value, 'corpsecret', _('Secret'));
o.rmempty = false;
o.depends('jsonpath', '/usr/share/wechatpush/api/qywx_mpnews.json');
o.depends('jsonpath', '/usr/share/wechatpush/api/qywx_markdown.json');
o = s.taboption('basic', form.Value, 'mediapath', _('Thumbnail Image File Path'))
o.rmempty = false;
o.default = '/usr/share/wechatpush/api/logo.jpg';
o.depends('jsonpath', '/usr/share/wechatpush/api/qywx_mpnews.json');
o.description = _('Supports JPG and PNG formats within 2MB <br> Optimal size: 900383 or 2.35:1');
o = s.taboption('basic', form.Value, 'wxpusher_apptoken', _('appToken'));
o.description = _('Get Instructions') + ' <a href="https://wxpusher.zjiecode.com/docs/#/?id=%e5%bf%ab%e9%80%9f%e6%8e%a5%e5%85%a5" target="_blank">' + _('Click here') + '</a>';
o.rmempty = false;
o.depends('jsonpath', '/usr/share/wechatpush/api/wxpusher.json');
o = s.taboption('basic', form.Value, 'wxpusher_uids', _('uids'));
o.rmempty = false;
o.depends('jsonpath', '/usr/share/wechatpush/api/wxpusher.json');
o = s.taboption('basic', form.Value, 'wxpusher_topicIds', _('topicIds(Mass sending)'));
o.description = _('Get Instructions') + ' <a href="https://wxpusher.zjiecode.com/docs/#/?id=%e5%8f%91%e9%80%81%e6%b6%88%e6%81%af-1" target="_blank">' + _('Click here') + '</a>';
o.rmempty = false;
o.depends('jsonpath', '/usr/share/wechatpush/api/wxpusher.json');
o = s.taboption('basic', form.Value, 'pushplus_token', _('pushplus_token'));
o.description = _('Get Instructions') + ' <a href="http://www.pushplus.plus/" target="_blank">' + _('Click here') + '</a>';
o.rmempty = false;
o.depends('jsonpath', '/usr/share/wechatpush/api/pushplus.json');
o = s.taboption('basic', form.Value, 'tg_token', _('TG_token'));
o.description = _('Get Bot') + ' <a href="https://t.me/BotFather" target="_blank">' + _('Click here') + '</a>' + _('<br />Send a message to the created bot to initiate a conversation.');
o.rmempty = false;
o.depends('jsonpath', '/usr/share/wechatpush/api/telegram.json');
o = s.taboption('basic', form.Value, 'chat_id', _('TG_chatid'));
o.description = _('Get chat_id') + ' <a href="https://t.me/getuserIDbot" target="_blank">' + _('Click here') + '</a>' + _('<br />If you want to send to a group/channel, please create a non-Chinese group/channel (for easier chatid lookup, you can rename it later).<br />Add the bot to the group, send a message, and use https://api.telegram.org/bot token /getUpdates to obtain the chatid.');
o.rmempty = false;
o.depends('jsonpath', '/usr/share/wechatpush/api/telegram.json');
o = s.taboption('basic', form.TextValue, 'diy_json', _('Custom Push'));
o.rows = 28;
o.wrap = 'oft';
o.cfgvalue = function (section_id) {
return fs.trimmed('/usr/share/wechatpush/api/diy.json');
};
o.write = function (section_id, formvalue) {
return this.cfgvalue(section_id).then(function (value) {
if (value == formvalue) {
return
}
return fs.write('/usr/share/wechatpush/api/diy.json', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
});
};
o.description = _('Please refer to the comments and other interface files for modifications. Limited resources, no longer supporting more interfaces, please debug on your own.<br />You can use a similar website to check the JSON file format: https://www.google.com/search?q=JSON+Parser+Online<br />Please use the 「Save」 button in the text box.');
o.depends('jsonpath', '/usr/share/wechatpush/api/diy.json');
o = s.taboption('basic', form.Button, '_test', _('Send Test'), _('You may need to save the configuration before sending.'));
o.inputstyle = 'add';
o.onclick = function () {
var _this = this;
return fs.exec(programPath, ['test']).then(function (res) {
if (res.code === 0)
_this.description = _('Message sent successfully. If you don\'t receive the message, please check the logs for manual processing.');
else if (res.code === 1)
_this.description = _('Sending failed');
return _this.map.reset();
}).catch(function (err) {
ui.addNotification(null, E('p', [_('Unknown error: %s.').format(err)]));
_this.description = _('Sending failed');
return _this.map.reset();
});
}
o = s.taboption('basic', form.Value, 'device_name', _('Device Name'));
o.description = _('The device name will be displayed in the push message title to identify the source device of the message.');
o = s.taboption('basic', form.Value, 'sleeptime', _('Check Interval (s)'));
o.rmempty = false;
o.placeholder = '60';
o.datatype = 'and(uinteger,min(10))';
o.description = _('Shorter intervals provide quicker response but consume more system resources.');
o = s.taboption('basic', cbiRichListValue, 'oui_data', _('MAC Device Database'));
o.value('', _('Close'),
_('Do not use MAC device database'));
o.value('1', _('Simplified Version'),
_('Includes common device manufacturers, occupies approximately 200Kb of space'));
o.value('2', _('Full Version'),
_('Download the complete database, processed size is approximately 1.3Mb'));
o.value('3', _('Network Query'),
_('Enables network query, slower response. Only use if space is limited.'));
o = s.taboption('basic', form.Button, '_update_oui', _('Update MAC Device Database'));
o.inputstyle = 'add';
o.onclick = function () {
var _this = this;
return fs.exec('/usr/libexec/wechatpush-call', ['down_oui']).then(function (res) {
if (res.code === 2) {
_this.description = _('Database is up to date, skipping update');
}
return _this.map.reset();
}).catch(function (err) {
ui.addNotification(null, E('p', [_('Unknown error: %s.').format(err)]));
_this.description = _('Browser timeout or unknown error. If the log shows that the update process has been established, please ignore this error: %s.');
return _this.map.reset();
});
};
o.depends('oui_data', '1');
o.depends('oui_data', '2');
o = s.taboption('basic', form.Flag, 'reset_regularly', _('Reset Traffic Data Every Day at Midnight'));
o = s.taboption('basic', form.Flag, 'debuglevel', _('Enable Logging'));
o = s.taboption('basic', form.TextValue, '_device_aliases', _('Device Alias'));
o.rows = 20;
o.wrap = 'oft';
o.cfgvalue = function (section_id) {
return fs.trimmed('/usr/share/wechatpush/api/device_aliases.list');
};
o.write = function (section_id, formvalue) {
return this.cfgvalue(section_id).then(function (value) {
if (value == formvalue) {
return
}
return fs.write('/usr/share/wechatpush/api/device_aliases.list', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
});
};
o.description = _('Please enter the device MAC and device alias separated by a space, such as:<br/> XX:XX:XX:XX:XX:XX My Phone<br/> 192.168.1.2 My PC<br />Please use the 「Save」 button in the text box.');
// 推送内容
o = s.taboption('content', cbiRichListValue, 'get_ipv4_mode', _('IPv4 Dynamic Notification'));
o.value('', _('Close'),
_(' '));
o.value('1', _('Obtain through interface'),
_(' '));
o.value('2', _('Obtain through URL'),
_('May fail due to server stability and frequent connections.<br/>If the interface can obtain the IP address properly, it is not recommended to use this method.'));
o = s.taboption('content', widgets.DeviceSelect, 'ipv4_interface', _("Device"));
o.description = _('Typically, it should be WAN or br-lan interface. For multi-wan environments, please choose accordingly.');
o.modalonly = true;
o.multiple = false;
o.default = 'WAN';
o.depends('get_ipv4_mode', '1');
o = s.taboption('content', form.TextValue, 'ipv4_list', _('IPv4 API List'));
o.depends('get_ipv4_mode', '2');
o.optional = false;
o.rows = 8;
o.wrap = 'oft';
o.cfgvalue = function (section_id) {
return fs.trimmed('/usr/share/wechatpush/api/ipv4.list');
};
o.write = function (section_id, formvalue) {
return this.cfgvalue(section_id).then(function (value) {
if (value == formvalue) {
return
}
return fs.write('/usr/share/wechatpush/api/ipv4.list', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
});
};
o.description = _('Access a random address from the list above,URLs in the list are specific to Chinese websites. If you need to use this feature, please replace the URLs with the ones available to you.<br/>Please use the 「Save」 button in the text box.');
o = s.taboption('content', form.Button, '_update_ipv4_list', _('Update IPv4 list'));
o.inputstyle = 'add';
o.onclick = function () {
var _this = this;
return fs.exec('/usr/libexec/wechatpush-call', ['update_ip_list', 'ipv4']).then(function (res) {
if (res.code === 0)
_this.description = _('Update successful');
else if (res.code === 1)
_this.description = _('Update failed');
return _this.map.reset();
}).catch(function (err) {
ui.addNotification(null, E('p', [_('Unknown error: %s.').format(err)]));
_this.description = _('Update failed');
return _this.map.reset();
});
}
o.depends('get_ipv4_mode', '2');
o = s.taboption('content', cbiRichListValue, 'get_ipv6_mode', _('IPv6 Dynamic Notification'));
o.value('', _('Close'),
_(' '));
o.value('1', _('Obtain through interface'),
_(' '));
o.value('2', _('Obtain through URL'),
_('May fail due to server stability and frequent connections.<br/>If the interface can obtain the IP address properly, it is not recommended to use this method.'));
o = s.taboption('content', widgets.DeviceSelect, 'ipv6_interface', _("Device"));
o.description = _('Typically, it should be WAN or br-lan interface. For multi-wan environments, please choose accordingly.');
o.modalonly = true;
o.multiple = false;
o.default = 'WAN';
o.depends('get_ipv6_mode', '1');
o = s.taboption('content', form.TextValue, 'ipv6_list', _('IPv6 API List'));
o.depends('get_ipv6_mode', '2')
o.optional = false;
o.rows = 8;
o.wrap = 'oft';
o.cfgvalue = function (section_id) {
return fs.trimmed('/usr/share/wechatpush/api/ipv6.list');
};
o.write = function (section_id, formvalue) {
return this.cfgvalue(section_id).then(function (value) {
if (value == formvalue) {
return
}
return fs.write('/usr/share/wechatpush/api/ipv6.list', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
});
};
o.description = _('Access a random address from the list above,URLs in the list are specific to Chinese websites. If you need to use this feature, please replace the URLs with the ones available to you.<br/>Please use the 「Save」 button in the text box.');
o = s.taboption('content', form.Button, '_update_ipv6_list', _('Update IPv6 list'));
o.inputstyle = 'add';
o.onclick = function () {
var _this = this;
return fs.exec('/usr/libexec/wechatpush-call', ['update_ip_list', 'ipv6']).then(function (res) {
if (res.code === 0)
_this.description = _('Update successful');
else if (res.code === 1)
_this.description = _('Update failed');
return _this.map.reset();
}).catch(function (err) {
ui.addNotification(null, E('p', [_('Unknown error: %s.').format(err)]));
_this.description = _('Update failed');
return _this.map.reset();
});
}
o.depends('get_ipv6_mode', '2');
o = s.taboption('content', form.Flag, 'auto_update_ip_list', _('Automatically update API list'));
o.description = _('When multiple IP retrieval attempts fail, try to automatically update the list file from GitHub');
o.depends('get_ipv4_mode', '2');
o.depends('get_ipv6_mode', '2');
o = s.taboption('content', form.MultiValue, 'device_notification', _('Device Online/Offline Notification'));
o.value('online', _('Online Notification'));
o.value('offline', _('Offline Notification'));
o.modalonly = true;
o = s.taboption('content', form.MultiValue, 'cpu_notification', _('CPU Alert'));
o.value('load', _('Load Alert'));
o.value('temp', _('Temperature Alert'));
o.modalonly = true;
o.description = _('Device alert will be triggered only if it exceeds the set value continuously for five minutes, and there won\'t be a second reminder within an hour.');
o = s.taboption('content', form.Value, 'cpu_load_threshold', _('Load alert threshold'));
o.rmempty = false;
o.placeholder = '2';
o.depends({ cpu_notification: "load", '!contains': true });
o.validate = function (section_id, value) {
var floatValue = parseFloat(value);
if (!isNaN(floatValue) && floatValue.toString() === value) {
return true;
}
return 'Please enter a numeric value only';
};
o = s.taboption('content', form.Value, 'temperature_threshold', _('Temperature alert threshold'));
o.rmempty = false;
o.placeholder = '80';
o.datatype = 'and(uinteger,min(1))';
o.depends({ cpu_notification: "temp", '!contains': true });
o.description = _('Please confirm that the device can retrieve temperature. If you need to modify the command, please go to advanced settings.');
o = s.taboption('content', form.MultiValue, 'login_notification', _('Login Notification'));
o.value('web_logged', _('Web Login'));
o.value('ssh_logged', _('SSH Login'));
o.value('web_login_failed', _('Frequent Web Login Errors'));
o.value('ssh_login_failed', _('Frequent SSH Login Errors'));
o.modalonly = true;
o = s.taboption('content', form.Value, 'login_max_num', _('Login failure count'));
o.default = '3';
o.rmempty = false;
o.datatype = 'and(uinteger,min(1))';
o.depends({ login_notification: "web_login_failed", '!contains': true });
o.depends({ login_notification: "ssh_login_failed", '!contains': true });
o.description = _('Send notification after exceeding the count, and optionally auto-ban IP');
o = s.taboption('content', form.Flag, 'client_usage', _('Device abnormal traffic alert'));
o.description = _('Please ensure that you can retrieve device traffic information correctly, otherwise this feature will not work properly');
o.default = '0';
o = s.taboption('content', form.Value, 'client_usage_max', _('Per-minute traffic limit'));
o.placeholder = '10M';
o.rmempty = false;
o.depends('client_usage', '1');
o.description = _('Abnormal traffic alert (byte), you can append K or M');
o = s.taboption('content', form.Flag, 'client_usage_disturb', _('Abnormal traffic do not disturb'));
o.default = '0';
o.depends('client_usage', '1');
o = fwtool.addMACOption(s, 'content', 'client_usage_whitelist', _('Abnormal traffic monitoring list'),
_('Please select device MAC'), hosts);
o.rmempty = true;
o.datatype = 'list(neg(macaddr))';
o.depends('client_usage_disturb', '1');
// 自动封禁
o = s.taboption('ipset', form.Flag, 'login_web_black', _('Auto-ban unauthorized login devices'));
o.default = '0';
o.depends({ login_notification: "web_login_failed", '!contains': true });
o.depends({ login_notification: "ssh_login_failed", '!contains': true });
o = s.taboption('ipset', form.Value, 'login_ip_black_timeout', _('Blacklisting time (s)'));
o.default = '86400';
o.rmempty = false;
o.datatype = 'and(uinteger,min(0))';
o.depends('login_web_black', '1');
o.description = _('\"0\" in ipset means permanent blacklist, use with caution. If misconfigured, change the device IP and clear rules in LUCI.');
o = s.taboption('ipset', form.Flag, 'port_knocking_enable', _('Port knocking'));
o.default = '0';
o.description = _('If you have disabled LAN port inbound and forwarding in Firewall - Zone Settings, it won\'t work.');
o.depends({ login_notification: "web_login_failed", '!contains': true });
o.depends({ login_notification: "ssh_login_failed", '!contains': true });
o = s.taboption('ipset', form.Value, 'login_port_white', _('Port'));
o.default = '';
o.description = _('Open port after successful login<br/>example\"22\"、\"21:25\"、\"21:25,135:139\"');
o.depends('port_knocking_enable', '1');
o = s.taboption('ipset', form.DynamicList, 'login_port_forward_list', _('Port Forwards'));
o.default = '';
o.description = _('Example: Forward port 13389 of this device (IPv4:10.0.0.1 / IPv6:fe80::10:0:0:2) to port 3389 of (IPv4:10.0.0.2 / IPv6:fe80::10:0:0:8)<br/>\"10.0.0.1,13389,10.0.0.2,3389\"<br/>\"fe80::10:0:0:1,13389,fe80::10:0:0:2,3389\"');
o.depends('port_knocking_enable', '1');
o = s.taboption('ipset', form.Value, 'login_ip_white_timeout', _('Release time (s)'));
o.default = '86400';
o.datatype = 'and(uinteger,min(0))';
o.description = _('\"0\" in ipset means permanent release, use with caution');
o.depends('port_knocking_enable', '1');
o = s.taboption('ipset', form.TextValue, 'ip_black_list', _('IP blacklist'));
o.rows = 8;
o.wrap = 'soft';
o.cfgvalue = function (section_id) {
return fs.trimmed('/usr/share/wechatpush/api/ip_blacklist');
};
o.write = function (section_id, formvalue) {
return this.cfgvalue(section_id).then(function (value) {
if (value == formvalue) {
return
}
return fs.write('/usr/share/wechatpush/api/ip_blacklist', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
});
};
o.depends('login_web_black', '1');
o.description = _('You can add or delete here, the numbers after represent the remaining time. When adding, only the IP needs to be entered.<br/>When clearing, please leave a blank line, otherwise it cannot be saved ╮(╯_╰)╭<br/>Please use the 「Save」 button in the text box.');
// 定时推送
o = s.taboption('crontab', cbiRichListValue, 'crontab_mode', _('Scheduled Tasks'));
o.value('', _('Close'),
_(' '));
o.value('1', _('Scheduled sending'),
_('Send at the same time every day'));
o.value('2', _('Interval sending'),
_('Starting from 00:00, send every * hours'));
o = s.taboption('crontab', form.MultiValue, 'crontab_regular_time', _('Sending time'));
for (var t = 0; t <= 23; t++) {
o.value(t, _('Every day') + t + _('clock'));
}
o.modalonly = true;
o.depends("crontab_mode", "1");
o = s.taboption('crontab', form.ListValue, 'crontab_interval_time', _('Interval sending'));
o.default = "6"
for (var t = 0; t <= 12; t++) {
o.value(t, _("") + t + _("Hour"));
}
o.default = '';
o.datatype = "uinteger";
o.depends('crontab_mode', '2');
o.description = _('Starting from 00:00, send every * hours');
o = s.taboption('crontab', form.Value, 'send_title', _('Push title'));
o.depends('crontab_mode', '1');
o.depends('crontab_mode', '2');
o.placeholder = _('OpenWrt Router Status:');
o.description = _('Using special characters may cause sending failure');
o = s.taboption('crontab', form.MultiValue, 'send_notification', _('Push content'));
o.value('router_status', _('System running status'));
o.value('router_temp', _('Device temperature'));
o.value('wan_info', _('WAN info'));
o.value('client_list', _('Client list'));
o.modalonly = true;
o.depends('crontab_mode', '1');
o.depends('crontab_mode', '2');
o = s.taboption('crontab', form.Button, '_send', _('Manual sending'), _('You may need to save the configuration before sending.<br/>Due to browser timeout limitations, if the program is not running, it may exit due to timeout during device list initialization'));
o.inputstyle = 'add';
o.onclick = function () {
var _this = this;
return fs.exec(programPath, ['send']).then(function (res) {
if (res.code === 0)
_this.description = _('Message sent successfully. If you don\'t receive the message, please check the logs for manual processing.');
else if (res.code === 1)
_this.description = _('Sending failed');
return _this.map.reset();
}).catch(function (err) {
ui.addNotification(null, E('p', [_('Unknown error: %s.').format(err)]));
_this.description = _('Sending failed');
return _this.map.reset();
});
}
// 免打扰
o = s.taboption('disturb', form.MultiValue, 'lite_enable', _('Simplified mode'));
o.value('device', _('Simplify the current device list'));
o.value('nowtime', _('Simplify the current time'));
o.value('content', _('Push only the title'));
o = s.taboption('disturb', cbiRichListValue, 'do_not_disturb_mode', _('Do Not Disturb time setting'));
o.value('', _('Close'),
_(' '));
o.value('1', _('Mode 1: Script Suspension'),
_('Suspend all script actions, including unattended tasks, until the end of the time period'));
o.value('2', _('Mode 2: Silent Mode'),
_('Stop sending notifications, but log normally'));
o = s.taboption('disturb', form.ListValue, 'do_not_disturb_starttime', _('Do Not Disturb start time'));
for (var t = 0; t <= 23; t++) {
o.value(t, _('Every day') + t + _('clock'));
}
o.default = '0';
o.datatype = "uinteger"
o.depends('do_not_disturb_mode', '1');
o.depends('do_not_disturb_mode', '2');
o = s.taboption('disturb', form.ListValue, 'do_not_disturb_endtime', _('Do Not Disturb end time'));
for (var t = 0; t <= 23; t++) {
o.value(t, _('Every day') + t + _('clock'));
}
o.default = 8
o.datatype = "uinteger"
o.depends('do_not_disturb_mode', '1');
o.depends('do_not_disturb_mode', '2');
o = s.taboption('disturb', cbiRichListValue, 'mac_filtering_mode_1', _('MAC Filtering Mode 1'));
o.value('', _('Close'),
_(' '));
o.value('allow', _('Ignore devices in the list'),
_('Ignored devices will not receive notifications or be logged'));
o.value('block', _('Notify only devices in the list'),
_('Ignored devices will not receive notifications or be logged'));
o.value('interface', _('Notify only devices using this interface'),
_('Multiple selections are not supported at the moment'));
o = fwtool.addMACOption(s, 'disturb', 'up_down_push_whitelist', _('Ignored device list'),
_('Please select device MAC'), hosts);
o.datatype = 'list(neg(macaddr))';
o.depends('mac_filtering_mode_1', 'allow');
o = fwtool.addMACOption(s, 'disturb', 'up_down_push_blacklist', _('Followed device list'),
_('Please select device MAC'), hosts);
o.datatype = 'list(neg(macaddr))';
o.depends('mac_filtering_mode_1', 'block');
o.description = _('AA:AA:AA:AA:AA:AA\\|BB:BB:BB:BB:BB:BB Multiple MAC addresses can be treated as the same user.<br/>Notifications will not be sent once any device is online, and notifications will only be sent when all devices are offline to avoid frequent notifications in dual Wi-Fi scenarios.'); // 有点问题,待修复
o = s.taboption('disturb', widgets.DeviceSelect, 'up_down_push_interface', _("Device"));
o.description = _('Notify only devices using this interface');
o.modalonly = true;
o.multiple = false;
o.depends('mac_filtering_mode_1', 'interface');
o = s.taboption('disturb', cbiRichListValue, 'mac_filtering_mode_2', _('MAC Filtering Mode 2'));
o.value('', _('Close'),
_(' '));
o.value('mac_online', _('Do Not Disturb when devices are online'),
_('No notifications will be sent when any device in the list is online'));
o.value('mac_offline', _('Do Not Disturb when devices are offline'),
_('No notifications will be sent when any device in the list is offline'));
o = fwtool.addMACOption(s, 'disturb', 'mac_online_list', _('Do Not Disturb device online list'),
_('Please select device MAC'), hosts);
o.datatype = 'list(neg(macaddr))';
o.depends('mac_filtering_mode_2', 'mac_online');
o = fwtool.addMACOption(s, 'disturb', 'mac_offline_list', _('Do Not Disturb device offline list'),
_('Please select device MAC'), hosts);
o.datatype = 'list(neg(macaddr))';
o.depends('mac_filtering_mode_2', 'mac_offline');
o = s.taboption('disturb', cbiRichListValue, 'login_disturb', _('Do Not Disturb for Login Reminders'));
o.value('', _('Close'),
_(' '));
o.value('1', _('Only record in the log'),
_('Ignore all login reminders and only record in the log'));
o.value('2', _('Send notification only on the first login'),
_('Send notification only once within the specified time interval'));
o = s.taboption('disturb', form.Value, 'login_notification_delay', _('Login reminder do not disturb time (s)'));
o.rmempty = false;
o.placeholder = '3600';
o.datatype = 'and(uinteger,min(10))';
o.description = _('Send notification after the first login and do not repeat within the specified time<br/>Take a shortcut and read the login time from the log');
o.depends('login_disturb', '2');
o = fwtool.addIPOption(s, 'disturb', 'login_ip_white_list', _('Login reminder whitelist'), null, 'ipv4', hosts, true);
o.datatype = 'ipaddr';
o.depends({ login_notification: "web_logged", '!contains': true });
o.depends({ login_notification: "ssh_logged", '!contains': true });
o.depends({ login_notification: "web_login_failed", '!contains': true });
o.depends({ login_notification: "ssh_login_failed", '!contains': true });
o.description = _('Add the IP addresses in the list to the whitelist for the blocking function (if available), and ignore automatic blocking and login event notifications. Only record in the log. Mask notation is currently not supported.');
o = s.taboption('disturb', form.Flag, 'login_log_enable', _('Login reminder log anti-flooding'));
o.description = _('Users in the whitelist or during the undisturbed time period after their first login IP will be exempt from log recording, preventing log flooding.');
o.depends('login_disturb', '1');
o.depends('login_disturb', '2');
return m.render();
}
});

View File

@ -0,0 +1,133 @@
'use strict';
'require dom';
'require fs';
'require poll';
'require uci';
'require view';
'require form';
return view.extend({
render: function () {
var css = `
#log_textarea {
margin-top: 10px;
}
#log_textarea pre {
background-color: #f7f7f7;
color: #333;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
font-family: Consolas, Menlo, Monaco, monospace;
font-size: 14px;
line-height: 1.5;
white-space: pre-wrap;
word-wrap: break-word;
overflow-y: auto;
max-height: 400px;
}
#.description {
background-color: #33ccff;
}
.cbi-button-danger {
background-color: #fff;
color: #f00;
border: 1px solid #f00;
border-radius: 4px;
padding: 4px 8px;
font-size: 14px;
cursor: pointer;
margin-top: 10px;
}
.cbi-button-danger:hover {
background-color: #f00;
color: #fff;
}
.cbi-section small {
margin-left: 10px;
}
.cbi-section .cbi-section-actions {
margin-top: 10px;
}
.cbi-section .cbi-section-actions-right {
text-align: right;
}
`;
var log_textarea = E('div', { 'id': 'log_textarea' },
E('img', {
'src': L.resource(['icons/loading.gif']),
'alt': _('Loading...'),
'style': 'vertical-align:middle'
}, _('Collecting data ...'))
);
var log_path = '/tmp/wechatpush/wechatpush.log';
var clear_log_button = E('div', {}, [
E('button', {
'class': 'cbi-button cbi-button-danger',
'click': function (ev) {
ev.preventDefault();
var button = ev.target;
button.disabled = true;
button.textContent = _('Clear Logs...');
fs.exec_direct('/usr/libexec/wechatpush-call', ['clear_log'])
.then(function () {
button.textContent = _('Logs cleared successfully!');
setTimeout(function () {
button.disabled = false;
button.textContent = _('Clear Logs');
}, 5000);
// 立即刷新日志显示框
var log = E('pre', { 'wrap': 'pre' }, [_('Log is clean.')]);
dom.content(log_textarea, log);
})
.catch(function () {
button.textContent = _('Failed to clear log.');
setTimeout(function () {
button.disabled = false;
button.textContent = _('Clear Logs');
}, 5000);
});
}
}, _('Clear Logs'))
]);
poll.add(L.bind(function () {
return fs.read_direct(log_path, 'text')
.then(function (res) {
var log = E('pre', { 'wrap': 'pre' }, [res.trim() || _('Log is clean.')]);
dom.content(log_textarea, log);
log.scrollTop = log.scrollHeight;
}).catch(function (err) {
var log;
if (err.toString().includes('NotFoundError')) {
log = E('pre', { 'wrap': 'pre' }, [_('Log file does not exist.')]);
} else {
log = E('pre', { 'wrap': 'pre' }, [_('Unknown error: %s').format(err)]);
}
dom.content(log_textarea, log);
});
}));
return E('div', { 'class': 'cbi-map' }, [
E('style', [css]),
E('div', { 'class': 'cbi-section' }, [
clear_log_button,
log_textarea,
E('small', {}, _('Refresh every 5 seconds.').format(L.env.pollinterval)),
E('div', { 'class': 'cbi-section-actions cbi-section-actions-right' })
])
]);
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});

View File

@ -0,0 +1 @@
zh_Hans

View File

@ -0,0 +1,976 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2023-06-01 20:00+0000\n"
"Last-Translator: https://github.com/tty228/luci-app-wechatpush \n"
"Language-Team: \n"
"Language: zh_Hans\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Weblate 4.18-dev\n"
#: applications/luci-app-wechatpush/root/usr/share/luci/menu.d/luci-app-wechatpush.json:3
msgid "WeChat push"
msgstr "微信推送"
#: applications/luci-app-wechatpush/root/usr/share/luci/menu.d/luci-app-wechatpush.json:15
msgid "Basic Settings"
msgstr "基本设置"
#: applications/luci-app-wechatpush/root/usr/share/luci/menu.d/luci-app-wechatpush.json:24
msgid "Advance Setting"
msgstr "高级设置"
#: applications/luci-app-wechatpush/root/usr/share/luci/menu.d/luci-app-wechatpush.json:33
msgid "Online Devices"
msgstr "在线设备"
#: applications/luci-app-wechatpush/root/usr/share/luci/menu.d/luci-app-wechatpush.json:33
msgid "Log"
msgstr "日志"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:101
msgid "A tool that can push device messages from OpenWrt to a mobile phone via WeChat or Telegram.<br /><br />If you encounter any issues while using it, please submit them here:"
msgstr "一个通过微信或 Telegram从 OpenWrt 上推送设备消息到手机的工具<br /><br />如果你在使用中遇到问题,请到这里提交:"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:101
msgid "GitHub Project Address"
msgstr "GitHub 项目地址"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:124
msgid "Push Content"
msgstr "推送内容"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:125
msgid "Auto Ban"
msgstr "自动封禁"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:126
msgid "Scheduled Push"
msgstr "定时推送"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:127
msgid "Do Not Disturb"
msgstr "免打扰"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:134
msgid "Push Mode"
msgstr "推送模式"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:135
msgid "WeChat serverchan"
msgstr "微信 Server 酱"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:136
msgid "Using serverchan API, simple configuration, supports multiple push methods"
msgstr "使用 Server酱 接口,配置较简单,支持多项推送方式"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:137
msgid "WeChat Work Image Message"
msgstr "企业微信 图文消息"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:138
msgid "Using WeChat Work application message, more complex configuration, and starting from June 20, 2022, additional configuration for trusted IP is required. Trusted IP cannot be shared. This channel is no longer recommended."
msgstr "使用 企业微信应用消息,配置较为麻烦,且 2022 年 6 月 20 日之后新创建的应用,需要额外配置可信 IP可信 IP 不可公用,不再推荐此通道"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:139
msgid "WeChat Work Markdown Version"
msgstr "企业微信 markdown 版"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:140
msgid "WeChat Work application message in plain text format, no need to click the title to view the content, same as above"
msgstr "企业微信应用消息 纯文字版,无需点击标题查看内容,其他同上"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:142
msgid "Another channel for WeChat push, the configuration is relatively simple, and only supports official accounts"
msgstr "微信推送的另一个通道,配置较简单,只支持公众号"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:144
msgid "Another channel for WeChat push, the configuration is relatively simple, and it supports multiple push methods"
msgstr "微信推送的另一个通道,配置较简单,支持多项推送方式"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:146
msgid "Telegram Bot Push"
msgstr "Telegram bot 推送,若无梯子,请勿使用"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:147
msgid "Custom Push"
msgstr "自定义推送"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:148
msgid "By modifying the JSON file, you can use a custom API"
msgstr "通过修改 JSON 文件,使用自定义接口"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:150
msgid "「wechatpush」sendkey"
msgstr "「Server酱」sendkey"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:151
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:156
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:184
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:193
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:198
msgid "Get Instructions"
msgstr "获取说明"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:151
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:156
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:184
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:193
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:198
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:203
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:208
msgid "Click here"
msgstr "点击这里"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:155
msgid "corpid"
msgstr "企业ID(corpid)"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:161
msgid "userid"
msgstr "帐号(userid)"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:163
msgid "Send to All App Users, enter @all"
msgstr "群发到应用请填入 @all"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:167
msgid "agentid"
msgstr "应用id(agentid)"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:172
msgid "Secret"
msgstr "应用密钥(Secret)"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:177
msgid "Thumbnail Image File Path"
msgstr "图片缩略图文件路径"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:181
msgid "Supports JPG and PNG formats within 2MB <br> Optimal size: 900383 or 2.35:1"
msgstr "只支持 2MB 以内 JPG、PNG 格式<br>最佳尺寸900383 或 2.35:1"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:192
msgid "topicIds(Mass sending)"
msgstr "topicIds(群发)"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:203
msgid "Get Bot"
msgstr "获取机器人"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:203
msgid "<br />Send a message to the created bot to initiate a conversation."
msgstr "<br />与创建的机器人发一条消息,开启对话"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:208
msgid "Get chat_id"
msgstr "获取 chat_id"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:208
msgid "<br />If you want to send to a group/channel, please create a non-Chinese group/channel (for easier chatid lookup, you can rename it later).<br />Add the bot to the group, send a message, and use https://api.telegram.org/bot token /getUpdates to obtain the chatid."
msgstr "<br />如需通过群组/频道推送,请创建一个非中文的群组或频道(便于查找 chatid后续再更名<br />将机器人添加至群组,发送信息后通过 https://api.telegram.org/bot token /getUpdates 获取 chatid"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:226
msgid "Please refer to the comments and other interface files for modifications. Limited resources, no longer supporting more interfaces, please debug on your own.<br />You can use a similar website to check the JSON file format: https://www.google.com/search?q=JSON+Parser+Online<br />Please use the 「Save」 button in the text box."
msgstr "请参照注释和其他接口文件修改,精力有限,不再支持更多接口,自行调试<br />请参考类似网站检查 JSON 文件格式https://www.baidu.com/s?wd=json在线解析<br />文本框请使用「保存」按钮"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:230
msgid "Send Test"
msgstr "发送测试"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:230
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:67
msgid "You may need to save the configuration before sending."
msgstr "你可能需要先保存配置再进行发送"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:236
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:578
msgid "Message sent successfully. If you don't receive the message, please check the logs for manual processing."
msgstr "发送成功,如果收不到信息,请查看日志手动处理"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:238
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:243
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:579
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:584
msgid "Sending failed"
msgstr "发送失败"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:242
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:277
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:350
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:401
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:583
msgid "Unknown error: %s."
msgstr "未知错误:%s"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:249
msgid "The device name will be displayed in the push message title to identify the source device of the message."
msgstr "在推送信息标题中会标识本设备名称,用于区分推送信息的来源设备"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:251
msgid "Check Interval (s)"
msgstr "检测时间间隔(秒)"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:255
msgid "Shorter intervals provide quicker response but consume more system resources."
msgstr "越短的时间间隔响应越及时,但会占用更多的系统资源"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:257
msgid "MAC Device Database"
msgstr "MAC 设备数据库"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:259
msgid "Do not use MAC device database"
msgstr "不使用 MAC 设备数据库"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:260
msgid "Simplified Version"
msgstr "简化版"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:261
msgid "Includes common device manufacturers, occupies approximately 200Kb of space"
msgstr "仅包含常见设备厂商,约占用 200Kb 空间"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:262
msgid "Full Version"
msgstr "完整版"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:263
msgid "Download the complete database, processed size is approximately 1.3Mb"
msgstr "下载完整数据,处理后约占用 1.3Mb 空间"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:264
msgid "Network Query"
msgstr "网络查询"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:265
msgid "Enables network query, slower response. Only use if space is limited."
msgstr "网络查询,查询速度较慢且需要梯子,除非空间紧缺,否则请勿使用"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:267
msgid "Update MAC Device Database"
msgstr "更新 MAC 设备数据库"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:273
msgid "Database is up to date, skipping update"
msgstr "已是最新,跳过更新"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:278
msgid "Browser timeout or unknown error. If the log shows that the update process has been established, please ignore this error: %s."
msgstr "浏览器超时强制退出或未知错误,若日志显示已建立更新进程,请忽略此错误:%s"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:285
msgid "Reset Traffic Data Every Day at Midnight"
msgstr "每天零点重置流量数据"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:287
msgid "Enable Logging"
msgstr "开启日志"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:289
msgid "Device Alias"
msgstr "设备别名"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:303
msgid "Please enter the device MAC and device alias separated by a space, such as:<br/> XX:XX:XX:XX:XX:XX My Phone<br/> 192.168.1.2 My PC<br />Please use the 「Save」 button in the text box."
msgstr "请输入设备 MAC 和设备别名,用空格隔开,例如:<br/> XX:XX:XX:XX:XX:XX 我的手机<br/> 192.168.1.2 我的电脑<br />文本框请使用「保存」按钮"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:306
msgid "IPv4 Dynamic Notification"
msgstr "IPv4 变动通知"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:309
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:360
msgid "Obtain through interface"
msgstr "通过网络接口获取"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:311
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:362
msgid "Obtain through URL"
msgstr "通过 URL 获取"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:312
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:363
msgid "May fail due to server stability and frequent connections.<br/>If the interface can obtain the IP address properly, it is not recommended to use this method."
msgstr "会因服务器稳定性、连接频繁等原因导致获取失败。<br/>如接口可以正常获取 IP不推荐使用此方法。"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:337
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:388
msgid "Access a random address from the list above,URLs in the list are specific to Chinese websites. If you need to use this feature, please replace the URLs with the ones available to you.<br/>Please use the 「Save」 button in the text box."
msgstr "从以上列表中随机访问地址<br />文本框请使用「保存」按钮"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:315
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:366
msgid "Typically, it should be WAN or br-lan interface. For multi-wan environments, please choose accordingly."
msgstr "一般应为 WAN 或 br-lan 接口。多拨环境请自行选择。"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:321
msgid "IPv4 API List"
msgstr "IPv4 API 列表"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:339
msgid "Update IPv4 list"
msgstr "更新 IPv4 list"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:345
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:396
msgid "Update successful"
msgstr "更新成功"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:347
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:351
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:398
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:402
msgid "Update failed"
msgstr "更新失败"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:357
msgid "IPv6 Dynamic Notification"
msgstr "IPv6 变动通知"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:372
msgid "IPv6 API List"
msgstr "IPv6 API 列表"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:390
msgid "Update IPv6 list"
msgstr "更新 IPv6 list"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:408
msgid "Automatically update API list"
msgstr "API 列表自动更新"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:409
msgid "When multiple IP retrieval attempts fail, try to automatically update the list file from GitHub"
msgstr "当多次获取 IP 失败时,尝试自动从 GitHub 上更新列表文件<br/>因为懒得做外链,所以请确保你可以链接 raw.githubusercontent.com"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:413
msgid "Device Online/Offline Notification"
msgstr "设备上下线通知"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:414
msgid "Online Notification"
msgstr "上线通知"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:415
msgid "Offline Notification"
msgstr "下线通知"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:418
msgid "CPU Alert"
msgstr "CPU 报警"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:419
msgid "Load Alert"
msgstr "负载报警"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:420
msgid "Temperature Alert"
msgstr "温度报警"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:422
msgid "Device alert will be triggered only if it exceeds the set value continuously for five minutes, and there won't be a second reminder within an hour."
msgstr "设备报警只会在连续五分钟超过设定值时才会推送,一个小时内不会再提醒第二次。"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:424
msgid "Load alert threshold"
msgstr "负载报警阈值"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:433
msgid "Please enter a numeric value only"
msgstr "请输入纯数字"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:436
msgid "Temperature alert threshold"
msgstr "温度报警阈值"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:441
msgid "Please confirm that the device can retrieve temperature. If you need to modify the command, please go to advanced settings."
msgstr "请确认设备可以获取温度。如果需修改命令,请移步高级设置。"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:443
msgid "Login Notification"
msgstr "登录提醒"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:444
msgid "Web Login"
msgstr "Web 登录"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:445
msgid "SSH Login"
msgstr "SSH 登录"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:446
msgid "Frequent Web Login Errors"
msgstr "Web 频繁错误登录"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:447
msgid "Frequent SSH Login Errors"
msgstr "SSH 频繁错误登录"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:450
msgid "Login failure count"
msgstr "登录失败次数"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:456
msgid "Send notification after exceeding the count, and optionally auto-ban IP"
msgstr "超过次数后推送提醒,并可选自动封禁 IP"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:458
msgid "Device abnormal traffic alert"
msgstr "设备异常流量警报"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:459
msgid "Please ensure that you can retrieve device traffic information correctly, otherwise this feature will not work properly"
msgstr "请确保可以正确获取设备流量情况,否则此功能无法正常工作"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:462
msgid "Per-minute traffic limit"
msgstr "每分钟流量限制"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:466
msgid "Abnormal traffic alert (byte), you can append K or M"
msgstr "设备异常流量警报byte你可以追加 K 或者 M"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:468
msgid "Abnormal traffic do not disturb"
msgstr "异常流量免打扰"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:472
msgid "Abnormal traffic monitoring list"
msgstr "异常流量关注列表"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:473
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:633
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:639
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:659
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:664
msgid "Please select device MAC"
msgstr "请选择设备 MAC"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:479
msgid "Auto-ban unauthorized login devices"
msgstr "自动封禁非法登录设备"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:484
msgid "Blacklisting time (s)"
msgstr "拉黑时间(秒)"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:489
msgid "\"0\" in ipset means permanent blacklist, use with caution. If misconfigured, change the device IP and clear rules in LUCI."
msgstr "ipset 中, \"0\" 为永久拉黑,慎用。如不幸误操作,请更改设备 IP 进入 LUCI 界面清空规则"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:491
msgid "Port knocking"
msgstr "端口敲门"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:497
msgid "Port"
msgstr "端口"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:499
msgid "Open port after successful login<br/>example\"22\"、\"21:25\"、\"21:25,135:139\""
msgstr "登录成功后开放端口<br/>例:\"22\"、\"21:25\"、\"21:25,135:139\""
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:494
msgid "If you have disabled LAN port inbound and forwarding in Firewall - Zone Settings, it won't work."
msgstr "如在 防火墙 - 区域设置 中禁用了 LAN 口入站和转发,该功能将不起作用"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:505
msgid "Example: Forward port 13389 of this device (IPv4:10.0.0.1 / IPv6:fe80::10:0:0:2) to port 3389 of (IPv4:10.0.0.2 / IPv6:fe80::10:0:0:8)<br/>\"10.0.0.1,13389,10.0.0.2,3389\"<br/>\"fe80::10:0:0:1,13389,fe80::10:0:0:2,3389\""
msgstr "例:将本机 (IPv4:10.0.0.1 / IPv6:fe80::10:0:0:2) 的 13389 端口转发到 (IPv4:10.0.0.2 / IPv6:fe80::10:0:0:8) 的 3389 端口:<br/>\"10.0.0.1,13389,10.0.0.2,3389\"<br/>\"fe80::10:0:0:2,13389,fe80::10:0:0:8,3389\""
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:508
msgid "Release time (s)"
msgstr "放行时间(秒)"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:494
msgid "\"0\" in ipset means permanent release, use with caution"
msgstr "ipset 中, \"0\" 为永久放行,慎用"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:514
msgid "IP blacklist"
msgstr "IP 黑名单列表"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:529
msgid "You can add or delete here, the numbers after represent the remaining time. When adding, only the IP needs to be entered.<br/>When clearing, please leave a blank line, otherwise it cannot be saved ╮(╯_╰)╭<br/>Please use the 「Save」 button in the text box."
msgstr "可在此处添加或删除,后面的数字为剩余时间,添加时只需要输入 IP<br/>清空时请保留一个回车,否则无法保存 ╮(╯_╰)╭<br/>文本框请使用「保存」按钮"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:535
msgid "Scheduled sending"
msgstr "定时发送"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:536
msgid "Send at the same time every day"
msgstr "每天固定时间发送"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:537
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:547
msgid "Interval sending"
msgstr "间隔发送"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:538
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:555
msgid "Starting from 00:00, send every * hours"
msgstr "从 00:00 开始,每 * 小时发送一次"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:540
msgid "Sending time"
msgstr "发送时间"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:542
msgid "Every day"
msgstr "每天"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:542
msgid "clock"
msgstr "点"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:557
msgid "Push title"
msgstr "推送标题"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:560
msgid "OpenWrt Router Status:"
msgstr "OpenWrt 路由状态:"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:561
msgid "Using special characters may cause sending failure"
msgstr "使用特殊符号可能会造成发送失败"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:563
msgid "Push content"
msgstr "推送内容"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:564
msgid "System running status"
msgstr "系统运行情况"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:565
msgid "Device temperature"
msgstr "设备温度"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:566
msgid "WAN info"
msgstr "WAN 信息"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:567
msgid "Client list"
msgstr "客户端列表"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:572
msgid "Manual sending"
msgstr "手动发送"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:572
msgid "You may need to save the configuration before sending.<br/>Due to browser timeout limitations, if the program is not running, it may exit due to timeout during device list initialization"
msgstr "你可能需要先保存配置再进行发送<br/>由于浏览器超时限制,若程序未在运行,可能会因初始化设备列表超时退出"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:591
msgid "Simplified mode"
msgstr "精简模式"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:592
msgid "Simplify the current device list"
msgstr "精简当前设备列表"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:593
msgid "Simplify the current time"
msgstr "精简当前时间"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:594
msgid "Push only the title"
msgstr "只推送标题"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:596
msgid "Do Not Disturb time setting"
msgstr "免打扰时段设置"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:599
msgid "Mode 1: Script Suspension"
msgstr "模式一:脚本挂起"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:600
msgid "Suspend all script actions, including unattended tasks, until the end of the time period"
msgstr "暂停脚本任何动作,包括无人值守任务,直到时段结束"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:601
msgid "Mode 2: Silent Mode"
msgstr "模式二:静默模式"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:602
msgid "Stop sending notifications, but log normally"
msgstr "停止信息推送,但正常记录日志"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:604
msgid "Do Not Disturb start time"
msgstr "免打扰开始时间"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:613
msgid "Do Not Disturb end time"
msgstr "免打扰结束时间"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:622
msgid "MAC Filtering Mode 1"
msgstr "MAC 过滤模式一"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:625
msgid "Ignore devices in the list"
msgstr "忽略列表内设备"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:626
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:628
msgid "Ignored devices will not receive notifications or be logged"
msgstr "被忽略设备不做推送和日志记录"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:627
msgid "Notify only devices in the list"
msgstr "仅通知列表内设备"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:629
msgid "Notify only devices using this interface"
msgstr "仅通知此接口设备"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:630
msgid "Multiple selections are not supported at the moment"
msgstr "暂不支持多选"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:632
msgid "Ignored device list"
msgstr "忽略设备列表"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:637
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:148
msgid "Followed device list"
msgstr "关注设备列表"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:641
msgid "AA:AA:AA:AA:AA:AA\\|BB:BB:BB:BB:BB:BB Multiple MAC addresses can be treated as the same user.<br/>Notifications will not be sent once any device is online, and notifications will only be sent when all devices are offline to avoid frequent notifications in dual Wi-Fi scenarios."
msgstr "AA:AA:AA:AA:AA:AA\\|BB:BB:BB:BB:BB:BB 可以将多个 MAC 视为同一用户<br/>任一设备在线后不再推送,设备全部离线时才会推送,避免双 wifi 频繁推送"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:644
msgid "Notify only devices using this interface"
msgstr "仅通知此接口设备"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:649
msgid "MAC Filtering Mode 2"
msgstr "MAC 过滤模式二"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:652
msgid "Do Not Disturb when devices are online"
msgstr "设备在线时免打扰"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:653
msgid "No notifications will be sent when any device in the list is online"
msgstr "当列表内任意设备在线时,不推送信息"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:654
msgid "Do Not Disturb when devices are offline"
msgstr "设备离线后免打扰"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:655
msgid "No notifications will be sent when any device in the list is offline"
msgstr "当列表内任意设备离线后,不推送信息"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:657
msgid "Do Not Disturb device online list"
msgstr "设备在线免打扰列表"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:662
msgid "Do Not Disturb device offline list"
msgstr "设备离线免打扰列表"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:667
msgid "Do Not Disturb for Login Reminders"
msgstr "登录提醒免打扰"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:670
msgid "Only record in the log"
msgstr "仅记录到日志"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:671
msgid "Ignore all login reminders and only record in the log"
msgstr "忽略所有登录提醒,仅记录到日志"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:672
msgid "Send notification only on the first login"
msgstr "仅在首次登录时推送通知"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:673
msgid "Send notification only once within the specified time interval"
msgstr "在设定时间间隔内,仅首次发送推送通知"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:675
msgid "Login reminder do not disturb time (s)"
msgstr "登录提醒免打扰时间(秒)"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:679
msgid "Send notification after the first login and do not repeat within the specified time<br/>Take a shortcut and read the login time from the log"
msgstr "首次登录后推送通知,在设定时间内不再重复提醒<br/>偷懒一下,登录时间从日志中读取,请确保开启日志功能"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:682
msgid "Login reminder whitelist"
msgstr "登录提醒白名单"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:689
msgid "Login reminder log anti-flooding"
msgstr "登录提醒日志免刷屏"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:690
msgid "Users in the whitelist or during the undisturbed time period after their first login IP will be exempt from log recording, preventing log flooding."
msgstr "白名单列表内的用户,或者登录 IP 处于首次登录后的免打扰时段,不做日志记录,避免日志刷屏"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:688
msgid "Add the IP addresses in the list to the whitelist for the blocking function (if available), and ignore automatic blocking and login event notifications. Only record in the log. Mask notation is currently not supported."
msgstr "列表内 IP 加入封禁功能白名单(如果可用),并忽略自动封禁和登录事件推送,仅在日志中记录,暂不支持掩码位表示"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:17
msgid "If you are not familiar with the meanings of these options, please do not modify them.<br/><br/>"
msgstr "如果你不了解这些选项的含义,请不要修改这些选项<br/><br/>"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:19
msgid "Advanced Settings"
msgstr "高级设置"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:23
msgid "Device online detection timeout (s)"
msgstr "设备上线检测超时(秒)"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:28
msgid "Device offline detection timeout (s)"
msgstr "设备离线检测超时(秒)"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:33
msgid "Offline detection count"
msgstr "离线检测次数"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:37
msgid "If the device has good signal strength and no Wi-Fi sleep issues, you can reduce the above values.<br/>Due to the mysterious nature of Wi-Fi sleep during the night, if you encounter frequent disconnections, please adjust the parameters accordingly.<br/>..╮(╯_╰╭.."
msgstr "若设备信号强度良好,无息屏 WiFi 休眠问题,可以减少以上数值<br/>因夜间 WiFi 息屏休眠较为玄学,遇到设备频繁推送断开,烦请自行调整参数<br/>..╮(╯_╰╭.."
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:42
msgid "Offline timeout applies only to the devices that receive push notifications"
msgstr "离线超时只针对推送设备"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:45
msgid "When this option is selected, the offline timeout and offline detection count apply only to the devices that require push notifications. Other devices will use default values, which can significantly reduce the time required for detection. However, it may result in inaccurate online time displayed in the online devices list. It is recommended to enable this option only when there are many devices and frequent offline occurrences are observed for specific devices of interest."
msgstr "选中此项后,离线超时时间和离线检测次数只针对需要推送的设备,其余设备使用默认值,可有效减少检测所需的时间,但会造成在线设备列表中的在线时间不准确,仅建议设备较多且关注的设备离线频繁时使用"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:47
msgid "Disable active detection"
msgstr "关闭主动探测"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:50
msgid "Disable active detection of client online status. Enabling this feature will no longer prompt device online/offline events.<br/>Suitable for users who are not sensitive to online devices but need other features."
msgstr "关闭客户端在线状态的主动探测,因误报较为严重,启用此功能后设备上下线将不再提示<br/>适用于对在线设备不敏感,但需要其他功能的用户"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:52
msgid "Maximum concurrent processes"
msgstr "最大并发进程数"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:56
msgid "Do not change the setting value for low-performance devices, or reduce the parameters as appropriate."
msgstr "低性能设备请勿更改设置值,或酌情减少参数"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:58
msgid "Custom temperature reading command"
msgstr "自定义温度读取命令"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:60
msgid "Default"
msgstr "默认"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:61
msgid "Proxmox Virtual Environment"
msgstr "PVE 虚拟机"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:62
msgid "If you need to use special symbols such as quotes, $, !, etc. in custom commands, you need to escape them yourself.<br/>You can use the command eval echo $(uci get wechatpush.wechatpush.soc_code) to view command output and error information.<br/>The execution result should be a pure number (including decimals) for temperature comparison.<br/>Here is an example that does not require escaping:<br/>cat /sys/class/thermal/thermal_zone0/temp|sort -nr|head -n1|cut -c-2"
msgstr "自定义命令如需使用特殊符号,如引号、$、!等,则需要自行转义<br/>可以使用 eval echo $(uci get wechatpush.wechatpush.soc_code) 命令查看命令输出及错误信息<br/>执行结果需为纯数字(可带小数),用于温度对比<br/>一个无需转义的例子:<br/>cat /sys/class/thermal/thermal_zone0/temp|sort -nr|head -n1|cut -c-2"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:64
msgid "Host machine address"
msgstr "宿主机地址"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:70
msgid "Host machine SSH port"
msgstr "宿主机 SSH 端口"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:73
msgid "The default SSH port is 22. If you have a custom port, please fill in the custom SSH port.<br/>Please make sure you have set up key-based login, otherwise it may cause script errors.<br/>Install the sensors command on PVE by searching on the internet.<br/>Example for key-based login (modify the address and port number accordingly):<br/>opkg update # Update package list<br/>opkg install openssh-client openssh-keygen # Install openssh client<br/>echo -e \"\\n\" | ssh-keygen -t rsa # Generate key file (no passphrase)<br/>pve_host=`uci get wechatpush.config.server_host` || pve_host=\"10.0.0.3\" # Read the PVE host address from the configuration file, If not saved, please fill in by yourself.<br/>pve_port=`uci get wechatpush.config.server_port` || pve_host=\"22\" # Read the PVE host SSH port number from the configuration file, If not saved, please fill in by yourself.<br/>ssh -o StrictHostKeyChecking=yes root@${pve_host} -p ${pve_port} \"tee -a ~/.ssh/OpenWrt_id_rsa.pub\" < ~/.ssh/id_rsa.pub # Transfer public key to PVE<br/>ssh root@${pve_host} -p ${pve_port} \"cat ~/.ssh/OpenWrt_id_rsa.pub >> ~/.ssh/authorized_keys\" # Write public key to PVE<br/>ssh -i /root/.ssh/id_rsa root@${pve_host} -p ${pve_port} sensors # To avoid script errors during the initial connection, please use a private key to connect to PVE and test the temperature command for its proper functioning.<br/>For users who frequently flash firmware, please add /root/.ssh/ to the backup list to avoid duplicate operations."
msgstr "SSH 端口默认为 22如有自定义请填写自定义 SSH 端口<br/>请确认已经设置好密钥登陆,否则会引起脚本无法运行等错误!<br/>PVE 安装 sensors 命令自行百度<br/>密钥登陆例(自行修改地址与端口号):<br/>opkg update #更新列表<br/>opkg install openssh-client openssh-keygen #安装openssh客户端<br/>echo -e \"\\n\" | ssh-keygen -t rsa # 生成密钥文件(空密码)<br/>pve_host=`uci get wechatpush.config.server_host` || pve_host=\"10.0.0.3\" # 读取配置文件中的 pve 主机地址,如果未保存设置,请自行填写 <br/>pve_port=`uci get wechatpush.config.server_port` || pve_host=\"22\" # 读取配置文件中的 pve 主机 ssh 端口号,如果未保存设置,请自行填写 <br/>ssh -o StrictHostKeyChecking=yes root@${pve_host} -p ${pve_port} \"tee -a ~/.ssh/OpenWrt_id_rsa.pub\" < ~/.ssh/id_rsa.pub # 传送公钥到 PVE<br/>ssh root@${pve_host} -p ${pve_port} \"cat ~/.ssh/OpenWrt_id_rsa.pub >> ~/.ssh/authorized_keys\" # 写入公钥到 PVE<br/>ssh -i /root/.ssh/id_rsa root@${pve_host} -p ${pve_port} sensors # 因首次连接时需要确认,为避免脚本错误,请使用私钥连接 PVE 并测试温度命令是否正常运行。<br/>刷机党自行将 /root/.ssh/ 加入备份列表,避免重复操作"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:76
msgid "Test temperature command"
msgstr "测试温度命令"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:82
msgid "Returned temperature value is empty"
msgstr "返回的温度值为空"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:87
msgid "Fetch failed"
msgstr "获取失败:"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:91
msgid "Assist in obtaining device information"
msgstr "辅助获取设备列表"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:92
msgid "Retrieve hostname list from modem"
msgstr "从光猫获取主机名等信息"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:93
msgid "Scan local IP"
msgstr "扫描局域网 IP"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:95
msgid "When OpenWrt is used as a bypass gateway and cannot obtain device hostnames or a complete list of local network devices.<br/>the \"Retrieve hostname list from modem\" option has only been tested with HG5143F/HN8145V China Telecom gateways and may not be universally applicable.<br/>The \"Scan local IP\" option may not retrieve hostnames, so please use device name annotations in conjunction with it."
msgstr "适用于 OpenWrt 作为旁路网关,无法获取设备主机名及完整的局域网设备列表时<br/>\"从光猫获取主机名列表\"选项仅测试通过 HG5143F/HN8145V 天翼网关,不保证通用性<br/>\"定期扫描局域网 IP\"选项可能无法获取主机名,请配合设备名备注使用"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:97
msgid "Optical modem login URL"
msgstr "光猫登录地址 URL"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:102
msgid "Device list JSON URL"
msgstr "设备列表 JSON URL"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:105
msgid "Use F12 console to capture<br/>ip, devName, model are mandatory fields. Example JSON file information:<br/>{\"pc1\":{\"devName\":\"RouterOS\",\"model\":\"\",\"type\":\"pc\",\"ip\":\"192.168.1.7\"}}"
msgstr "使用 F12 控制台自行抓取<br/>ip、devName、model 为必须项JSON 文件信息范例:<br/>{\"pc1\":{\"devName\":\"RouterOS\",\"model\":\"\",\"type\":\"pc\",\"ip\":\"192.168.1.7\"}}"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:108
msgid "Optical modem logout URL"
msgstr "光猫注销登录 URL"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:111
msgid "Not a mandatory field, but it may affect other users logging into the web management page, e.g., HG5143F"
msgstr "非必须项,但可能会影响其他用户登录 Web 管理页面,如 HG5143F"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:114
msgid "Login page account input box ID"
msgstr "登录页面帐号输入框 ID"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:119
msgid "Login page password input box ID"
msgstr "登录页面密码输入框 ID"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:122
msgid "Right-click in the browser and select 'Inspect Element'"
msgstr "浏览器右键-检查元素"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:125
msgid "Optical modem login account"
msgstr "光猫登录帐号"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:130
msgid "Optical modem login password"
msgstr "光猫登录密码"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:132
msgid "Use a regular account, no need for super password"
msgstr "使用普通账号即可,不需要超密"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:135
msgid "IP range to be scanned"
msgstr "需要扫描的 IP 段"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:140
msgid "Interval for capturing info"
msgstr "抓取信息时间间隔"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:144
msgid "Generally, frequent capturing is not necessary. Adjust it as needed."
msgstr "一般不需要频繁抓取,酌情设置"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:148
msgid "Unattended tasks"
msgstr "无人值守任务"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:151
msgid "Please make sure the script can run properly, otherwise it may cause frequent restarts and other errors!"
msgstr "请确认脚本可以正常运行,否则可能造成频繁重启等错误!"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:153
msgid "Restart zerotier after IP change"
msgstr "IP 变化后重启 zerotier"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:154
msgid "An old issue with zerotier<br/>Cannot reconnect after disconnection, emmm, I don't know if it has been fixed now."
msgstr "zerotier 的陈年老问题<br/>断网后不能重新打洞emmm我也不知道修了没有"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:157
msgid "Redial only during Do-Not-Disturb period"
msgstr "仅在免打扰时段重拨"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:160
msgid "Avoid redialing network during the day to prevent waiting for DDNS domain resolution. This feature does not affect disconnection detection.<br/>Due to the issue of certain apps consuming excessive data at night, this feature may be unstable."
msgstr "避免在白天重拨网络造成 DDNS 域名等待解析,此功能不影响断网检测<br/>因夜间某些 APP 偷跑流量问题,该功能可能不稳定"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:165
msgid "Will only be executed when none of the devices in the list are online.<br/>After an hour of Do-Not-Disturb period, if the devices in the focus list have low traffic (around 100kb/m) for five minutes, they will be considered offline."
msgstr "只会在列表中设备都不在线时才会执行<br/>免打扰时段一小时后关注设备五分钟低流量约100kb/m将视为离线"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:169
msgid "When the network is disconnected"
msgstr "网络断开时"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:171
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:179
msgid "No operation"
msgstr "无操作"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:172
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:180
msgid "Restart the router"
msgstr "重启路由器"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:173
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:181
msgid "Redialing network"
msgstr "重新拨号"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:174
msgid "The restart operation will occur ten minutes after the network disconnection and will be attempted a maximum of two times. If the option to log in to the optical modem is available, this operation will attempt to restart the optical modem.<br/>【!!This feature cannot guarantee compatibility!!】"
msgstr "重启操作将在网络断开十分钟后进行,且最多尝试两次。如果光猫登录选项可用,此操作将会尝试重启光猫。<br/>【!!此功能无法保证兼容性!!】"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:177
msgid "Scheduled reboot"
msgstr "定时重启"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:184
msgid "System uptime greater than"
msgstr "系统运行时间大于"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:188
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:195
msgid "Unit: hours"
msgstr "单位为小时"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/advanced.js:191
msgid "Network uptime greater than"
msgstr "网络在线时间大于"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/client.js:14
msgid "Online time"
msgstr "在线时间"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/log.js:75
msgid "Clear Logs..."
msgstr "清除日志..."
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/log.js:75
msgid "Logs cleared successfully!"
msgstr "日志清除成功!"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/log.js:81
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/log.js:91
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/log.js:95
msgid "Clear Logs"
msgstr "清除日志"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/log.js:124
msgid "Refresh every 5 seconds."
msgstr "每 5 秒刷新"

View File

@ -0,0 +1,9 @@
config wechatpush "config"
option enable '0'
option sleeptime '60'
option debuglevel '1'
option up_timeout '2'
option down_timeout '10'
option timeout_retry_count '2'
option thread_num '3'

View File

@ -0,0 +1,36 @@
#!/bin/sh /etc/rc.common
START=99
STOP=90
USE_PROCD=1
dir="/tmp/wechatpush/"
start_service() {
procd_open_instance
enable_value=$(uci get wechatpush.config.enable 2>/dev/null || echo "0")
[ "$enable_value" -ne "0" ] && procd_set_param command /usr/share/wechatpush/wechatpush && echo "wechatpush is starting now ..."
procd_close_instance
}
reload_service() {
stop
sleep 1
start
}
stop_service() {
[ -f ${dir}child_pid ] && parent_pid=$(cat ${dir}child_pid)
[ -n "$parent_pid" ] && {
child_pids=$(pgrep -P $parent_pid)
echo "Terminating child processes of wechatpush..."
for child_pid in $child_pids; do
kill $child_pid
done
}
echo "Terminating wechatpush process..."
}
service_triggers() {
procd_add_reload_trigger wechatpush
}

View File

@ -0,0 +1,179 @@
#!/bin/sh
function get_config_wechatpush(){
while [[ "$*" != "" ]]; do
eval ${1}='`uci get wechatpush.config.$1`' 2>/dev/null
uci del wechatpush.config.$1 2>/dev/null
uci commit wechatpush
shift
done
}
function get_config_serverchan(){
while [[ "$*" != "" ]]; do
eval ${1}='`uci get serverchan.serverchan.$1`' 2>/dev/null
uci del serverchan.serverchan.$1 2>/dev/null
uci commit serverchan 2>/dev/null
shift
done
}
function serverchan_to_wechatpush_list(){
[ $2 ] && config_name=$2 || config_name=$1
config_list=`uci get serverchan.serverchan.$1` 2>/dev/null
[ -z "$config_list" ] && return
uci del serverchan.serverchan.$1 2>/dev/null
uci commit serverchan 2>/dev/null
for config in $config_list ;do
uci add_list wechatpush.config.$config_name="$config"
done
uci commit wechatpush
}
function serverchan_to_wechatpush_change(){
config=`uci get serverchan.serverchan.$1` 2>/dev/null
[ -z "$config" ] && return
uci del serverchan.serverchan.$1 2>/dev/null
uci commit serverchan 2>/dev/null
uci set wechatpush.config.$2=$config
uci commit wechatpush
}
function serverchan_to_wechatpush_get(){
while [[ "$*" != "" ]]; do
config=`uci get serverchan.serverchan.$1` 2>/dev/null
[ -z "$config" ] && shift && continue
uci del serverchan.serverchan.$1 2>/dev/null
uci commit serverchan 2>/dev/null
uci set wechatpush.config.${1}=${config}
uci commit wechatpush
shift
done
}
if [ ! -f "/etc/config/wechatpush" ]; then
cat>/etc/config/wechatpush<<EOF
config wechatpush "config"
option enable '0'
option sleeptime '60'
option debuglevel '1'
option up_timeout '2'
option down_timeout '20'
option timeout_retry_count '2'
option thread_num '3'
EOF
fi
serverchan_config="/etc/config/serverchan"
if [ -f "$serverchan_config" ]; then
cp "/etc/config/serverchan" "/etc/config/serverchan.bak"
sed -i 's#/usr/share/serverchan/api/#/usr/share/wechatpush/api/#g' "$serverchan_config" 2>/dev/null
sed -i 's#/root/usr/bin/serverchan/api/#/usr/share/wechatpush/api/#g' "$serverchan_config" 2>/dev/null
fi
get_config_serverchan "serverchan_up" "serverchan_down"
[ -n "$serverchan_up" ] && [ "$serverchan_up" -eq "1" ] && uci add_list wechatpush.config.device_notification='online'
[ -n "$serverchan_down" ] && [ "$serverchan_down" -eq "1" ] && uci add_list wechatpush.config.device_notification='offline'
get_config_serverchan "cpuload_enable" "temperature_enable"
[ -n "$cpuload_enable" ] && [ "$cpuload_enable" -eq "1" ] && uci add_list wechatpush.config.cpu_notification='load'
[ -n "$temperature_enable" ] && [ "$temperature_enable" -eq "1" ] && uci add_list wechatpush.config.cpu_notification='temp'
get_config_serverchan "web_logged" "ssh_logged" "web_login_failed" "ssh_login_failed"
[ -n "$web_logged" ] && [ "$web_logged" -eq "1" ] && uci add_list wechatpush.config.login_notification='web_logged'
[ -n "$ssh_logged" ] && [ "$ssh_logged" -eq "1" ] && uci add_list wechatpush.config.login_notification='ssh_logged'
[ -n "$web_login_failed" ] && [ "$web_login_failed" -eq "1" ] && uci add_list wechatpush.config.login_notification='web_login_failed'
[ -n "$ssh_login_failed" ] && [ "$ssh_login_failed" -eq "1" ] && uci add_list wechatpush.config.login_notification='ssh_login_failed'
get_config_serverchan "router_status" "router_temp" "router_wan" "client_list"
[ -n "$router_status" ] && [ "$router_status" -eq "1" ] && uci add_list wechatpush.config.send_notification='router_status'
[ -n "$router_temp" ] && [ "$router_temp" -eq "1" ] && uci add_list wechatpush.config.send_notification='router_temp'
[ -n "$router_wan" ] && [ "$router_wan" -eq "1" ] && uci add_list wechatpush.config.send_notification='wan_info'
[ -n "$client_list" ] && [ "$client_list" -eq "1" ] && uci add_list wechatpush.config.send_notification='client_list'
get_config_serverchan "regular_time" "regular_time2" "regular_time3"
[ -n "$regular_time" ] && uci add_list wechatpush.config.crontab_regular_time="$regular_time"
[ -n "$regular_time2" ] && uci add_list wechatpush.config.crontab_regular_time="$regular_time2"
[ -n "$regular_time3" ] && uci add_list wechatpush.config.crontab_regular_time="$regular_time3"
get_config_wechatpush "gateway_info_enable" "gateway_sleeptime"
[ -n "$gateway_info_enable" ] && [ "$" -eq "1" ] && uci add_list wechatpush.config.device_info_helper='gateway_info'
[ -n "$gateway_sleeptime" ] && uci set wechatpush.config.device_info_helper_sleeptime="$gateway_sleeptime"
serverchan_to_wechatpush_list "device_notification"
serverchan_to_wechatpush_list "cpu_notification"
serverchan_to_wechatpush_list "login_notification"
serverchan_to_wechatpush_list "send_notification"
serverchan_to_wechatpush_list "ip_white_list" "login_ip_white_list"
serverchan_to_wechatpush_list "port_forward_list" "login_port_forward_list"
serverchan_to_wechatpush_list "client_usage_whitelist"
serverchan_to_wechatpush_list "serverchan_whitelist" "up_down_push_whitelist"
serverchan_to_wechatpush_list "serverchan_blacklist" "up_down_push_blacklist"
serverchan_to_wechatpush_list "MAC_online_list" "mac_online_list"
serverchan_to_wechatpush_list "MAC_offline_list" "mac_offline_list"
serverchan_to_wechatpush_list "err_device_aliases" "unattended_device_aliases"
get_config_serverchan "device_aliases"
mkdir -p /usr/share/wechatpush/api/
[ -n "$device_aliases" ] && echo "$device_aliases"|sed 's/ /\n/g'|sed 's/-/ /' > /usr/share/wechatpush/api/device_aliases.list
serverchan_device_aliases_path="/usr/share/serverchan/api/device_aliases.list"
wechatpush_device_aliases_path="/usr/share/wechatpush/api/device_aliases.list"
[ -f "$wechatpush_device_aliases_path" ] && [ `tail -n1 "${wechatpush_device_aliases_path}" | wc -l` -eq "0" ] && echo -e >> ${wechatpush_device_aliases_path}
[ -f "$serverchan_device_aliases_path" ] && grep -v '^#' "$serverchan_device_aliases_path" | grep -v '^[[:space:]]*$' | sort -u > "$wechatpush_device_aliases_path.temp" && mv "$wechatpush_device_aliases_path.temp" "$wechatpush_device_aliases_path"
[ -f "$serverchan_device_aliases_path" ] && rm -rf "$serverchan_device_aliases_path"
cp -r "/usr/share/serverchan/api/." "/usr/share/wechatpush/api/" 2>/dev/null
rm -rf "/usr/share/serverchan/api" 2>/dev/null
serverchan_to_wechatpush_change "serverchan_enable" "enable"
serverchan_to_wechatpush_change "serverchan_ipv4" "get_ipv4_mode"
serverchan_to_wechatpush_change "serverchan_ipv6" "get_ipv6_mode"
serverchan_to_wechatpush_change "update_list" "auto_update_ip_list"
serverchan_to_wechatpush_change "cpuload" "cpu_load_threshold"
serverchan_to_wechatpush_change "temperature" "temperature_threshold"
serverchan_to_wechatpush_change "web_login_black" "login_web_black"
serverchan_to_wechatpush_change "ip_black_timeout" "login_ip_black_timeout"
serverchan_to_wechatpush_change "port_knocking" "port_knocking_enable"
serverchan_to_wechatpush_change "ip_white_timeout" "login_ip_white_timeout"
serverchan_to_wechatpush_change "ip_port_white" "login_port_white"
serverchan_to_wechatpush_change "regular_time" "crontab_regular_time"
serverchan_to_wechatpush_change "interval_time" "crontab_interval_time"
serverchan_to_wechatpush_change "serverchan_sheep" "do_not_disturb_mode"
serverchan_to_wechatpush_change "starttime" "do_not_disturb_starttime"
serverchan_to_wechatpush_change "endtime" "do_not_disturb_endtime"
serverchan_to_wechatpush_change "serverchan_interface" "up_down_push_interface"
serverchan_to_wechatpush_change "passive_option" "passive_mode"
serverchan_to_wechatpush_change "err_enable" "unattended_enable"
serverchan_to_wechatpush_change "err_sheep_enable" "unattended_only_on_disturb_time"
serverchan_to_wechatpush_change "network_err_event" "network_disconnect_event"
serverchan_to_wechatpush_change "system_time_event" "unattended_autoreboot_mode"
serverchan_to_wechatpush_change "autoreboot_time" "autoreboot_system_uptime"
serverchan_to_wechatpush_change "network_restart_time autoreboot_network_uptime"
serverchan_to_wechatpush_change "crontab" "crontab_mode"
serverchan_to_wechatpush_change "macmechanism" "mac_filtering_mode_1"
serverchan_to_wechatpush_change "macmechanism2" "mac_filtering_mode_2"
serverchan_to_wechatpush_get \
"enable" "lite_enable" "device_name" "sleeptime" "oui_data" "reset_regularly" "debuglevel" \
"jsonpath" "sckey" "corpid" "userid" "agentid" "corpsecret" "mediapath" "wxpusher_apptoken" "wxpusher_uids" "wxpusher_topicIds" "pushplus_token" "tg_token" "chat_id" \
"get_ipv4_mode" "ipv4_interface" "get_ipv6_mode" "ipv6_interface" "auto_update_ip_list" \
"device_notification" "cpu_notification" "cpu_load_threshold" "temperature_threshold" \
"client_usage" "client_usage_max" "client_usage_disturb" "client_usage_whitelist" \
"login_notification" "login_max_num" "login_web_black" "login_ip_black_timeout" "login_ip_white_list" "port_knocking_enable" "login_ip_white_timeout" "login_port_white" "login_port_forward_list" \
"crontab_regular_time" "crontab_interval_time" \
"do_not_disturb_mode" "do_not_disturb_starttime" "do_not_disturb_endtime" "up_down_push_whitelist" "up_down_push_blacklist" "up_down_push_interface" "mac_online_list" "mac_offline_list" "login_disturb" "login_notification_delay" \
"up_timeout" "down_timeout" "timeout_retry_count" "passive_mode" "thread_num" "soc_code" "server_host" "server_port" \
"unattended_enable" "zerotier_helper" "unattended_only_on_disturb_time" "unattended_device_aliases" "network_disconnect_event" "unattended_autoreboot_mode" "autoreboot_system_uptime" "autoreboot_network_uptime" \
"gateway_info_enable" "gateway_host_url" "gateway_info_url" "gateway_logout_url" "gateway_username_id" "gateway_password_id" "gateway_username" "gateway_password" "gateway_sleeptime"
uci commit wechatpush
rm -rf "$serverchan_config" 2>/dev/null
dir="/tmp/wechatpush/" && mkdir -p ${dir}
echo "" > ${dir}web_login
echo "" > ${dir}ssh_login
echo "" > ${dir}web_failed
echo "" > ${dir}ssh_failed
nohup sh -c 'while [ -f /var/lock/opkg.lock ]; do sleep 1; done; opkg remove luci-app-serverchan; rm -rf /tmp/luci-*' >/dev/null 2>&1 &

View File

@ -0,0 +1,48 @@
#!/bin/sh
logfile="/tmp/wechatpush/wechatpush.log"
dir="/tmp/wechatpush/" && mkdir -p ${dir} && mkdir -p ${dir}/client
oui_base=${dir}oui_base.txt
oui_data=$(uci get wechatpush.config.oui_data 2>/dev/null)
oui_url="https://standards-oui.ieee.org/oui/oui.txt"
function file_date(){
file_dir="$1"
[ -f ${file_dir} ] && filerow=$(grep -c "" ${file_dir}) || filerow="0"
[ "$filerow" -ne "0" ] && datetime=$(date -r ${file_dir} +%s 2>/dev/null) || datetime=0
expr $(date +%s) - $datetime
}
function down_oui(){
if [ ! -z "$oui_data" ] && [ "$oui_data" -ne "3" ]; then
echo "`date "+%Y-%m-%d %H:%M:%S"` 【info】开始后台更新 MAC 信息文件" >> ${logfile}
wget --no-check-certificate -t 10 -T 15 -O ${dir}oui.txt "$oui_url" >/dev/null 2>&1
[ $? -ne "0"] && echo "`date "+%Y-%m-%d %H:%M:%S"` 【!!!】设备 MAC 信息文件下载失败,返回码为 $? " && return
echo "`date "+%Y-%m-%d %H:%M:%S"` 【info】设备 MAC 信息文件下载成功,处理中" >> ${logfile}
if [ "$oui_data" -eq "1" ]; then
cat ${dir}oui.txt | grep -i -E ".*(base 16).*(apple|aruba|asus|autelan|belkin|bhu|buffalo|cctf|cisco|comba|datang|dell|dlink|dowell|ericsson|fast|feixun|fiberhome|fujitsu|grentech|h3c|hisense|hiwifi|honghai|honghao|hp|htc|huawei|intel|jinli|jse|lenovo|lg|liteon|malata|meizu|mercury|meru|moto|netcore|netgear|nokia|omron|oneplus|oppo|philips|router_unkown|samsung|shanzhai|sony|start_net|sunyuanda|tcl|tenda|texas|tianyu|tp-link|ubq|undefine|VMware|utstarcom|volans|xerox|xiaomi|zdc|zhongxing|smartisan).*" | sed -E 's/( Electronic| Technology| Intelligence| TECHNOLOGIES| Device| Systems| TELECOMMUNICATIONS| Instruments| Electronics| Corporation| Telecommunication| Communications| Electrical| Technology| Corporate| Intelligent| Interactive| MOBILE| Solutions| Mobility| Meraki| ELECTRO| VISUAL| Limited| International| Information| LLC|Co$|Co\.|Ltd\.$|Inc\.|B\.V\.$|AB$|,).*$/ /I; s/[[:space:]]*$//; s/ +$//' > ${oui_base}
elif [ "$oui_data" -eq "2" ]; then
cat ${dir}oui.txt | grep -i "(base 16)" | sed -E 's/( Electronic| Technology| Intelligence| TECHNOLOGIES| Device| Systems| TELECOMMUNICATIONS| Instruments| Electronics| Corporation| Telecommunication| Communications| Electrical| Technology| Corporate| Intelligent| Interactive| MOBILE| Solutions| Mobility| Meraki| ELECTRO| VISUAL| Limited| International| Information| LLC|Co$|Co\.|Ltd\.$|Inc\.|B\.V\.$|AB$|,).*$/ /I; s/[[:space:]]*$//; s/ +$//' > ${oui_base}
fi
rm -f ${dir}oui.txt >/dev/null 2>&1
echo "`date "+%Y-%m-%d %H:%M:%S"` 【info】设备 MAC 信息文件处理完成" >> ${logfile}
fi
}
if [ "$1" == "get_client" ]; then
# 生成在线设备列表,沿用 LUA 版本生成的临时文件
devices=$(find /tmp/wechatpush/client -type f -print0 | xargs -0 cat | sed "s/'/\"/g" | tr '\n' ',')
echo "{\"devices\": [${devices%,}]}"
elif [ "$1" == "clear_log" ]; then
# 清空日志
> /tmp/wechatpush/wechatpush.log
elif [ "$1" == "update_list" ]; then
# 更新 API 列表
echo "`date "+%Y-%m-%d %H:%M:%S"` 【info】开始更新 $2 API 列表" >> ${logfile}
wget --no-check-certificate -t 3 -T 15 -O "/tmp/wechatpush/${2}.list" "https://raw.githubusercontent.com/tty228/luci-app-wechatpush/master/root/usr/share/wechatpush/api/${2}.list" >/dev/null 2>&1
[ "$?" -eq "0" ] && mv -f "/tmp/wechatpush/${2}.list" "/usr/share/wechatpush/api/${2}.list" echo "`date "+%Y-%m-%d %H:%M:%S"` 【info】 $2 API 列表更新成功" >> ${logfile}
elif [ "$1" == "down_oui" ]; then
# 更新 MAC 信息列表
[ `file_date "$oui_base"` -lt "86400" ] && return 2
down_oui > /dev/null 2>&1 &
fi

View File

@ -0,0 +1,49 @@
{
"admin/services/wechatpush": {
"title": "WeChat push",
"order": 30,
"action": {
"type": "firstchild"
},
"depends": {
"acl": [ "luci-app-wechatpush" ],
"uci": { "wechatpush": true }
}
},
"admin/services/wechatpush/config": {
"title": "Basic Settings",
"order": 10,
"action": {
"type": "view",
"path": "wechatpush/config"
}
},
"admin/services/wechatpush/advanced": {
"title": "Advance Setting",
"order": 20,
"action": {
"type": "view",
"path": "wechatpush/advanced"
}
},
"admin/services/wechatpush/client": {
"title": "Online Devices",
"order": 30,
"action": {
"type": "view",
"path": "wechatpush/client"
}
},
"admin/services/wechatpush/log": {
"title": "Log",
"order": 40,
"action": {
"type": "view",
"path": "wechatpush/log"
}
}
}

View File

@ -0,0 +1,25 @@
{
"luci-app-wechatpush": {
"description": "Grant UCI access for luci-app-wechatpush",
"read": {
"file": {
"/etc/init.d/wechatpush": [ "exec" ],
"/usr/share/wechatpush/wechatpush": [ "exec" ],
"/tmp/wechatpush/*": [ "read" ],
"/usr/share/wechatpush/api/*": [ "read" ],
"/usr/libexec/wechatpush-call": [ "exec" ]
},
"ubus": {
"service": [ "list" ]
},
"uci": [ "wechatpush" ]
},
"write": {
"file": {
"/usr/share/wechatpush/api/*": [ "write" ],
"/tmp/wechatpush/*": [ "write" ]
},
"uci": [ "wechatpush" ]
}
}
}

View File

@ -0,0 +1,3 @@
# Examples :
#XX:XX:XX:XX:XX:XX My Phone
#192.168.1.2 My PC

View File

@ -0,0 +1,42 @@
{
"_//": "-------------------------------------------------------------------------------",
"_readme": "这是 自定义 api 文件,这里以 telegram 为例",
"_readme": "特殊符号请使用斜杠转义,变量使用 ${var} 表示",
"_//": "-------------------------------------------------------------------------------",
"_api": "【DIY 推送】",
"_url": "api 地址",
"_data": "生成的 json 文件路径,一般不需要改,如 api 不支持 json请参考 serverchan 推送接口",
"_content_type": "post 内容类型,这里为 json",
"_//": "-------------------------------------------------------------------------------",
"_str_title_start": "标题粗体字开始符号",
"_str_title_end": "标题粗体字结束符号",
"_str_linefeed": "换行符号",
"_str_splitline": "换行+分隔符",
"_str_space": "空格",
"_str_tab": "TAB用在行首生成文字区块",
"_//": "-------------------------------------------------------------------------------",
"_type":
{
"_readme": "下文中text 为 telegram 推送需要的键值名称,参见 telegram 官方文档,后面的内容为生成标题所需要的字符串和变量,${1} 为标题内容变量,${nowtime} 为推送时间,${2} 为推送内容变量",
"_readme": "下文中chat_id 为 telegram 推送需要的键值名称,参见 telegram 官方文档,${chat_id} 为从脚本配置中读取名为 chat_id 的变量,其实就是你填写的机器人的 chat_id ",
"_readme": "type 对象因为需要转义变量,前后必须使用 斜杠+双引号 转义",
"_readme": "参照上文说明,填写下文相关参数"
},
"_//": "-------------------------------------------------------------------------------",
"url": "https://api.telegram.org/bot${tg_token}/sendMessage",
"data": "@${tempjsonpath}",
"content_type": "Content-Type: application/json",
"str_title_start": "<b>",
"str_title_end": "</b>",
"str_linefeed": "\\n",
"str_splitline": "\\n----\\n",
"str_space": " ",
"str_tab": " ",
"type":
{
"text":"\"${str_title_start}${1}${str_title_end}${str_splitline}${nowtime}${2}\"",
"chat_id":"\"${chat_id}\"",
"parse_mode":"\"HTML\""
}
}

View File

@ -0,0 +1,2 @@
curl -s cip.cc/${ip} | sed -n 's/地址[[:space:]]*:[[:space:]]*\(.*\)/\1/p'
curl -s https://ip.rss.ink/v1/qqwry?ip=${ip} | jq -r '.data.area'

View File

@ -0,0 +1,7 @@
cip.cc
ddns.oray.com/checkip
www.net.cn/static/customercare/yourip.asp
ip.3322.net
ip.threep.top
10086.cn/web-Center/commonservice/getUserIp.do --referer http://10086.cn -XPOST
https://www.taobao.com/help/getip.php -H 'authority: www.taobao.com'

View File

@ -0,0 +1,5 @@
ipv6.ddnspod.com
speed.neu6.edu.cn/getIP.php
6.ipw.cn
10086.cn/web-Center/commonservice/getUserIp.do --referer http://10086.cn -XPOST
https://www.taobao.com/help/getip.php -H 'authority: www.taobao.com'

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -0,0 +1,21 @@
{
"_api": "这是 pushplus api 文件",
"_api": "【pushplus】",
"url": "http://www.pushplus.plus/send",
"data": "@${tempjsonpath}",
"content_type": "Content-Type: application/json",
"str_title_start": "##### ",
"str_title_end": "",
"str_linefeed": "\\n",
"str_splitline": "\\n----\\n",
"str_space": " ",
"str_tab": " ",
"type":
{
"title": "\"${1}\"",
"content": "\"${2}\"",
"token": "\"${pushplus_token}\"",
"template":"\"markdown\""
}
}

View File

@ -0,0 +1,23 @@
{
"_api": "这是企业微信 markdown 模板信息 api 文件",
"_api": "【企业微信】",
"url": "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=$(curl -s \"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=${corpid}&corpsecret=${corpsecret}\"|jq '.access_token' | sed 's/\"//g')",
"data": "@${tempjsonpath}",
"content_type": "Content-Type: application/json",
"str_title_start": "#### ",
"str_title_end": "",
"str_linefeed": "\\n",
"str_splitline": "\\n\\n",
"str_space": " ",
"str_tab": "> ",
"type":
{
"touser": "\"${userid}\"",
"msgtype": "\"markdown\"",
"agentid": "\"${agentid}\"",
"markdown": {
"content": "\"${1}${str_linefeed}${nowtime}${2}\""
}
}
}

View File

@ -0,0 +1,33 @@
{
"_api": "这是企业微信图文信息 api 文件",
"_api": "【企业微信】",
"url": "\"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=$(curl -s \"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=${corpid}&corpsecret=${corpsecret}\"|jq '.access_token'|sed 's/\"//g')\"",
"data": "@${tempjsonpath}",
"content_type": "Content-Type: application/json",
"str_title_start": "<b>",
"str_title_end": "</b>",
"str_linefeed": "<br>",
"str_splitline": "<hr>",
"str_space": " ",
"str_tab": "",
"type":
{
"touser": "\"${userid}\"",
"msgtype": "\"mpnews\"",
"agentid": "\"${agentid}\"",
"mpnews":{
"articles":[
{
"title": "\"${nowtime}${str_linefeed}${1}\"",
"thumb_media_id": "\"`curl \"https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=$(curl -s \"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=${corpid}&corpsecret=${corpsecret}\"|jq '.access_token'|sed 's/\"//g')&type=image\" -F \"file=@${mediapath}\"|jq '.media_id'|sed 's/\"//g'`\"",
"author": "\"\"",
"content_source_url": "\"\"",
"content": "\"${2}\"",
"digest": "\"\""
}
]
},
"safe":0
}
}

View File

@ -0,0 +1,17 @@
{
"_api": "这是 serverchan api 文件",
"_api": "【serverchan】",
"url": "\"https://sctapi.ftqq.com/${sckey}.send\"",
"data": "\"text=${1}&desp=${nowtime}${str_linefeed}${2}\"",
"content_type": "Content-Type:application/x-www-form-urlencoded",
"str_title_start": "#### ",
"str_title_end": "",
"str_linefeed": "%0D%0A%0D%0A",
"str_splitline": "%0D%0A%0D%0A----%0D%0A%0D%0A",
"str_space": " ",
"str_tab": " ",
"type":
{
}
}

View File

@ -0,0 +1,20 @@
{
"_api": "这是 telegram api 文件",
"_api": "【telegram】",
"url": "https://api.telegram.org/bot${tg_token}/sendMessage",
"data": "@${tempjsonpath}",
"content_type": "Content-Type: application/json",
"str_title_start": "<b>",
"str_title_end": "</b>",
"str_linefeed": "\\n",
"str_splitline": "\\n----\\n",
"str_space": " ",
"str_tab": " ",
"type":
{
"text":"\"${str_title_start}${1}${str_title_end}${str_splitline}${nowtime}${2}\"",
"chat_id":"\"${chat_id}\"",
"parse_mode":"\"HTML\""
}
}

View File

@ -0,0 +1,23 @@
{
"_api": "这是 wxpusher api 文件",
"_api": "【wxpusher】",
"url": "http://wxpusher.zjiecode.com/api/send/message",
"data": "@${tempjsonpath}",
"content_type": "Content-Type: application/json",
"str_title_start": "#### ",
"str_title_end": "",
"str_linefeed": "\\n",
"str_splitline": "\\n----\\n",
"str_space": " ",
"str_tab": " ",
"type":
{
"summary":"\"${1}\"",
"content":"\"${2}\"",
"appToken":"\"${wxpusher_apptoken}\"",
"topicIds":"[\"${wxpusher_topicIds}\"]",
"uids":"[\"${wxpusher_uids}\"]",
"contentType":3
}
}

File diff suppressed because it is too large Load Diff