@whyour/qinglong 2.17.9 → 2.17.10-rc.2

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 (99) hide show
  1. package/docker/310.Dockerfile +4 -3
  2. package/docker/Dockerfile +5 -4
  3. package/package.json +7 -5
  4. package/sample/config.sample.sh +8 -0
  5. package/sample/notify.js +1 -1
  6. package/shell/api.sh +9 -9
  7. package/shell/otask.sh +19 -3
  8. package/shell/preload/sitecustomize.js +23 -12
  9. package/shell/preload/sitecustomize.py +17 -15
  10. package/shell/rmlog.sh +20 -18
  11. package/shell/share.sh +3 -3
  12. package/shell/start.sh +2 -1
  13. package/shell/task.sh +6 -8
  14. package/static/build/api/subscription.js +3 -3
  15. package/static/build/api/system.js +18 -2
  16. package/static/build/app.js +1 -1
  17. package/static/build/config/index.js +2 -0
  18. package/static/build/config/util.js +1 -1
  19. package/static/build/loaders/express.js +1 -1
  20. package/static/build/loaders/initData.js +6 -0
  21. package/static/build/loaders/initTask.js +4 -7
  22. package/static/build/loaders/sentry.js +20 -22
  23. package/static/build/loaders/sock.js +0 -4
  24. package/static/build/public.js +0 -1
  25. package/static/build/schedule/addCron.js +3 -3
  26. package/static/build/services/cron.js +4 -1
  27. package/static/build/services/notify.js +20 -8
  28. package/static/build/services/schedule.js +33 -8
  29. package/static/build/services/script.js +3 -1
  30. package/static/build/services/subscription.js +7 -4
  31. package/static/build/services/system.js +29 -5
  32. package/static/build/services/user.js +4 -1
  33. package/static/build/shared/interface.js +3 -0
  34. package/static/build/shared/pLimit.js +48 -1
  35. package/static/build/shared/runCron.js +6 -4
  36. package/static/dist/{2393.c35a1174.async.js → 2393.3d8adf53.async.js} +1 -1
  37. package/static/dist/2796.9a52d80e.async.js +1 -0
  38. package/static/dist/2899.03668225.async.js +1 -0
  39. package/static/dist/4039.badd6267.async.js +1 -0
  40. package/static/dist/{4124.b86154ed.async.js → 4124.980265f2.async.js} +1 -1
  41. package/static/dist/{4163.1781a549.async.js → 4163.17026fe1.async.js} +1 -1
  42. package/static/dist/4645.d909733e.async.js +1 -0
  43. package/static/dist/641.f0614d96.async.js +1 -0
  44. package/static/dist/6712.05e15d48.async.js +1 -0
  45. package/static/dist/6805.ae3d4019.async.js +1 -0
  46. package/static/dist/{7393.341d9643.async.js → 7393.ea2d5ba3.async.js} +1 -1
  47. package/static/dist/7787.b041d555.async.js +1 -0
  48. package/static/dist/8298.978b54ae.async.js +1 -0
  49. package/static/dist/9631.042017c3.async.js +1 -0
  50. package/static/dist/index.html +1 -1
  51. package/static/dist/layouts__index.2f94d49c.async.js +1 -0
  52. package/static/dist/layouts__index.fee54067.chunk.css +1 -0
  53. package/static/dist/src__pages__crontab__detail.34c9ca68.async.js +1 -0
  54. package/static/dist/src__pages__crontab__index.7d67660b.async.js +1 -0
  55. package/static/dist/src__pages__crontab__modal.ac728c12.async.js +1 -0
  56. package/static/dist/src__pages__crontab__viewCreateModal.1fe0e251.async.js +1 -0
  57. package/static/dist/src__pages__crontab__viewManageModal.c6dcfcf8.async.js +1 -0
  58. package/static/dist/src__pages__dependence__index.f30d6cf9.async.js +1 -0
  59. package/static/dist/src__pages__dependence__logModal.4826a923.async.js +1 -0
  60. package/static/dist/src__pages__error__index.e5c6d102.async.js +1 -0
  61. package/static/dist/src__pages__script__editModal.be12c9e5.async.js +1 -0
  62. package/static/dist/src__pages__script__index.6afda14d.async.js +1 -0
  63. package/static/dist/src__pages__setting__about.d7cea886.async.js +1 -0
  64. package/static/dist/src__pages__setting__checkUpdate.0dd2f8d5.async.js +1 -0
  65. package/static/dist/src__pages__setting__index.d9ba61cd.async.js +1 -0
  66. package/static/dist/src__pages__setting__loginLog.2f5ce1e4.async.js +1 -0
  67. package/static/dist/src__pages__setting__progress.57907231.async.js +1 -0
  68. package/static/dist/{src__pages__setting__security.b5ead1c3.async.js → src__pages__setting__security.cbf8e0b7.async.js} +1 -1
  69. package/static/dist/src__pages__setting__systemLog.1b30b79c.async.js +1 -0
  70. package/static/dist/src__pages__subscription__logModal.5bf23b06.async.js +1 -0
  71. package/static/dist/umi.3f48f15a.js +1 -0
  72. package/version.yaml +10 -6
  73. package/static/dist/4378.59be202f.async.js +0 -1
  74. package/static/dist/5207.4d5f0a6d.async.js +0 -1
  75. package/static/dist/7708.27674f3a.async.js +0 -1
  76. package/static/dist/7787.2fcf966f.async.js +0 -1
  77. package/static/dist/8297.0c80e09a.async.js +0 -1
  78. package/static/dist/8722.408e3112.async.js +0 -1
  79. package/static/dist/9525.b2007159.async.js +0 -1
  80. package/static/dist/layouts__index.308c5e5e.chunk.css +0 -1
  81. package/static/dist/layouts__index.a51b2768.async.js +0 -1
  82. package/static/dist/src__pages__crontab__detail.f691fe2e.async.js +0 -1
  83. package/static/dist/src__pages__crontab__index.06bb5925.async.js +0 -1
  84. package/static/dist/src__pages__crontab__modal.2fc5acc5.async.js +0 -1
  85. package/static/dist/src__pages__crontab__viewCreateModal.a29322e7.async.js +0 -1
  86. package/static/dist/src__pages__crontab__viewManageModal.c026d403.async.js +0 -1
  87. package/static/dist/src__pages__dependence__index.52fca7ba.async.js +0 -1
  88. package/static/dist/src__pages__dependence__logModal.39bc29eb.async.js +0 -1
  89. package/static/dist/src__pages__error__index.8ca01b97.async.js +0 -1
  90. package/static/dist/src__pages__script__editModal.3a322b87.async.js +0 -1
  91. package/static/dist/src__pages__script__index.8c311439.async.js +0 -1
  92. package/static/dist/src__pages__setting__about.40dce429.async.js +0 -1
  93. package/static/dist/src__pages__setting__checkUpdate.43e62d05.async.js +0 -1
  94. package/static/dist/src__pages__setting__index.d655075d.async.js +0 -1
  95. package/static/dist/src__pages__setting__loginLog.fe7238b5.async.js +0 -1
  96. package/static/dist/src__pages__setting__progress.7d65aebf.async.js +0 -1
  97. package/static/dist/src__pages__setting__systemLog.751cc94d.async.js +0 -1
  98. package/static/dist/src__pages__subscription__logModal.fce8a9b4.async.js +0 -1
  99. package/static/dist/umi.5e777fc4.js +0 -1
@@ -1,6 +1,6 @@
1
- FROM node:20-slim as nodebuilder
1
+ FROM node:20-slim AS nodebuilder
2
2
 
3
- FROM python:3.10-slim-bullseye as builder
3
+ FROM python:3.10-slim-bullseye AS builder
4
4
  COPY package.json .npmrc pnpm-lock.yaml /tmp/build/
5
5
  COPY --from=nodebuilder /usr/local/bin/node /usr/local/bin/
6
6
  COPY --from=nodebuilder /usr/local/lib/node_modules/. /usr/local/lib/node_modules/
@@ -59,7 +59,8 @@ RUN set -x && \
59
59
  rm -rf /root/.local/share/pnpm/store && \
60
60
  rm -rf /root/.cache && \
61
61
  rm -rf /root/.npm && \
62
- ulimit -c 0
62
+ ulimit -c 0 && \
63
+ pip3 install requests
63
64
 
64
65
  ARG SOURCE_COMMIT
65
66
  RUN git clone --depth=1 -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} && \
package/docker/Dockerfile CHANGED
@@ -1,6 +1,6 @@
1
- FROM node:20-slim as nodebuilder
1
+ FROM node:20-slim AS nodebuilder
2
2
 
3
- FROM python:3.11-slim-bullseye as builder
3
+ FROM python:3.11-slim-bullseye AS builder
4
4
  COPY package.json .npmrc pnpm-lock.yaml /tmp/build/
5
5
  COPY --from=nodebuilder /usr/local/bin/node /usr/local/bin/
6
6
  COPY --from=nodebuilder /usr/local/lib/node_modules/. /usr/local/lib/node_modules/
@@ -20,7 +20,7 @@ ARG QL_URL=https://github.com/${QL_MAINTAINER}/qinglong.git
20
20
  ARG QL_BRANCH=develop
21
21
 
22
22
  ENV PNPM_HOME=/root/.local/share/pnpm \
23
- PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.local/share/pnpm:/root/.local/share/pnpm/global/5/node_modules:$PNPM_HOME \
23
+ PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.local/share/pnpm:/root/.local/share/pnpm/global/5/node_modules \
24
24
  NODE_PATH=/usr/local/bin:/usr/local/pnpm-global/5/node_modules:/usr/local/lib/node_modules:/root/.local/share/pnpm/global/5/node_modules \
25
25
  LANG=C.UTF-8 \
26
26
  SHELL=/bin/bash \
@@ -60,7 +60,8 @@ RUN set -x && \
60
60
  rm -rf /root/.local/share/pnpm/store && \
61
61
  rm -rf /root/.cache && \
62
62
  rm -rf /root/.npm && \
63
- ulimit -c 0
63
+ ulimit -c 0 && \
64
+ pip3 install requests
64
65
 
65
66
  ARG SOURCE_COMMIT
66
67
  RUN git clone --depth=1 -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} && \
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whyour/qinglong",
3
- "version": "2.17.9",
3
+ "version": "2.17.10-rc.2",
4
4
  "description": "Timed task management platform supporting Python3, JavaScript, Shell, Typescript",
5
5
  "repository": {
6
6
  "type": "git",
@@ -13,11 +13,11 @@
13
13
  },
14
14
  "scripts": {
15
15
  "start": "concurrently -n w: npm:start:*",
16
- "start:front": "max dev",
17
- "start:back": "nodemon",
18
16
  "start:update": "ts-node -P tsconfig.back.json ./back/update.ts",
19
17
  "start:public": "ts-node -P tsconfig.back.json ./back/public.ts",
20
18
  "start:rpc": "ts-node -P tsconfig.back.json ./back/schedule/index.ts",
19
+ "start:back": "nodemon",
20
+ "start:front": "max dev",
21
21
  "build:front": "max build",
22
22
  "build:back": "tsc -p tsconfig.back.json",
23
23
  "panel": "npm run build:back && node static/build/app.js",
@@ -75,7 +75,7 @@
75
75
  "dependencies": {
76
76
  "@grpc/grpc-js": "^1.8.13",
77
77
  "@otplib/preset-default": "^12.0.1",
78
- "@sentry/node": "^7.12.1",
78
+ "@sentry/node": "^8.26.0",
79
79
  "body-parser": "^1.19.2",
80
80
  "celebrate": "^15.0.1",
81
81
  "chokidar": "^3.5.3",
@@ -119,11 +119,13 @@
119
119
  "ip2region": "2.3.0"
120
120
  },
121
121
  "devDependencies": {
122
+ "moment": "2.30.1",
122
123
  "@ant-design/icons": "^4.7.0",
123
124
  "@ant-design/pro-layout": "6.38.22",
124
125
  "@monaco-editor/react": "4.2.1",
125
126
  "@react-hook/resize-observer": "^1.2.6",
126
- "@sentry/react": "^7.12.1",
127
+ "react-router-dom": "6.26.1",
128
+ "@sentry/react": "^8.26.0",
127
129
  "@types/body-parser": "^1.19.2",
128
130
  "@types/cors": "^2.8.12",
129
131
  "@types/cross-spawn": "^6.0.2",
@@ -175,8 +175,16 @@ export CHRONOCAT_QQ=""
175
175
  export CHRONOCAT_TOKEN=""
176
176
 
177
177
  ## 16. SMTP
178
+ ## JavaScript 参数
178
179
  ## 邮箱服务名称,比如126、163、Gmail、QQ等,支持列表 https://github.com/nodemailer/nodemailer/blob/master/lib/well-known/services.json
179
180
  export SMTP_SERVICE=""
181
+
182
+ ## Python 参数
183
+ ## SMTP 发送邮件服务器,形如 smtp.exmail.qq.com:465
184
+ export SMTP_SERVER=""
185
+ ## SMTP 发送邮件服务器是否使用 SSL,填写 true 或 false
186
+ export SMTP_SSL=""
187
+
180
188
  ## smtp_email 填写 SMTP 收发件邮箱,通知将会由自己发给自己
181
189
  export SMTP_EMAIL=""
182
190
  ## smtp_password 填写 SMTP 登录密码,也可能为特殊口令,视具体邮件服务商说明而定
package/sample/notify.js CHANGED
@@ -817,7 +817,7 @@ function wePlusBotNotify(text, desp) {
817
817
  const { WE_PLUS_BOT_TOKEN, WE_PLUS_BOT_RECEIVER, WE_PLUS_BOT_VERSION } =
818
818
  push_config;
819
819
  if (WE_PLUS_BOT_TOKEN) {
820
- const template = 'txt';
820
+ let template = 'txt';
821
821
  if (desp.length > 800) {
822
822
  desp = desp.replace(/[\n\r]/g, '<br>');
823
823
  template = 'html';
package/shell/api.sh CHANGED
@@ -6,12 +6,12 @@ create_token() {
6
6
  if [[ -f $token_file ]]; then
7
7
  token_command="node ${token_file}"
8
8
  fi
9
- token=$(eval "$token_command")
9
+ __ql_token__=$(eval "$token_command")
10
10
  }
11
11
 
12
12
  get_token() {
13
13
  if [[ -f $file_auth_token ]]; then
14
- token=$(cat $file_auth_token | jq -r .value)
14
+ __ql_token__=$(cat $file_auth_token | jq -r .value)
15
15
  local expiration=$(cat $file_auth_token | jq -r .expiration)
16
16
  local currentTimeStamp=$(date +%s)
17
17
  if [[ $currentTimeStamp -ge $expiration ]]; then
@@ -43,7 +43,7 @@ add_cron_api() {
43
43
  local api=$(
44
44
  curl -s --noproxy "*" "http://0.0.0.0:5600/open/crons?t=$currentTimeStamp" \
45
45
  -H "Accept: application/json" \
46
- -H "Authorization: Bearer $token" \
46
+ -H "Authorization: Bearer ${__ql_token__}" \
47
47
  -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" \
48
48
  -H "Content-Type: application/json;charset=UTF-8" \
49
49
  -H "Origin: http://0.0.0.0:5700" \
@@ -79,7 +79,7 @@ update_cron_api() {
79
79
  curl -s --noproxy "*" "http://0.0.0.0:5600/open/crons?t=$currentTimeStamp" \
80
80
  -X 'PUT' \
81
81
  -H "Accept: application/json" \
82
- -H "Authorization: Bearer $token" \
82
+ -H "Authorization: Bearer ${__ql_token__}" \
83
83
  -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" \
84
84
  -H "Content-Type: application/json;charset=UTF-8" \
85
85
  -H "Origin: http://0.0.0.0:5700" \
@@ -111,7 +111,7 @@ update_cron_command_api() {
111
111
  curl -s --noproxy "*" "http://0.0.0.0:5600/open/crons?t=$currentTimeStamp" \
112
112
  -X 'PUT' \
113
113
  -H "Accept: application/json" \
114
- -H "Authorization: Bearer $token" \
114
+ -H "Authorization: Bearer ${__ql_token__}" \
115
115
  -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" \
116
116
  -H "Content-Type: application/json;charset=UTF-8" \
117
117
  -H "Origin: http://0.0.0.0:5700" \
@@ -136,7 +136,7 @@ del_cron_api() {
136
136
  curl -s --noproxy "*" "http://0.0.0.0:5600/open/crons?t=$currentTimeStamp" \
137
137
  -X 'DELETE' \
138
138
  -H "Accept: application/json" \
139
- -H "Authorization: Bearer $token" \
139
+ -H "Authorization: Bearer ${__ql_token__}" \
140
140
  -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" \
141
141
  -H "Content-Type: application/json;charset=UTF-8" \
142
142
  -H "Origin: http://0.0.0.0:5700" \
@@ -166,7 +166,7 @@ update_cron() {
166
166
  curl -s --noproxy "*" "http://0.0.0.0:5600/open/crons/status?t=$currentTimeStamp" \
167
167
  -X 'PUT' \
168
168
  -H "Accept: application/json" \
169
- -H "Authorization: Bearer $token" \
169
+ -H "Authorization: Bearer ${__ql_token__}" \
170
170
  -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" \
171
171
  -H "Content-Type: application/json;charset=UTF-8" \
172
172
  -H "Origin: http://0.0.0.0:5700" \
@@ -190,7 +190,7 @@ notify_api() {
190
190
  curl -s --noproxy "*" "http://0.0.0.0:5600/open/system/notify?t=$currentTimeStamp" \
191
191
  -X 'PUT' \
192
192
  -H "Accept: application/json" \
193
- -H "Authorization: Bearer $token" \
193
+ -H "Authorization: Bearer ${__ql_token__}" \
194
194
  -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" \
195
195
  -H "Content-Type: application/json;charset=UTF-8" \
196
196
  -H "Origin: http://0.0.0.0:5700" \
@@ -214,7 +214,7 @@ find_cron_api() {
214
214
  local api=$(
215
215
  curl -s --noproxy "*" "http://0.0.0.0:5600/open/crons/detail?$params&t=$currentTimeStamp" \
216
216
  -H "Accept: application/json" \
217
- -H "Authorization: Bearer $token" \
217
+ -H "Authorization: Bearer ${__ql_token__}" \
218
218
  -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" \
219
219
  -H "Content-Type: application/json;charset=UTF-8" \
220
220
  -H "Origin: http://0.0.0.0:5700" \
package/shell/otask.sh CHANGED
@@ -210,14 +210,19 @@ run_else() {
210
210
 
211
211
  check_file() {
212
212
  isJsOrPythonFile="false"
213
- if [[ $1 == *.js ]] || [[ $1 == *.py ]] || [[ $1 == *.pyc ]] || [[ $1 == *.ts ]]; then
213
+ if [[ $1 == *.js ]] || [[ $1 == *.mjs ]] || [[ $1 == *.py ]] || [[ $1 == *.pyc ]] || [[ $1 == *.ts ]]; then
214
214
  isJsOrPythonFile="true"
215
215
  fi
216
216
  if [[ -f $file_env ]]; then
217
217
  get_env_array
218
218
  if [[ $isJsOrPythonFile == 'true' ]]; then
219
- export NODE_OPTIONS="${NODE_OPTIONS} -r ${file_preload_js}"
220
- export PYTHONPATH="${PYTHONPATH}:${dir_preload}:${dir_config}"
219
+ PREV_NODE_OPTIONS="${NODE_OPTIONS:=}"
220
+ PREV_PYTHONPATH="${PYTHONPATH:=}"
221
+ if [[ $1 == *.js ]] || [[ $1 == *.ts ]] || [[ $1 == *.mjs ]]; then
222
+ export NODE_OPTIONS="${NODE_OPTIONS} -r ${file_preload_js}"
223
+ else
224
+ export PYTHONPATH="${PYTHONPATH}:${dir_preload}:${dir_config}"
225
+ fi
221
226
  else
222
227
  . $file_env
223
228
  fi
@@ -264,7 +269,18 @@ check_file "${task_shell_params[@]}"
264
269
  if [[ $isJsOrPythonFile == 'false' ]]; then
265
270
  run_task_before "${task_shell_params[@]}"
266
271
  fi
272
+ if set -o | grep -q 'nounset.*on'; then
273
+ set_u_on="true"
274
+ set +u
275
+ fi
267
276
  main "${task_shell_params[@]}"
277
+ if [[ "$set_u_on" == 'true' ]]; then
278
+ set -u
279
+ fi
280
+ if [[ $isJsOrPythonFile == 'true' ]]; then
281
+ export NODE_OPTIONS="${PREV_NODE_OPTIONS}"
282
+ export PYTHONPATH="${PREV_PYTHONPATH}"
283
+ fi
268
284
  run_task_after "${task_shell_params[@]}"
269
285
  clear_env
270
286
  handle_task_end "${task_shell_params[@]}"
@@ -1,13 +1,5 @@
1
1
  const { execSync } = require('child_process');
2
- const { sendNotify } = require('./notify.js');
3
2
  require(`./env.js`);
4
-
5
- function initGlobal() {
6
- global.QLAPI = {
7
- notify: sendNotify,
8
- };
9
- }
10
-
11
3
  function expandRange(rangeStr, max) {
12
4
  const tempRangeStr = rangeStr
13
5
  .trim()
@@ -18,7 +10,11 @@ function expandRange(rangeStr, max) {
18
10
  const rangeMatch = part.match(/^(\d+)([-~_])(\d+)$/);
19
11
  if (rangeMatch) {
20
12
  const [, start, , end] = rangeMatch.map(Number);
21
- return Array.from({ length: end - start + 1 }, (_, i) => start + i);
13
+ const step = start < end ? 1 : -1;
14
+ return Array.from(
15
+ { length: Math.abs(end - start) + 1 },
16
+ (_, i) => start + i * step,
17
+ );
22
18
  }
23
19
  return Number(part);
24
20
  });
@@ -41,10 +37,14 @@ function run() {
41
37
  const fileName = process.argv[1].replace(`${dir_scripts}/`, '');
42
38
  let command = `bash -c "source ${file_task_before} ${fileName}`;
43
39
  if (task_before) {
44
- command = `${command} && echo -e '执行前置命令\n' && eval "${task_before}" && echo -e '\n执行前置命令结束\n'`;
40
+ const escapeTaskBefore = task_before
41
+ .replace(/"/g, '\\"')
42
+ .replace(/\$/g, '\\$');
43
+ command = `${command} && eval '${escapeTaskBefore}'`;
44
+ console.log('执行前置命令\n');
45
45
  }
46
46
  const res = execSync(
47
- `${command} && echo "${splitStr}" && NODE_OPTIONS= node -p 'JSON.stringify(process.env)'"`,
47
+ `${command} && echo -e '${splitStr}' && NODE_OPTIONS= node -p 'JSON.stringify(process.env)'"`,
48
48
  {
49
49
  encoding: 'utf-8',
50
50
  },
@@ -55,6 +55,9 @@ function run() {
55
55
  process.env[key] = newEnvObject[key];
56
56
  }
57
57
  console.log(output);
58
+ if (task_before) {
59
+ console.log('执行前置命令结束\n');
60
+ }
58
61
  } catch (error) {
59
62
  if (!error.message.includes('spawnSync /bin/sh E2BIG')) {
60
63
  console.log(`run task before error: `, error);
@@ -71,8 +74,16 @@ function run() {
71
74
  }
72
75
 
73
76
  try {
74
- initGlobal();
77
+ if (!process.argv[1]) {
78
+ return;
79
+ }
80
+
75
81
  run();
82
+
83
+ const { sendNotify } = require('./notify.js');
84
+ global.QLAPI = {
85
+ notify: sendNotify,
86
+ };
76
87
  } catch (error) {
77
88
  console.log(`run builtin code error: `, error, '\n');
78
89
  }
@@ -5,17 +5,6 @@ import json
5
5
  import builtins
6
6
  import sys
7
7
  import env
8
- from notify import send
9
-
10
-
11
- class BaseApi:
12
- def notify(self, *args, **kwargs):
13
- return send(*args, **kwargs)
14
-
15
-
16
- def init_global():
17
- QLAPI = BaseApi()
18
- builtins.QLAPI = QLAPI
19
8
 
20
9
 
21
10
  def try_parse_int(value):
@@ -37,7 +26,8 @@ def expand_range(range_str, max_value):
37
26
  range_match = re.match(r"^(\d+)([-~_])(\d+)$", part)
38
27
  if range_match:
39
28
  start, _, end = map(try_parse_int, range_match.groups())
40
- result.extend(range(start, end + 1))
29
+ step = 1 if start < end else -1
30
+ result.extend(range(start, end + step, step))
41
31
  else:
42
32
  result.append(int(part))
43
33
 
@@ -54,10 +44,12 @@ def run():
54
44
  task_before = os.getenv("task_before")
55
45
 
56
46
  if task_before:
57
- command += f" && echo -e '执行前置命令\n' && eval \"{task_before}\" && echo -e '\n执行前置命令结束\n'"
47
+ escape_task_before = task_before.replace('"', '\\"').replace("$", "\\$")
48
+ command += f" && eval '{escape_task_before}'"
49
+ print("执行前置命令\n")
58
50
 
59
51
  python_command = "PYTHONPATH= python3 -c 'import os, json; print(json.dumps(dict(os.environ)))'"
60
- command += f' && echo "{split_str}" && {python_command}"'
52
+ command += f" && echo -e '{split_str}' && {python_command}\""
61
53
 
62
54
  res = subprocess.check_output(command, shell=True, encoding="utf-8")
63
55
  output, env_str = res.split(split_str)
@@ -68,6 +60,8 @@ def run():
68
60
  os.environ[key] = value
69
61
 
70
62
  print(output)
63
+ if task_before:
64
+ print("执行前置命令结束")
71
65
 
72
66
  except subprocess.CalledProcessError as error:
73
67
  print(f"run task before error: {error}")
@@ -90,7 +84,15 @@ def run():
90
84
 
91
85
 
92
86
  try:
93
- init_global()
94
87
  run()
88
+
89
+ from notify import send
90
+
91
+ class BaseApi:
92
+ def notify(self, *args, **kwargs):
93
+ return send(*args, **kwargs)
94
+
95
+ QLAPI = BaseApi()
96
+ builtins.QLAPI = QLAPI
95
97
  except Exception as error:
96
98
  print(f"run builtin code error: {error}\n")
package/shell/rmlog.sh CHANGED
@@ -2,34 +2,37 @@
2
2
 
3
3
  days=$1
4
4
 
5
- ## 删除运行脚本的旧日志
6
5
  remove_js_log() {
7
- local log_full_path_list=$(find $dir_log/ -name "*.log")
6
+ local log_full_path_list=$(find $dir_log -name "*.log")
8
7
  local diff_time
9
8
  for log in $log_full_path_list; do
10
- local log_date=$(echo $log | awk -F "/" '{print $NF}' | cut -c1-10) #文件名比文件属性获得的日期要可靠
11
- if [[ $(date +%s -d $log_date 2>/dev/null) ]]; then
9
+ local log_date=$(echo $log | awk -F "/" '{print $NF}' | cut -c1-10)
10
+ if ! [[ $log_date =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
12
11
  if [[ $is_macos -eq 1 ]]; then
13
- diff_time=$(($(date +%s) - $(date -j -f "%Y-%m-%d" "$log_date" +%s)))
12
+ log_date=$(stat -f %Sm -t "%Y-%m-%d" "$log")
14
13
  else
15
- diff_time=$(($(date +%s) - $(date +%s -d "$log_date")))
14
+ log_date=$(stat -c %y "$log" | cut -d ' ' -f 1)
16
15
  fi
17
- if [[ $diff_time -gt $((${days} * 86400)) ]]; then
18
- local log_path=$(echo "$log" | sed "s,${dir_log}/,,g")
19
- local result=$(find_cron_api "log_path=$log_path")
20
- echo -e "查询文件 $log_path"
21
- if [[ -z $result ]]; then
22
- echo -e "删除中~"
23
- rm -vf $log
24
- else
25
- echo -e "正在被 $result 使用,跳过~"
26
- fi
16
+ fi
17
+ if [[ $is_macos -eq 1 ]]; then
18
+ diff_time=$(($(date +%s) - $(date -j -f "%Y-%m-%d" "$log_date" +%s)))
19
+ else
20
+ diff_time=$(($(date +%s) - $(date +%s -d "$log_date")))
21
+ fi
22
+ if [[ $diff_time -gt $((${days} * 86400)) ]]; then
23
+ local log_path=$(echo "$log" | sed "s,${dir_log}/,,g")
24
+ local result=$(find_cron_api "log_path=$log_path")
25
+ echo -e "查询文件 $log_path"
26
+ if [[ -z $result ]]; then
27
+ echo -e "删除中~"
28
+ rm -vf $log
29
+ else
30
+ echo -e "正在被 $result 使用,跳过~"
27
31
  fi
28
32
  fi
29
33
  done
30
34
  }
31
35
 
32
- ## 删除空文件夹
33
36
  remove_empty_dir() {
34
37
  cd $dir_log
35
38
  for dir in $(ls); do
@@ -39,7 +42,6 @@ remove_empty_dir() {
39
42
  done
40
43
  }
41
44
 
42
- ## 运行
43
45
  if [[ ${days} ]]; then
44
46
  echo -e "查找旧日志文件中...\n"
45
47
  remove_js_log
package/shell/share.sh CHANGED
@@ -5,7 +5,7 @@ export dir_root=$QL_DIR
5
5
  export dir_tmp=$dir_root/.tmp
6
6
  export dir_data=$dir_root/data
7
7
 
8
- if [[ $QL_DATA_DIR ]]; then
8
+ if [[ ${QL_DATA_DIR:=} ]]; then
9
9
  export dir_data="${QL_DATA_DIR%/}"
10
10
  fi
11
11
 
@@ -84,7 +84,7 @@ import_config() {
84
84
  command_timeout_time=${CommandTimeoutTime:-""}
85
85
  file_extensions=${RepoFileExtensions:-"js py"}
86
86
  proxy_url=${ProxyUrl:-""}
87
- current_branch=${QL_BRANCH}
87
+ current_branch=${QL_BRANCH:-""}
88
88
 
89
89
  if [[ -n "${DefaultCronRule}" ]]; then
90
90
  default_cron="${DefaultCronRule}"
@@ -461,7 +461,7 @@ run_task_before() {
461
461
  run_task_after() {
462
462
  . $file_task_after "$@"
463
463
 
464
- if [[ $task_after ]]; then
464
+ if [[ ${task_after:=} ]]; then
465
465
  echo -e "\n执行后置命令\n"
466
466
  eval "$task_after" "$@"
467
467
  echo -e "\n执行后置命令结束"
package/shell/start.sh CHANGED
@@ -67,10 +67,11 @@ cd ${QL_DIR}
67
67
  cp -f .env.example .env
68
68
  chmod 777 ${QL_DIR}/shell/*.sh
69
69
 
70
- . ${QL_DIR}/shell/env.sh
71
70
  . ${QL_DIR}/shell/share.sh
71
+ . ${QL_DIR}/shell/env.sh
72
72
 
73
73
  echo -e "======================1. 检测配置文件========================\n"
74
+ import_config "$@"
74
75
  make_dir /etc/nginx/conf.d
75
76
  make_dir /run/nginx
76
77
  init_nginx
package/shell/task.sh CHANGED
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env bash
2
2
 
3
- ## 导入通用变量与函数
4
3
  dir_shell=$QL_DIR/shell
5
4
  . $dir_shell/share.sh
6
5
  . $dir_shell/api.sh
@@ -11,7 +10,6 @@ single_hanle() {
11
10
  exit 1
12
11
  }
13
12
 
14
- ## 选择python3还是node
15
13
  define_program() {
16
14
  local file_param=$1
17
15
  if [[ $file_param == *.js ]] || [[ $file_param == *.mjs ]]; then
@@ -34,7 +32,7 @@ handle_log_path() {
34
32
  file_param="task"
35
33
  fi
36
34
 
37
- if [[ -z $ID ]]; then
35
+ if [[ -z ${ID:=} ]]; then
38
36
  ID=$(cat $list_crontab_user | grep -E "$cmd_task.* $file_param" | perl -pe "s|.*ID=(.*) $cmd_task.* $file_param\.*|\1|" | head -1 | awk -F " " '{print $1}')
39
37
  fi
40
38
  local suffix=""
@@ -62,17 +60,17 @@ handle_log_path() {
62
60
  log_dir="${log_dir_tmp%.*}${suffix}"
63
61
  log_path="$log_dir/$log_time.log"
64
62
 
65
- if [[ $real_log_path ]]; then
63
+ if [[ ${real_log_path:=} ]]; then
66
64
  log_path="$real_log_path"
67
65
  fi
68
66
 
69
67
  cmd="2>&1 | tee -a $dir_log/$log_path"
70
68
  make_dir "$dir_log/$log_dir"
71
- if [[ "$no_tee" == "true" ]]; then
69
+ if [[ "${no_tee:=}" == "true" ]]; then
72
70
  cmd=">> $dir_log/$log_path 2>&1"
73
71
  fi
74
72
 
75
- if [[ "$real_time" == "true" ]]; then
73
+ if [[ "${real_time:=}" == "true" ]]; then
76
74
  cmd=""
77
75
  fi
78
76
  }
@@ -124,8 +122,8 @@ while getopts ":lm:" opt; do
124
122
  ;;
125
123
  esac
126
124
  done
127
- [[ $show_log ]] && shift $(($OPTIND - 1))
128
- if [[ $max_time ]]; then
125
+ [[ ${show_log:=} ]] && shift $(($OPTIND - 1))
126
+ if [[ ${max_time:=} ]]; then
129
127
  shift $(($OPTIND - 1))
130
128
  command_timeout_time="$max_time"
131
129
  fi
@@ -15,7 +15,7 @@ exports.default = (app) => {
15
15
  const logger = typedi_1.Container.get('logger');
16
16
  try {
17
17
  const subscriptionService = typedi_1.Container.get(subscription_1.default);
18
- const data = await subscriptionService.list(req.query.searchValue);
18
+ const data = await subscriptionService.list(req.query.searchValue, req.query.ids);
19
19
  return res.send({ code: 200, data });
20
20
  }
21
21
  catch (e) {
@@ -180,8 +180,8 @@ exports.default = (app) => {
180
180
  body: celebrate_1.Joi.array().items(celebrate_1.Joi.number().required()),
181
181
  query: celebrate_1.Joi.object({
182
182
  force: celebrate_1.Joi.boolean().optional(),
183
- t: celebrate_1.Joi.number()
184
- })
183
+ t: celebrate_1.Joi.number(),
184
+ }),
185
185
  }), async (req, res, next) => {
186
186
  const logger = typedi_1.Container.get('logger');
187
187
  try {
@@ -296,10 +296,26 @@ exports.default = (app) => {
296
296
  return next(e);
297
297
  }
298
298
  });
299
- route.get('/log', async (req, res, next) => {
299
+ route.get('/log', (0, celebrate_1.celebrate)({
300
+ query: {
301
+ startTime: celebrate_1.Joi.string().allow('').optional(),
302
+ endTime: celebrate_1.Joi.string().allow('').optional(),
303
+ t: celebrate_1.Joi.string().optional(),
304
+ },
305
+ }), async (req, res, next) => {
306
+ try {
307
+ const systemService = typedi_1.Container.get(system_1.default);
308
+ await systemService.getSystemLog(res, req.query);
309
+ }
310
+ catch (e) {
311
+ return next(e);
312
+ }
313
+ });
314
+ route.delete('/log', async (req, res, next) => {
300
315
  try {
301
316
  const systemService = typedi_1.Container.get(system_1.default);
302
- await systemService.getSystemLog(res);
317
+ await systemService.deleteSystemLog();
318
+ res.send({ code: 200 });
303
319
  }
304
320
  catch (e) {
305
321
  return next(e);
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ require("./loaders/sentry");
6
7
  require("reflect-metadata"); // We need this in order to use @Decorators
7
8
  const config_1 = __importDefault(require("./config"));
8
9
  const express_1 = __importDefault(require("express"));
@@ -11,7 +12,6 @@ async function startServer() {
11
12
  const app = (0, express_1.default)();
12
13
  await require('./loaders/db').default();
13
14
  await require('./loaders/initFile').default();
14
- await require('./loaders/sentry').default({ expressApp: app });
15
15
  await require('./loaders/app').default({ expressApp: app });
16
16
  const server = app
17
17
  .listen(config_1.default.port, '0.0.0.0', () => {
@@ -47,6 +47,7 @@ const extraFile = path_1.default.join(configPath, 'extra.sh');
47
47
  const confBakDir = path_1.default.join(dataPath, 'config/bak/');
48
48
  const sampleFile = path_1.default.join(samplePath, 'config.sample.sh');
49
49
  const sqliteFile = path_1.default.join(samplePath, 'database.sqlite');
50
+ const systemNotifyFile = path_1.default.join(preloadPath, 'system-notify.json');
50
51
  const authError = '错误的用户名密码,请重试';
51
52
  const loginFaild = '请先登录!';
52
53
  const configString = 'config sample crontab shareCode diy';
@@ -126,5 +127,6 @@ exports.default = {
126
127
  sqliteFile,
127
128
  sshdPath,
128
129
  systemLogPath,
130
+ systemNotifyFile,
129
131
  };
130
132
  //# sourceMappingURL=index.js.map
@@ -431,7 +431,7 @@ async function parseVersion(path) {
431
431
  return (0, js_yaml_1.load)(await fs.readFile(path, 'utf8'));
432
432
  }
433
433
  exports.parseVersion = parseVersion;
434
- async function parseContentVersion(content) {
434
+ function parseContentVersion(content) {
435
435
  return (0, js_yaml_1.load)(content);
436
436
  }
437
437
  exports.parseContentVersion = parseContentVersion;
@@ -135,6 +135,7 @@ exports.default = ({ app }) => {
135
135
  next(err);
136
136
  });
137
137
  app.use((0, celebrate_1.errors)());
138
+ Sentry.setupExpressErrorHandler(app);
138
139
  app.use((err, req, res, next) => {
139
140
  if (err.name === 'UnauthorizedError') {
140
141
  return res
@@ -158,7 +159,6 @@ exports.default = ({ app }) => {
158
159
  return next(err);
159
160
  });
160
161
  app.use((err, req, res, next) => {
161
- Sentry.captureException(err);
162
162
  res.status(err.status || 500);
163
163
  res.json({
164
164
  code: err.status || 500,