From 0cde9d07eebc39e98d8d58d1cf0e0fb74a0f55a0 Mon Sep 17 00:00:00 2001 From: kilo5hz <90814817+kilo5hz@users.noreply.github.com> Date: Mon, 15 Nov 2021 23:04:55 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E5=A2=9E=E5=8A=A0gotify=E6=8E=A8=E9=80=81?= =?UTF-8?q?=20(#905)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 增加gotify推送 --- sample/notify.js | 61 ++++++++++++++++++++++++++++++++++++++++++--- sample/notify.py | 25 +++++++++++++++++++ src/utils/config.ts | 10 ++++++++ 3 files changed, 92 insertions(+), 4 deletions(-) diff --git a/sample/notify.js b/sample/notify.js index 8c85baf8..12b7cfeb 100644 --- a/sample/notify.js +++ b/sample/notify.js @@ -13,6 +13,13 @@ const querystring = require('querystring'); const $ = new Env(); const timeout = 15000; //超时时间(单位毫秒) +// =======================================gotify通知设置区域============================================== +//gotify_url 填写gotify地址,如https://push.example.de:8080 +//gotify_token 填写gotify的消息应用token +//gotify_priority 填写推送消息优先级,默认为0 +let GOTIFY_URL = ''; +let GOTIFY_TOKEN = ''; +let GOTIFY_PRIORITY = 0; // =======================================go-cqhttp通知设置区域=========================================== //gobot_url 填写请求地址http://127.0.0.1/send_private_msg //gobot_token 填写在go-cqhttp文件设置的访问密钥 @@ -84,6 +91,16 @@ let PUSH_PLUS_TOKEN = ''; let PUSH_PLUS_USER = ''; //==========================云端环境变量的判断与接收========================= +if (process.env.GOTIFY_URL) { + GOTIFY_URL = process.env.GOTIFY_URL; +} +if (process.env.GOTIFY_TOKEN) { + GOTIFY_TOKEN = process.env.GOTIFY_TOKEN; +} +if (process.env.GOTIFY_PRIORITY) { + GOTIFY_PRIORITY = process.env.GOTIFY_PRIORITY; +} + if (process.env.GOBOT_URL) { GOBOT_URL = process.env.GOBOT_URL; } @@ -200,9 +217,45 @@ async function sendNotify( qywxamNotify(text, desp), //企业微信应用消息推送 iGotNotify(text, desp, params), //iGot gobotNotify(text, desp),//go-cqhttp + gotifyNotify(text, desp),//gotify ]); } +function gotifyNotify(text, desp) { + return new Promise((resolve) => { + if (GOTIFY_URL && GOTIFY_TOKEN) { + const options = { + url: `${GOTIFY_URL}/message?token=${GOTIFY_TOKEN}`, + body: `title=${encodeURIComponent(text)}&message=${encodeURIComponent(desp)}&priority=${GOTIFY_PRIORITY}`, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + } + }; + $.post(options, (err, resp, data) => { + try { + if (err) { + console.log('gotify发送通知调用API失败!!\n'); + console.log(err); + } else { + data = JSON.parse(data); + if (data.id) { + console.log('gotify发送通知消息成功🎉\n'); + } else { + console.log(`${data.message}\n`); + } + } + } catch (e) { + $.logErr(e, resp); + } finally { + resolve(); + } + }); + } else { + resolve(); + } + }); +} + function gobotNotify(text, desp, time = 2100) { return new Promise((resolve) => { if (GOBOT_URL) { @@ -673,8 +726,8 @@ function qywxamNotify(text, desp) { if (err) { console.log( '成员ID:' + - ChangeUserId(desp) + - '企业微信应用消息发送通知消息失败!!\n', + ChangeUserId(desp) + + '企业微信应用消息发送通知消息失败!!\n', ); console.log(err); } else { @@ -682,8 +735,8 @@ function qywxamNotify(text, desp) { if (data.errcode === 0) { console.log( '成员ID:' + - ChangeUserId(desp) + - '企业微信应用消息发送通知消息成功🎉。\n', + ChangeUserId(desp) + + '企业微信应用消息发送通知消息成功🎉。\n', ); } else { console.log(`${data.errmsg}\n`); diff --git a/sample/notify.py b/sample/notify.py index b08634ca..e1691bbe 100644 --- a/sample/notify.py +++ b/sample/notify.py @@ -51,6 +51,10 @@ push_config = { # /send_group_msg 时填入 group_id=QQ群 'GOBOT_TOKEN': '', # go-cqhttp 的 access_token + 'GOTIFY_URL': '', # gotify地址,如https://push.example.de:8080 + 'GOTIFY_TOKEN': '', # gotify的消息应用token + 'GOTIFY_PRIORITY': 0, # 推送消息优先级,默认为0 + 'IGOT_PUSH_KEY': '', # iGot 聚合推送的 IGOT_PUSH_KEY 'PUSH_KEY': '', # server 酱的 PUSH_KEY,兼容旧版与 Turbo 版 @@ -194,6 +198,25 @@ def go_cqhttp(title: str, content: str) -> None: print("go-cqhttp 推送失败!") +def gotify(title:str,content:str) -> None: + """ + 使用 gotify 推送消息。 + """ + if not push_config.get("GOTIFY_URL") or not push_config.get("GOTIFY_TOKEN"): + print("gotify 服务的 GOTIFY_URL 或 GOTIFY_TOKEN 未设置!!\n取消推送") + return + print("gotify 服务启动") + + url = f'{push_config.get("GOTIFY_URL")}/message?token={push_config.get("GOTIFY_TOKEN")}' + data = {"title": title,"message": content,"priority": push_config.get("GOTIFY_PRIORITY")} + response = requests.post(url,data=data).json() + + if response.get("id"): + print("gotify 推送成功!") + else: + print("gotify 推送失败!") + + def iGot(title: str, content: str) -> None: """ 使用 iGot 推送消息。 @@ -473,6 +496,8 @@ if push_config.get("FSKEY"): notify_function.append(feishu_bot) if push_config.get("GOBOT_URL") and push_config.get("GOBOT_QQ"): notify_function.append(go_cqhttp) +if push_config.get("GOTIFY_URL") and push_config.get("GOTIFY_TOKEN"): + notify_function.append(gotify) if push_config.get("IGOT_PUSH_KEY"): notify_function.append(iGot) if push_config.get("PUSH_KEY"): diff --git a/src/utils/config.ts b/src/utils/config.ts index a1b1e083..4c0c28a4 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -64,6 +64,7 @@ export default { logs: '任务日志', }, notificationModes: [ + { value: 'gotify', label: 'Gotify' }, { value: 'goCqHttpBot', label: 'GoCqHttpBot' }, { value: 'serverChan', label: 'Server酱' }, { value: 'bark', label: 'Bark' }, @@ -77,6 +78,15 @@ export default { { value: 'closed', label: '已关闭' }, ], notificationModeMap: { + gotify: [ + { + label: 'gotifyUrl', + tip: 'gotify的url地址,例如 https://push.example.de:8080', + required: true, + }, + { label: 'gotifyToken', tip: 'gotify的消息应用token码', required: true }, + { label: 'gotifyPriority', tip: '推送消息的优先级' }, + ], goCqHttpBot: [ { label: 'goCqHttpBotUrl', From d1e9f741d0dd8c72321a1822ec703859336959c9 Mon Sep 17 00:00:00 2001 From: whyour Date: Tue, 16 Nov 2021 00:15:49 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=88=A0=E9=99=A4=E3=80=81=E6=96=B0=E5=BB=BA?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=80=89=E6=8B=A9=E7=88=B6=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/api/script.ts | 9 +++- shell/check.sh | 14 ++---- shell/update.sh | 14 ++---- src/pages/script/editNameModal.tsx | 36 +++++++++++++-- src/pages/script/index.tsx | 71 ++++++++++++++++++++++++------ 5 files changed, 104 insertions(+), 40 deletions(-) diff --git a/back/api/script.ts b/back/api/script.ts index 2e418e5c..930f11a4 100644 --- a/back/api/script.ts +++ b/back/api/script.ts @@ -120,6 +120,9 @@ export default (app: Router) => { if (!path.endsWith('/')) { path += '/'; } + if (!path.startsWith('/')) { + path = `${config.scriptPath}${path}`; + } if (config.writePathList.every((x) => !path.startsWith(x))) { return res.send({ code: 430, @@ -184,15 +187,17 @@ export default (app: Router) => { celebrate({ body: Joi.object({ filename: Joi.string().required(), + path: Joi.string().allow(''), }), }), async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger'); try { - let { filename } = req.body as { + let { filename, path } = req.body as { filename: string; + path: string; }; - const filePath = `${config.scriptPath}${filename}`; + const filePath = `${config.scriptPath}${path}/${filename}`; fs.unlinkSync(filePath); res.send({ code: 200 }); } catch (e) { diff --git a/shell/check.sh b/shell/check.sh index c3277591..decd277b 100644 --- a/shell/check.sh +++ b/shell/check.sh @@ -39,17 +39,11 @@ copy_dep() { reload_pm2() { pm2 l &>/dev/null - if test -z "$(pm2 info panel 1>/dev/null)"; then - pm2 reload panel --source-map-support --time &>/dev/null - else - pm2 start $dir_root/build/app.js -n panel --source-map-support --time &>/dev/null - fi + pm2 delete panel --source-map-support --time &>/dev/null + pm2 start $dir_root/build/app.js -n panel --source-map-support --time &>/dev/null - if test -z "$(pm2 info schedule 1>/dev/null)"; then - pm2 reload schedule --source-map-support --time &>/dev/null - else - pm2 start $dir_root/build/schedule.js -n schedule --source-map-support --time &>/dev/null - fi + pm2 delete schedule --source-map-support --time &>/dev/null + pm2 start $dir_root/build/schedule.js -n schedule --source-map-support --time &>/dev/null } pm2_log() { diff --git a/shell/update.sh b/shell/update.sh index 72ae41d4..d7b49920 100755 --- a/shell/update.sh +++ b/shell/update.sh @@ -318,17 +318,11 @@ patch_version() { reload_pm2() { pm2 l &>/dev/null - if [[ $(pm2 info panel 2>/dev/null) ]]; then - pm2 reload panel --source-map-support --time &>/dev/null - else - pm2 start $dir_root/build/app.js -n panel --source-map-support --time &>/dev/null - fi + pm2 delete panel --source-map-support --time &>/dev/null + pm2 start $dir_root/build/app.js -n panel --source-map-support --time &>/dev/null - if [[ $(pm2 info schedule 2>/dev/null) ]]; then - pm2 reload schedule --source-map-support --time &>/dev/null - else - pm2 start $dir_root/build/schedule.js -n schedule --source-map-support --time &>/dev/null - fi + pm2 delete schedule --source-map-support --time &>/dev/null + pm2 start $dir_root/build/schedule.js -n schedule --source-map-support --time &>/dev/null } ## 对比脚本 diff --git a/src/pages/script/editNameModal.tsx b/src/pages/script/editNameModal.tsx index 75528428..271ce481 100644 --- a/src/pages/script/editNameModal.tsx +++ b/src/pages/script/editNameModal.tsx @@ -1,28 +1,42 @@ import React, { useEffect, useState } from 'react'; -import { Modal, message, Input, Form } from 'antd'; +import { Modal, message, Input, Form, Select } from 'antd'; import { request } from '@/utils/http'; import config from '@/utils/config'; +const { Option } = Select; + const EditScriptNameModal = ({ handleCancel, + treeData, visible, }: { visible: boolean; - handleCancel: (file?: { filename: string }) => void; + treeData: any[]; + handleCancel: (file?: { + filename: string; + path: string; + key: string; + }) => void; }) => { const [form] = Form.useForm(); const [loading, setLoading] = useState(false); + const [dirs, setDirs] = useState([]); const handleOk = async (values: any) => { setLoading(true); + values.path = values.path || ''; request .post(`${config.apiPrefix}scripts`, { - data: { filename: values.filename, content: '' }, + data: { filename: values.filename, path: values.path, content: '' }, }) .then(({ code, data }) => { if (code === 200) { message.success('保存文件成功'); - handleCancel({ filename: values.filename }); + handleCancel({ + filename: values.filename, + path: values.path, + key: `${values.path}-${values.filename}`, + }); } else { message.error(data); } @@ -33,6 +47,8 @@ const EditScriptNameModal = ({ useEffect(() => { form.resetFields(); + const originDirs = treeData.filter((x) => x.disabled); + setDirs([{ key: '' }, ...originDirs]); }, [visible]); return ( @@ -56,10 +72,22 @@ const EditScriptNameModal = ({
+ 0 ? dirs[0].key : ''} + > + +
); diff --git a/src/pages/script/index.tsx b/src/pages/script/index.tsx index 65951360..b71b91a6 100644 --- a/src/pages/script/index.tsx +++ b/src/pages/script/index.tsx @@ -113,7 +113,7 @@ const Script = ({ headerStyle, isPhone, theme }: any) => { setValue('加载中...'); const newMode = value ? LangMap[value.slice(-3)] : ''; setMode(isPhone && newMode === 'typescript' ? 'javascript' : newMode); - setSelect(value); + setSelect(node.key); setTitle(node.parent || node.value); setCurrentNode(node); getDetail(node); @@ -167,7 +167,7 @@ const Script = ({ headerStyle, isPhone, theme }: any) => { const cancelEdit = () => { setIsEditing(false); setValue('加载中...'); - getDetail({ value: select }); + getDetail(currentNode); }; const saveFile = () => { @@ -177,7 +177,7 @@ const Script = ({ headerStyle, isPhone, theme }: any) => { <> 确认保存文件 - {select} + {currentNode.value} {' '} ,保存后不可恢复 @@ -190,7 +190,7 @@ const Script = ({ headerStyle, isPhone, theme }: any) => { request .put(`${config.apiPrefix}scripts`, { data: { - filename: select, + filename: currentNode.value, path: currentNode.parent || '', content, }, @@ -230,15 +230,30 @@ const Script = ({ headerStyle, isPhone, theme }: any) => { request .delete(`${config.apiPrefix}scripts`, { data: { - filename: select, + filename: currentNode.value, + path: currentNode.parent || '', }, }) .then((_data: any) => { if (_data.code === 200) { message.success(`删除成功`); let newData = [...data]; - const index = newData.findIndex((x) => x.value === select); - newData.splice(index, 1); + if (currentNode.parent) { + const parentNodeIndex = newData.findIndex( + (x) => x.key === currentNode.parent, + ); + const parentNode = newData[parentNodeIndex]; + const index = parentNode.children.findIndex( + (y) => y.key === currentNode.key, + ); + parentNode.children.splice(index, 1); + newData.splice(parentNodeIndex, 1, { ...parentNode }); + } else { + const index = newData.findIndex( + (x) => x.key === currentNode.key, + ); + newData.splice(index, 1); + } setData(newData); } else { message.error(_data); @@ -256,12 +271,27 @@ const Script = ({ headerStyle, isPhone, theme }: any) => { }; const addFileModalClose = ( - { filename }: { filename: string } = { filename: '' }, + { filename, path, key }: { filename: string; path: string; key: string } = { + filename: '', + path: '', + key: '', + }, ) => { if (filename) { const newData = [...data]; - const _file = { title: filename, key: filename, value: filename }; - newData.unshift(_file); + const _file = { title: filename, key, value: filename, parent: path }; + if (path) { + const parentNodeIndex = newData.findIndex((x) => x.key === path); + const parentNode = newData[parentNodeIndex]; + if (parentNode.children && parentNode.children.length > 0) { + parentNode.children.unshift(_file); + } else { + parentNode.children = [_file]; + } + newData.splice(parentNodeIndex, 1, { ...parentNode }); + } else { + newData.unshift(_file); + } setData(newData); onSelect(_file.value, _file); setIsEditing(true); @@ -273,7 +303,7 @@ const Script = ({ headerStyle, isPhone, theme }: any) => { request .post(`${config.apiPrefix}scripts/download`, { data: { - filename: select, + filename: currentNode.value, }, }) .then((_data: any) => { @@ -281,7 +311,7 @@ const Script = ({ headerStyle, isPhone, theme }: any) => { const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; - a.download = select; + a.download = currentNode.value; document.documentElement.appendChild(a); a.click(); document.documentElement.removeChild(a); @@ -319,10 +349,20 @@ const Script = ({ headerStyle, isPhone, theme }: any) => { } onClick={addFile}> 添加 - } onClick={editFile}> + } + onClick={editFile} + disabled={!select} + > 编辑 - } onClick={deleteFile}> + } + onClick={deleteFile} + disabled={!select} + > 删除 @@ -368,6 +408,7 @@ const Script = ({ headerStyle, isPhone, theme }: any) => { ,