@whyour/qinglong 2.17.13 → 2.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/package.json +9 -2
  2. package/sample/notify.js +47 -30
  3. package/sample/notify.py +36 -53
  4. package/shell/api.sh +26 -0
  5. package/shell/preload/sitecustomize.js +7 -1
  6. package/shell/preload/sitecustomize.py +9 -1
  7. package/shell/share.sh +3 -7
  8. package/shell/task.sh +1 -1
  9. package/shell/update.sh +2 -6
  10. package/static/build/api/config.js +2 -1
  11. package/static/build/api/script.js +4 -3
  12. package/static/build/api/system.js +16 -1
  13. package/static/build/api/user.js +1 -1
  14. package/static/build/config/util.js +10 -3
  15. package/static/build/data/system.js +1 -0
  16. package/static/build/loaders/express.js +8 -11
  17. package/static/build/loaders/initData.js +41 -5
  18. package/static/build/loaders/initFile.js +74 -76
  19. package/static/build/loaders/sock.js +4 -5
  20. package/static/build/services/cron.js +2 -1
  21. package/static/build/services/dependence.js +16 -7
  22. package/static/build/services/env.js +4 -27
  23. package/static/build/services/open.js +16 -7
  24. package/static/build/services/sshKey.js +5 -6
  25. package/static/build/services/system.js +15 -3
  26. package/static/build/services/user.js +116 -161
  27. package/static/build/shared/store.js +32 -0
  28. package/static/build/shared/utils.js +27 -0
  29. package/static/build/token.js +2 -6
  30. package/static/dist/{4642.260d2a8e.async.js → 4642.9e24d86c.async.js} +1 -1
  31. package/static/dist/4799.d5ca9f30.async.js +1 -0
  32. package/static/dist/index.html +2 -2
  33. package/static/dist/{preload_helper.2e4c8e3f.js → preload_helper.55b35ae0.js} +1 -1
  34. package/static/dist/{src__pages__crontab__index.7163c445.async.js → src__pages__crontab__index.55a8714d.async.js} +1 -1
  35. package/static/dist/{src__pages__script__index.b893a14e.async.js → src__pages__script__index.6a212c2d.async.js} +1 -1
  36. package/static/dist/{src__pages__setting__index.636a04c7.async.js → src__pages__setting__index.ffa1cdd6.async.js} +1 -1
  37. package/static/dist/{umi.916b40e1.js → umi.fb3ed7a0.js} +1 -1
  38. package/version.yaml +7 -8
  39. package/static/dist/4799.2c2c56e5.async.js +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whyour/qinglong",
3
- "version": "2.17.13",
3
+ "version": "2.18.1",
4
4
  "description": "Timed task management platform supporting Python3, JavaScript, Shell, Typescript",
5
5
  "repository": {
6
6
  "type": "git",
@@ -70,6 +70,9 @@
70
70
  "react-dom": "18",
71
71
  "dva-core": "2"
72
72
  }
73
+ },
74
+ "overrides": {
75
+ "sqlite3": "git+https://github.com/whyour/node-sqlite3.git#v1.0.3"
73
76
  }
74
77
  },
75
78
  "dependencies": {
@@ -114,7 +117,10 @@
114
117
  "winston": "^3.17.0",
115
118
  "winston-daily-rotate-file": "^5.0.0",
116
119
  "request-ip": "3.3.0",
117
- "ip2region": "2.3.0"
120
+ "ip2region": "2.3.0",
121
+ "keyv": "^5.2.3",
122
+ "@keyv/sqlite": "^4.0.1",
123
+ "proper-lockfile": "^4.1.2"
118
124
  },
119
125
  "devDependencies": {
120
126
  "moment": "2.30.1",
@@ -149,6 +155,7 @@
149
155
  "@types/sockjs-client": "^1.5.1",
150
156
  "@types/uuid": "^8.3.4",
151
157
  "@types/request-ip": "0.0.41",
158
+ "@types/proper-lockfile": "^4.1.4",
152
159
  "@uiw/codemirror-extensions-langs": "^4.21.9",
153
160
  "@uiw/react-codemirror": "^4.21.9",
154
161
  "@umijs/max": "^4.3.36",
package/sample/notify.js CHANGED
@@ -43,12 +43,11 @@ const push_config = {
43
43
  // 官方文档:https://www.pushplus.plus/
44
44
  PUSH_PLUS_TOKEN: '', // pushplus 推送的用户令牌
45
45
  PUSH_PLUS_USER: '', // pushplus 推送的群组编码
46
- PUSH_PLUS_TEMPLATE: 'html', // pushplus 发送模板,支持html,txt,json,markdown,cloudMonitor,jenkins,route,pay
47
- PUSH_PLUS_CHANNEL: 'wechat', // pushplus 发送渠道,支持wechat,webhook,cp,mail,sms
48
- PUSH_PLUS_WEBHOOK: '', // pushplus webhook编码,可在pushplus公众号上扩展配置出更多渠道
49
- PUSH_PLUS_CALLBACKURL: '', // pushplus 发送结果回调地址,会把推送最终结果通知到这个地址上
50
- PUSH_PLUS_TO: '', // pushplus 好友令牌,微信公众号渠道填写好友令牌,企业微信渠道填写企业微信用户id
51
-
46
+ PUSH_PLUS_TEMPLATE: 'html', // pushplus 发送模板,支持html,txt,json,markdown,cloudMonitor,jenkins,route,pay
47
+ PUSH_PLUS_CHANNEL: 'wechat', // pushplus 发送渠道,支持wechat,webhook,cp,mail,sms
48
+ PUSH_PLUS_WEBHOOK: '', // pushplus webhook编码,可在pushplus公众号上扩展配置出更多渠道
49
+ PUSH_PLUS_CALLBACKURL: '', // pushplus 发送结果回调地址,会把推送最终结果通知到这个地址上
50
+ PUSH_PLUS_TO: '', // pushplus 好友令牌,微信公众号渠道填写好友令牌,企业微信渠道填写企业微信用户id
52
51
 
53
52
  // 微加机器人,官方网站:https://www.weplusbot.com/
54
53
  WE_PLUS_BOT_TOKEN: '', // 微加机器人的用户令牌
@@ -243,10 +242,13 @@ function serverNotify(text, desp) {
243
242
 
244
243
  const matchResult = PUSH_KEY.match(/^sctp(\d+)t/i);
245
244
  const options = {
246
- url: matchResult && matchResult[1]
247
- ? `https://${matchResult[1]}.push.ft07.com/send/${PUSH_KEY}.send`
248
- : `https://sctapi.ftqq.com/${PUSH_KEY}.send`,
249
- body: `text=${encodeURIComponent(text)}&desp=${encodeURIComponent(desp)}`,
245
+ url:
246
+ matchResult && matchResult[1]
247
+ ? `https://${matchResult[1]}.push.ft07.com/send/${PUSH_KEY}.send`
248
+ : `https://sctapi.ftqq.com/${PUSH_KEY}.send`,
249
+ body: `text=${encodeURIComponent(text)}&desp=${encodeURIComponent(
250
+ desp,
251
+ )}`,
250
252
  headers: {
251
253
  'Content-Type': 'application/x-www-form-urlencoded',
252
254
  },
@@ -777,7 +779,15 @@ function iGotNotify(text, desp, params = {}) {
777
779
 
778
780
  function pushPlusNotify(text, desp) {
779
781
  return new Promise((resolve) => {
780
- const { PUSH_PLUS_TOKEN, PUSH_PLUS_USER, PUSH_PLUS_TEMPLATE, PUSH_PLUS_CHANNEL, PUSH_PLUS_WEBHOOK, PUSH_PLUS_CALLBACKURL, PUSH_PLUS_TO } = push_config;
782
+ const {
783
+ PUSH_PLUS_TOKEN,
784
+ PUSH_PLUS_USER,
785
+ PUSH_PLUS_TEMPLATE,
786
+ PUSH_PLUS_CHANNEL,
787
+ PUSH_PLUS_WEBHOOK,
788
+ PUSH_PLUS_CALLBACKURL,
789
+ PUSH_PLUS_TO,
790
+ } = push_config;
781
791
  if (PUSH_PLUS_TOKEN) {
782
792
  desp = desp.replace(/[\n\r]/g, '<br>'); // 默认为html, 不支持plaintext
783
793
  const body = {
@@ -789,7 +799,7 @@ function pushPlusNotify(text, desp) {
789
799
  channel: `${PUSH_PLUS_CHANNEL}`,
790
800
  webhook: `${PUSH_PLUS_WEBHOOK}`,
791
801
  callbackUrl: `${PUSH_PLUS_CALLBACKURL}`,
792
- to: `${PUSH_PLUS_TO}`
802
+ to: `${PUSH_PLUS_TO}`,
793
803
  };
794
804
  const options = {
795
805
  url: `https://www.pushplus.plus/send`,
@@ -813,7 +823,9 @@ function pushPlusNotify(text, desp) {
813
823
  console.log(
814
824
  `pushplus 发送${
815
825
  PUSH_PLUS_USER ? '一对多' : '一对一'
816
- }通知请求成功🎉,可根据流水号查询推送结果:${data.data}\n注意:请求成功并不代表推送成功,如未收到消息,请到pushplus官网使用流水号查询推送最终结果`,
826
+ }通知请求成功🎉,可根据流水号查询推送结果:${
827
+ data.data
828
+ }\n注意:请求成功并不代表推送成功,如未收到消息,请到pushplus官网使用流水号查询推送最终结果`,
817
829
  );
818
830
  } else {
819
831
  console.log(
@@ -1222,10 +1234,10 @@ function ntfyNotify(text, desp) {
1222
1234
  if (NTFY_TOPIC) {
1223
1235
  const options = {
1224
1236
  url: `${NTFY_URL || 'https://ntfy.sh'}/${NTFY_TOPIC}`,
1225
- body: `${desp}`,
1237
+ body: `${desp}`,
1226
1238
  headers: {
1227
- 'Title': `${encodeRFC2047(text)}`,
1228
- 'Priority': NTFY_PRIORITY || '3'
1239
+ Title: `${encodeRFC2047(text)}`,
1240
+ Priority: NTFY_PRIORITY || '3',
1229
1241
  },
1230
1242
  timeout,
1231
1243
  };
@@ -1254,22 +1266,29 @@ function ntfyNotify(text, desp) {
1254
1266
 
1255
1267
  function wxPusherNotify(text, desp) {
1256
1268
  return new Promise((resolve) => {
1257
- const { WXPUSHER_APP_TOKEN, WXPUSHER_TOPIC_IDS, WXPUSHER_UIDS } = push_config;
1269
+ const { WXPUSHER_APP_TOKEN, WXPUSHER_TOPIC_IDS, WXPUSHER_UIDS } =
1270
+ push_config;
1258
1271
  if (WXPUSHER_APP_TOKEN) {
1259
1272
  // 处理topic_ids,将分号分隔的字符串转为数组
1260
- const topicIds = WXPUSHER_TOPIC_IDS ? WXPUSHER_TOPIC_IDS.split(';')
1261
- .map(id => id.trim())
1262
- .filter(id => id)
1263
- .map(id => parseInt(id)) : [];
1273
+ const topicIds = WXPUSHER_TOPIC_IDS
1274
+ ? WXPUSHER_TOPIC_IDS.split(';')
1275
+ .map((id) => id.trim())
1276
+ .filter((id) => id)
1277
+ .map((id) => parseInt(id))
1278
+ : [];
1264
1279
 
1265
1280
  // 处理uids,将分号分隔的字符串转为数组
1266
- const uids = WXPUSHER_UIDS ? WXPUSHER_UIDS.split(';')
1267
- .map(uid => uid.trim())
1268
- .filter(uid => uid) : [];
1281
+ const uids = WXPUSHER_UIDS
1282
+ ? WXPUSHER_UIDS.split(';')
1283
+ .map((uid) => uid.trim())
1284
+ .filter((uid) => uid)
1285
+ : [];
1269
1286
 
1270
1287
  // topic_ids uids 至少有一个
1271
1288
  if (!topicIds.length && !uids.length) {
1272
- console.log("wxpusher 服务的 WXPUSHER_TOPIC_IDS 和 WXPUSHER_UIDS 至少设置一个!!\n取消推送");
1289
+ console.log(
1290
+ 'wxpusher 服务的 WXPUSHER_TOPIC_IDS 和 WXPUSHER_UIDS 至少设置一个!!',
1291
+ );
1273
1292
  return resolve();
1274
1293
  }
1275
1294
 
@@ -1280,16 +1299,16 @@ function wxPusherNotify(text, desp) {
1280
1299
  contentType: 2,
1281
1300
  topicIds: topicIds,
1282
1301
  uids: uids,
1283
- verifyPayType: 0
1302
+ verifyPayType: 0,
1284
1303
  };
1285
1304
 
1286
1305
  const options = {
1287
1306
  url: 'https://wxpusher.zjiecode.com/api/send/message',
1288
1307
  body: JSON.stringify(body),
1289
1308
  headers: {
1290
- 'Content-Type': 'application/json'
1309
+ 'Content-Type': 'application/json',
1291
1310
  },
1292
- timeout
1311
+ timeout,
1293
1312
  };
1294
1313
 
1295
1314
  $.post(options, (err, resp, data) => {
@@ -1310,13 +1329,11 @@ function wxPusherNotify(text, desp) {
1310
1329
  }
1311
1330
  });
1312
1331
  } else {
1313
- console.log('wxpusher 服务的 WXPUSHER_APP_TOKEN 未设置!!\n取消推送');
1314
1332
  resolve();
1315
1333
  }
1316
1334
  });
1317
1335
  }
1318
1336
 
1319
-
1320
1337
  function parseString(input, valueFormatFn) {
1321
1338
  const regex = /(\w+):\s*((?:(?!\n\w+:).)*)/g;
1322
1339
  const matches = {};
package/sample/notify.py CHANGED
@@ -144,7 +144,6 @@ def bark(title: str, content: str) -> None:
144
144
  使用 bark 推送消息。
145
145
  """
146
146
  if not push_config.get("BARK_PUSH"):
147
- print("bark 服务的 BARK_PUSH 未设置!!\n取消推送")
148
147
  return
149
148
  print("bark 服务启动")
150
149
 
@@ -196,7 +195,6 @@ def dingding_bot(title: str, content: str) -> None:
196
195
  使用 钉钉机器人 推送消息。
197
196
  """
198
197
  if not push_config.get("DD_BOT_SECRET") or not push_config.get("DD_BOT_TOKEN"):
199
- print("钉钉机器人 服务的 DD_BOT_SECRET 或者 DD_BOT_TOKEN 未设置!!\n取消推送")
200
198
  return
201
199
  print("钉钉机器人 服务启动")
202
200
 
@@ -226,7 +224,6 @@ def feishu_bot(title: str, content: str) -> None:
226
224
  使用 飞书机器人 推送消息。
227
225
  """
228
226
  if not push_config.get("FSKEY"):
229
- print("飞书 服务的 FSKEY 未设置!!\n取消推送")
230
227
  return
231
228
  print("飞书 服务启动")
232
229
 
@@ -245,7 +242,6 @@ def go_cqhttp(title: str, content: str) -> None:
245
242
  使用 go_cqhttp 推送消息。
246
243
  """
247
244
  if not push_config.get("GOBOT_URL") or not push_config.get("GOBOT_QQ"):
248
- print("go-cqhttp 服务的 GOBOT_URL 或 GOBOT_QQ 未设置!!\n取消推送")
249
245
  return
250
246
  print("go-cqhttp 服务启动")
251
247
 
@@ -263,7 +259,6 @@ def gotify(title: str, content: str) -> None:
263
259
  使用 gotify 推送消息。
264
260
  """
265
261
  if not push_config.get("GOTIFY_URL") or not push_config.get("GOTIFY_TOKEN"):
266
- print("gotify 服务的 GOTIFY_URL 或 GOTIFY_TOKEN 未设置!!\n取消推送")
267
262
  return
268
263
  print("gotify 服务启动")
269
264
 
@@ -286,7 +281,6 @@ def iGot(title: str, content: str) -> None:
286
281
  使用 iGot 推送消息。
287
282
  """
288
283
  if not push_config.get("IGOT_PUSH_KEY"):
289
- print("iGot 服务的 IGOT_PUSH_KEY 未设置!!\n取消推送")
290
284
  return
291
285
  print("iGot 服务启动")
292
286
 
@@ -306,13 +300,12 @@ def serverJ(title: str, content: str) -> None:
306
300
  通过 serverJ 推送消息。
307
301
  """
308
302
  if not push_config.get("PUSH_KEY"):
309
- print("serverJ 服务的 PUSH_KEY 未设置!!\n取消推送")
310
303
  return
311
304
  print("serverJ 服务启动")
312
305
 
313
306
  data = {"text": title, "desp": content.replace("\n", "\n\n")}
314
307
 
315
- match = re.match(r'sctp(\d+)t', push_config.get("PUSH_KEY"))
308
+ match = re.match(r"sctp(\d+)t", push_config.get("PUSH_KEY"))
316
309
  if match:
317
310
  num = match.group(1)
318
311
  url = f'https://{num}.push.ft07.com/send/{push_config.get("PUSH_KEY")}.send'
@@ -332,7 +325,6 @@ def pushdeer(title: str, content: str) -> None:
332
325
  通过PushDeer 推送消息
333
326
  """
334
327
  if not push_config.get("DEER_KEY"):
335
- print("PushDeer 服务的 DEER_KEY 未设置!!\n取消推送")
336
328
  return
337
329
  print("PushDeer 服务启动")
338
330
  data = {
@@ -358,7 +350,6 @@ def chat(title: str, content: str) -> None:
358
350
  通过Chat 推送消息
359
351
  """
360
352
  if not push_config.get("CHAT_URL") or not push_config.get("CHAT_TOKEN"):
361
- print("chat 服务的 CHAT_URL或CHAT_TOKEN 未设置!!\n取消推送")
362
353
  return
363
354
  print("chat 服务启动")
364
355
  data = "payload=" + json.dumps({"text": title + "\n" + content})
@@ -376,7 +367,6 @@ def pushplus_bot(title: str, content: str) -> None:
376
367
  通过 pushplus 推送消息。
377
368
  """
378
369
  if not push_config.get("PUSH_PLUS_TOKEN"):
379
- print("PUSHPLUS 服务的 PUSH_PLUS_TOKEN 未设置!!\n取消推送")
380
370
  return
381
371
  print("PUSHPLUS 服务启动")
382
372
 
@@ -390,7 +380,7 @@ def pushplus_bot(title: str, content: str) -> None:
390
380
  "channel": push_config.get("PUSH_PLUS_CHANNEL"),
391
381
  "webhook": push_config.get("PUSH_PLUS_WEBHOOK"),
392
382
  "callbackUrl": push_config.get("PUSH_PLUS_CALLBACKURL"),
393
- "to": push_config.get("PUSH_PLUS_TO")
383
+ "to": push_config.get("PUSH_PLUS_TO"),
394
384
  }
395
385
  body = json.dumps(data).encode(encoding="utf-8")
396
386
  headers = {"Content-Type": "application/json"}
@@ -398,9 +388,11 @@ def pushplus_bot(title: str, content: str) -> None:
398
388
 
399
389
  code = response["code"]
400
390
  if code == 200:
401
- print("PUSHPLUS 推送请求成功,可根据流水号查询推送结果:"+ response["data"])
402
- print("注意:请求成功并不代表推送成功,如未收到消息,请到pushplus官网使用流水号查询推送最终结果")
403
- elif code == 900 or code == 903 or code == 905 or code == 999 :
391
+ print("PUSHPLUS 推送请求成功,可根据流水号查询推送结果:" + response["data"])
392
+ print(
393
+ "注意:请求成功并不代表推送成功,如未收到消息,请到pushplus官网使用流水号查询推送最终结果"
394
+ )
395
+ elif code == 900 or code == 903 or code == 905 or code == 999:
404
396
  print(response["msg"])
405
397
 
406
398
  else:
@@ -420,7 +412,6 @@ def weplus_bot(title: str, content: str) -> None:
420
412
  通过 微加机器人 推送消息。
421
413
  """
422
414
  if not push_config.get("WE_PLUS_BOT_TOKEN"):
423
- print("微加机器人 服务的 WE_PLUS_BOT_TOKEN 未设置!!\n取消推送")
424
415
  return
425
416
  print("微加机器人 服务启动")
426
417
 
@@ -452,7 +443,6 @@ def qmsg_bot(title: str, content: str) -> None:
452
443
  使用 qmsg 推送消息。
453
444
  """
454
445
  if not push_config.get("QMSG_KEY") or not push_config.get("QMSG_TYPE"):
455
- print("qmsg 的 QMSG_KEY 或者 QMSG_TYPE 未设置!!\n取消推送")
456
446
  return
457
447
  print("qmsg 服务启动")
458
448
 
@@ -471,11 +461,10 @@ def wecom_app(title: str, content: str) -> None:
471
461
  通过 企业微信 APP 推送消息。
472
462
  """
473
463
  if not push_config.get("QYWX_AM"):
474
- print("QYWX_AM 未设置!!\n取消推送")
475
464
  return
476
465
  QYWX_AM_AY = re.split(",", push_config.get("QYWX_AM"))
477
466
  if 4 < len(QYWX_AM_AY) > 5:
478
- print("QYWX_AM 设置错误!!\n取消推送")
467
+ print("QYWX_AM 设置错误!!")
479
468
  return
480
469
  print("企业微信 APP 服务启动")
481
470
 
@@ -568,7 +557,6 @@ def wecom_bot(title: str, content: str) -> None:
568
557
  通过 企业微信机器人 推送消息。
569
558
  """
570
559
  if not push_config.get("QYWX_KEY"):
571
- print("企业微信机器人 服务的 QYWX_KEY 未设置!!\n取消推送")
572
560
  return
573
561
  print("企业微信机器人服务启动")
574
562
 
@@ -594,7 +582,6 @@ def telegram_bot(title: str, content: str) -> None:
594
582
  使用 telegram 机器人 推送消息。
595
583
  """
596
584
  if not push_config.get("TG_BOT_TOKEN") or not push_config.get("TG_USER_ID"):
597
- print("tg 服务的 bot_token 或者 user_id 未设置!!\n取消推送")
598
585
  return
599
586
  print("tg 服务启动")
600
587
 
@@ -643,9 +630,6 @@ def aibotk(title: str, content: str) -> None:
643
630
  or not push_config.get("AIBOTK_TYPE")
644
631
  or not push_config.get("AIBOTK_NAME")
645
632
  ):
646
- print(
647
- "智能微秘书 的 AIBOTK_KEY 或者 AIBOTK_TYPE 或者 AIBOTK_NAME 未设置!!\n取消推送"
648
- )
649
633
  return
650
634
  print("智能微秘书 服务启动")
651
635
 
@@ -684,9 +668,6 @@ def smtp(title: str, content: str) -> None:
684
668
  or not push_config.get("SMTP_PASSWORD")
685
669
  or not push_config.get("SMTP_NAME")
686
670
  ):
687
- print(
688
- "SMTP 邮件 的 SMTP_SERVER 或者 SMTP_SSL 或者 SMTP_EMAIL 或者 SMTP_PASSWORD 或者 SMTP_NAME 未设置!!\n取消推送"
689
- )
690
671
  return
691
672
  print("SMTP 邮件 服务启动")
692
673
 
@@ -730,7 +711,6 @@ def pushme(title: str, content: str) -> None:
730
711
  使用 PushMe 推送消息。
731
712
  """
732
713
  if not push_config.get("PUSHME_KEY"):
733
- print("PushMe 服务的 PUSHME_KEY 未设置!!\n取消推送")
734
714
  return
735
715
  print("PushMe 服务启动")
736
716
 
@@ -763,7 +743,6 @@ def chronocat(title: str, content: str) -> None:
763
743
  or not push_config.get("CHRONOCAT_QQ")
764
744
  or not push_config.get("CHRONOCAT_TOKEN")
765
745
  ):
766
- print("CHRONOCAT 服务的 CHRONOCAT_URL 或 CHRONOCAT_QQ 未设置!!\n取消推送")
767
746
  return
768
747
 
769
748
  print("CHRONOCAT 服务启动")
@@ -807,31 +786,28 @@ def ntfy(title: str, content: str) -> None:
807
786
  """
808
787
  通过 Ntfy 推送消息
809
788
  """
789
+
810
790
  def encode_rfc2047(text: str) -> str:
811
791
  """将文本编码为符合 RFC 2047 标准的格式"""
812
- encoded_bytes = base64.b64encode(text.encode('utf-8'))
813
- encoded_str = encoded_bytes.decode('utf-8')
814
- return f'=?utf-8?B?{encoded_str}?='
792
+ encoded_bytes = base64.b64encode(text.encode("utf-8"))
793
+ encoded_str = encoded_bytes.decode("utf-8")
794
+ return f"=?utf-8?B?{encoded_str}?="
815
795
 
816
796
  if not push_config.get("NTFY_TOPIC"):
817
- print("ntfy 服务的 NTFY_TOPIC 未设置!!\n取消推送")
818
797
  return
819
798
  print("ntfy 服务启动")
820
- priority = '3'
799
+ priority = "3"
821
800
  if not push_config.get("NTFY_PRIORITY"):
822
801
  print("ntfy 服务的NTFY_PRIORITY 未设置!!默认设置为3")
823
802
  else:
824
803
  priority = push_config.get("NTFY_PRIORITY")
825
-
804
+
826
805
  # 使用 RFC 2047 编码 title
827
806
  encoded_title = encode_rfc2047(title)
828
807
 
829
- data = content.encode(encoding='utf-8')
830
- headers = {
831
- "Title": encoded_title, # 使用编码后的 title
832
- "Priority": priority
833
- }
834
-
808
+ data = content.encode(encoding="utf-8")
809
+ headers = {"Title": encoded_title, "Priority": priority} # 使用编码后的 title
810
+
835
811
  url = push_config.get("NTFY_URL") + "/" + push_config.get("NTFY_TOPIC")
836
812
  response = requests.post(url, data=data, headers=headers)
837
813
  if response.status_code == 200: # 使用 response.status_code 进行检查
@@ -849,24 +825,30 @@ def wxpusher_bot(title: str, content: str) -> None:
849
825
  - WXPUSHER_UIDS: 用户ID, 多个用英文分号;分隔
850
826
  """
851
827
  if not push_config.get("WXPUSHER_APP_TOKEN"):
852
- print("wxpusher 服务的 WXPUSHER_APP_TOKEN 未设置!!\n取消推送")
853
828
  return
854
-
855
829
 
856
830
  url = "https://wxpusher.zjiecode.com/api/send/message"
857
-
831
+
858
832
  # 处理topic_ids和uids,将分号分隔的字符串转为数组
859
833
  topic_ids = []
860
834
  if push_config.get("WXPUSHER_TOPIC_IDS"):
861
- topic_ids = [int(id.strip()) for id in push_config.get("WXPUSHER_TOPIC_IDS").split(";") if id.strip()]
862
-
835
+ topic_ids = [
836
+ int(id.strip())
837
+ for id in push_config.get("WXPUSHER_TOPIC_IDS").split(";")
838
+ if id.strip()
839
+ ]
840
+
863
841
  uids = []
864
842
  if push_config.get("WXPUSHER_UIDS"):
865
- uids = [uid.strip() for uid in push_config.get("WXPUSHER_UIDS").split(";") if uid.strip()]
843
+ uids = [
844
+ uid.strip()
845
+ for uid in push_config.get("WXPUSHER_UIDS").split(";")
846
+ if uid.strip()
847
+ ]
866
848
 
867
849
  # topic_ids uids 至少有一个
868
850
  if not topic_ids and not uids:
869
- print("wxpusher 服务的 WXPUSHER_TOPIC_IDS 和 WXPUSHER_UIDS 至少设置一个!!\n取消推送")
851
+ print("wxpusher 服务的 WXPUSHER_TOPIC_IDS 和 WXPUSHER_UIDS 至少设置一个!!")
870
852
  return
871
853
 
872
854
  print("wxpusher 服务启动")
@@ -878,9 +860,9 @@ def wxpusher_bot(title: str, content: str) -> None:
878
860
  "contentType": 2,
879
861
  "topicIds": topic_ids,
880
862
  "uids": uids,
881
- "verifyPayType": 0
863
+ "verifyPayType": 0,
882
864
  }
883
-
865
+
884
866
  headers = {"Content-Type": "application/json"}
885
867
  response = requests.post(url=url, json=data, headers=headers).json()
886
868
 
@@ -946,7 +928,6 @@ def custom_notify(title: str, content: str) -> None:
946
928
  通过 自定义通知 推送消息。
947
929
  """
948
930
  if not push_config.get("WEBHOOK_URL") or not push_config.get("WEBHOOK_METHOD"):
949
- print("自定义通知的 WEBHOOK_URL 或 WEBHOOK_METHOD 未设置!!\n取消推送")
950
931
  return
951
932
 
952
933
  print("自定义通知服务启动")
@@ -1052,7 +1033,9 @@ def add_notify_function():
1052
1033
  notify_function.append(custom_notify)
1053
1034
  if push_config.get("NTFY_TOPIC"):
1054
1035
  notify_function.append(ntfy)
1055
- if push_config.get("WXPUSHER_APP_TOKEN") and (push_config.get("WXPUSHER_TOPIC_IDS") or push_config.get("WXPUSHER_UIDS")):
1036
+ if push_config.get("WXPUSHER_APP_TOKEN") and (
1037
+ push_config.get("WXPUSHER_TOPIC_IDS") or push_config.get("WXPUSHER_UIDS")
1038
+ ):
1056
1039
  notify_function.append(wxpusher_bot)
1057
1040
  if not notify_function:
1058
1041
  print(f"无推送渠道,请检查通知变量是否正确")
@@ -1095,4 +1078,4 @@ def main():
1095
1078
 
1096
1079
 
1097
1080
  if __name__ == "__main__":
1098
- main()
1081
+ main()
package/shell/api.sh CHANGED
@@ -231,4 +231,30 @@ find_cron_api() {
231
231
  fi
232
232
  }
233
233
 
234
+ update_auth_config() {
235
+ local body="$1"
236
+ local tip="$2"
237
+ local currentTimeStamp=$(date +%s)
238
+ local api=$(
239
+ curl -s --noproxy "*" "http://0.0.0.0:5600/open/system/auth/reset?t=$currentTimeStamp" \
240
+ -X 'PUT' \
241
+ -H "Accept: application/json" \
242
+ -H "Authorization: Bearer ${__ql_token__}" \
243
+ -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36" \
244
+ -H "Content-Type: application/json;charset=UTF-8" \
245
+ -H "Origin: http://0.0.0.0:5700" \
246
+ -H "Referer: http://0.0.0.0:5700/crontab" \
247
+ -H "Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7" \
248
+ --data-raw "{$body}" \
249
+ --compressed
250
+ )
251
+ code=$(echo "$api" | jq -r .code)
252
+ message=$(echo "$api" | jq -r .message)
253
+ if [[ $code == 200 ]]; then
254
+ echo -e "${tip}成功🎉"
255
+ else
256
+ echo -e "${tip}失败(${message})"
257
+ fi
258
+ }
259
+
234
260
  get_token
@@ -56,7 +56,9 @@ function run() {
56
56
  for (const key in newEnvObject) {
57
57
  process.env[key] = newEnvObject[key];
58
58
  }
59
- console.log(output);
59
+ if (output) {
60
+ console.log(output);
61
+ }
60
62
  if (task_before) {
61
63
  console.log('执行前置命令结束\n');
62
64
  }
@@ -89,6 +91,10 @@ try {
89
91
  return;
90
92
  }
91
93
 
94
+ process.on('SIGTERM', (code) => {
95
+ process.exit(15);
96
+ });
97
+
92
98
  run();
93
99
 
94
100
  const { sendNotify } = require('./notify.js');
@@ -5,6 +5,7 @@ import json
5
5
  import builtins
6
6
  import sys
7
7
  import env
8
+ import signal
8
9
 
9
10
 
10
11
  def try_parse_int(value):
@@ -63,7 +64,8 @@ def run():
63
64
  for key, value in env_json.items():
64
65
  os.environ[key] = value
65
66
 
66
- print(output)
67
+ if len(output) > 0:
68
+ print(output)
67
69
  if task_before:
68
70
  print("执行前置命令结束")
69
71
 
@@ -95,7 +97,13 @@ def run():
95
97
  os.environ[env_param] = env_str
96
98
 
97
99
 
100
+ def handle_sigterm(signum, frame):
101
+ sys.exit(15)
102
+
103
+
98
104
  try:
105
+ signal.signal(signal.SIGTERM, handle_sigterm)
106
+
99
107
  run()
100
108
 
101
109
  from notify import send
package/shell/share.sh CHANGED
@@ -193,12 +193,6 @@ fix_config() {
193
193
  echo
194
194
  fi
195
195
 
196
- if [[ ! -s $file_auth_user ]]; then
197
- echo -e "复制一份 $file_auth_sample 为 $file_auth_user\n"
198
- cp -fv $file_auth_sample $file_auth_user
199
- echo
200
- fi
201
-
202
196
  if [[ ! -s $file_notify_py ]]; then
203
197
  echo -e "复制一份 $file_notify_py_sample 为 $file_notify_py\n"
204
198
  cp -fv $file_notify_py_sample $file_notify_py
@@ -473,10 +467,12 @@ handle_task_end() {
473
467
  local end_time=$(format_time "$time_format" "$etime")
474
468
  local end_timestamp=$(format_timestamp "$time_format" "$etime")
475
469
  local diff_time=$(($end_timestamp - $begin_timestamp))
470
+ local suffix=""
471
+ [[ "$MANUAL" == "true" ]] && suffix="(手动停止)"
476
472
 
477
473
  [[ "$diff_time" == 0 ]] && diff_time=1
478
474
 
479
- echo -e "\n## 执行结束... $end_time 耗时 $diff_time 秒     "
475
+ echo -e "\n## 执行结束$suffix... $end_time 耗时 $diff_time 秒     "
480
476
  [[ $ID ]] && update_cron "\"$ID\"" "1" "" "$log_path" "$begin_timestamp" "$diff_time"
481
477
  }
482
478
 
package/shell/task.sh CHANGED
@@ -6,7 +6,7 @@ dir_shell=$QL_DIR/shell
6
6
 
7
7
  trap "single_hanle" 2 3 20 15 14 19 1
8
8
  single_hanle() {
9
- eval handle_task_end "$@" "$cmd"
9
+ eval MANUAL=true handle_task_end "$@" "$cmd"
10
10
  exit 1
11
11
  }
12
12
 
package/shell/update.sh CHANGED
@@ -537,14 +537,10 @@ main() {
537
537
  eval . $dir_shell/check.sh $cmd
538
538
  ;;
539
539
  resetlet)
540
- auth_value=$(cat $file_auth_user | jq '.retries =0' -c)
541
- echo "$auth_value" >$file_auth_user
542
- eval echo -e "重置登录错误次数成功" $cmd
540
+ eval update_auth_config "\\\"retries\\\":0" "重置登录错误次数" $cmd
543
541
  ;;
544
542
  resettfa)
545
- auth_value=$(cat $file_auth_user | jq '.twoFactorActivated =false' | jq '.twoFactorActived =false' -c)
546
- echo "$auth_value" >$file_auth_user
547
- eval echo -e "禁用两步验证成功" $cmd
543
+ eval update_auth_config "\\\"twoFactorActivated\\\":false" "禁用两步验证" $cmd
548
544
  ;;
549
545
  *)
550
546
  eval echo -e "命令输入错误...\\\n" $cmd
@@ -34,6 +34,7 @@ const celebrate_1 = require("celebrate");
34
34
  const path_1 = require("path");
35
35
  const const_1 = require("../config/const");
36
36
  const config_2 = __importDefault(require("../services/config"));
37
+ const utils_1 = require("../shared/utils");
37
38
  const route = (0, express_1.Router)();
38
39
  exports.default = (app) => {
39
40
  app.use('/configs', route);
@@ -90,7 +91,7 @@ exports.default = (app) => {
90
91
  if (name.startsWith('data/scripts/')) {
91
92
  path = (0, path_1.join)(config_1.default.rootPath, name);
92
93
  }
93
- await fs.writeFile(path, content);
94
+ await (0, utils_1.writeFileWithLock)(path, content);
94
95
  res.send({ code: 200, message: '保存成功' });
95
96
  }
96
97
  catch (e) {