@whyour/qinglong 0.16.0 → 0.18.0

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 (58) hide show
  1. package/.env.example +1 -0
  2. package/docker/310.Dockerfile +4 -0
  3. package/docker/docker-entrypoint.sh +1 -0
  4. package/docker/front.conf +16 -0
  5. package/other.config.js +13 -0
  6. package/package.json +4 -4
  7. package/sample/config.sample.sh +19 -8
  8. package/sample/notify.js +19 -16
  9. package/sample/notify.py +32 -29
  10. package/sample/test.js +8 -0
  11. package/sample/test.py +8 -0
  12. package/shell/check.sh +1 -0
  13. package/shell/share.sh +27 -1
  14. package/shell/update.sh +34 -22
  15. package/static/build/api/script.js +1 -1
  16. package/static/build/config/index.js +1 -0
  17. package/static/build/config/util.js +9 -8
  18. package/static/build/loaders/server.js +0 -21
  19. package/static/build/loaders/update.js +79 -0
  20. package/static/build/services/cron.js +1 -1
  21. package/static/build/services/notify.js +5 -14
  22. package/static/build/services/subscription.js +1 -1
  23. package/static/build/services/system.js +17 -32
  24. package/static/build/update.js +29 -0
  25. package/static/dist/{833.c59c5023.async.js → 833.ea0fd669.async.js} +1 -1
  26. package/static/dist/index.html +1 -1
  27. package/static/dist/{src__pages__crontab__detail.2ab4f3e8.async.js → src__pages__crontab__detail.a2bfd72a.async.js} +1 -1
  28. package/static/dist/src__pages__crontab__index.98d464c0.async.js +1 -0
  29. package/static/dist/src__pages__log__index.e7377c48.async.js +1 -0
  30. package/static/dist/src__pages__script__editNameModal.3eabdcdb.async.js +1 -0
  31. package/static/dist/src__pages__script__index.8d14185b.async.js +1 -0
  32. package/static/dist/src__pages__setting__checkUpdate.43e62d05.async.js +1 -0
  33. package/static/dist/src__pages__setting__dependence.28193e94.async.js +1 -0
  34. package/static/dist/src__pages__setting__index.7ab054fb.async.js +1 -0
  35. package/static/dist/src__pages__setting__other.2c4534ef.async.js +1 -0
  36. package/static/dist/src__pages__setting__progress.7d65aebf.async.js +1 -0
  37. package/static/dist/{umi.cbe4d7e7.js → umi.11c81ea6.js} +1 -1
  38. package/version.yaml +10 -6
  39. package/static/build/data/cron.js +0 -69
  40. package/static/build/data/cronView.js +0 -39
  41. package/static/build/data/dependence.js +0 -70
  42. package/static/build/data/env.js +0 -38
  43. package/static/build/data/index.js +0 -27
  44. package/static/build/data/notify.js +0 -183
  45. package/static/build/data/open.js +0 -23
  46. package/static/build/data/sock.js +0 -12
  47. package/static/build/data/subscription.js +0 -82
  48. package/static/build/data/system.js +0 -36
  49. package/static/dist/8008.89ba3d06.async.js +0 -1
  50. package/static/dist/src__pages__crontab__index.f4269e9c.async.js +0 -1
  51. package/static/dist/src__pages__log__index.44c6a008.async.js +0 -1
  52. package/static/dist/src__pages__script__editNameModal.55a6bcbb.async.js +0 -1
  53. package/static/dist/src__pages__script__index.364b93d9.async.js +0 -1
  54. package/static/dist/src__pages__setting__checkUpdate.42020a45.async.js +0 -1
  55. package/static/dist/src__pages__setting__dependence.2efb8ee3.async.js +0 -1
  56. package/static/dist/src__pages__setting__index.3e2ad723.async.js +0 -1
  57. package/static/dist/src__pages__setting__other.a029d99a.async.js +0 -1
  58. package/static/dist/src__pages__setting__progress.65e2e878.async.js +0 -1
package/.env.example CHANGED
@@ -1,3 +1,4 @@
1
+ UPDATE_PORT=5300
1
2
  PUBLIC_PORT=5400
2
3
  CRON_PORT=5500
3
4
  BACK_PORT=5600
@@ -80,3 +80,7 @@ HEALTHCHECK --interval=5s --timeout=2s --retries=20 \
80
80
  CMD curl -sf --noproxy '*' http://127.0.0.1:5400/api/health || exit 1
81
81
 
82
82
  ENTRYPOINT ["./docker/docker-entrypoint.sh"]
83
+
84
+ VOLUME /ql/data
85
+
86
+ EXPOSE 5700
@@ -21,6 +21,7 @@ nginx -s reload 2>/dev/null || nginx -c /etc/nginx/nginx.conf
21
21
  echo -e "nginx启动成功...\n"
22
22
 
23
23
  echo -e "======================4. 启动pm2服务========================\n"
24
+ reload_update
24
25
  reload_pm2
25
26
 
26
27
  if [[ $AutoStartBot == true ]]; then
package/docker/front.conf CHANGED
@@ -6,6 +6,10 @@ upstream publicApi {
6
6
  server 0.0.0.0:5400;
7
7
  }
8
8
 
9
+ upstream updateApi {
10
+ server 0.0.0.0:5300;
11
+ }
12
+
9
13
  map $http_upgrade $connection_upgrade {
10
14
  default keep-alive;
11
15
  'websocket' upgrade;
@@ -16,6 +20,18 @@ server {
16
20
  IPV6_CONFIG
17
21
  ssl_session_timeout 5m;
18
22
 
23
+ location QL_BASE_URLapi/update/ {
24
+ proxy_set_header Host $http_host;
25
+ proxy_set_header X-Real-IP $remote_addr;
26
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
27
+ proxy_pass http://updateApi/api/;
28
+ proxy_buffering off;
29
+ proxy_redirect default;
30
+ proxy_connect_timeout 1800;
31
+ proxy_send_timeout 1800;
32
+ proxy_read_timeout 1800;
33
+ }
34
+
19
35
  location QL_BASE_URLapi/public/ {
20
36
  proxy_set_header Host $http_host;
21
37
  proxy_set_header X-Real-IP $remote_addr;
@@ -0,0 +1,13 @@
1
+ module.exports = {
2
+ apps: [
3
+ {
4
+ name: 'update',
5
+ max_restarts: 10,
6
+ kill_timeout: 15000,
7
+ wait_ready: true,
8
+ listen_timeout: 10000,
9
+ time: true,
10
+ script: 'static/build/update.js',
11
+ },
12
+ ],
13
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whyour/qinglong",
3
- "version": "0.16.0",
3
+ "version": "0.18.0",
4
4
  "description": "Timed task management platform supporting Python3, JavaScript, Shell, Typescript",
5
5
  "repository": {
6
6
  "type": "git",
@@ -15,6 +15,7 @@
15
15
  "start": "concurrently -n w: npm:start:*",
16
16
  "start:front": "max dev",
17
17
  "start:back": "nodemon",
18
+ "start:update": "ts-node -P tsconfig.back.json ./back/update.ts",
18
19
  "start:public": "ts-node -P tsconfig.back.json ./back/public.ts",
19
20
  "start:rpc": "ts-node -P tsconfig.back.json ./back/schedule/index.ts",
20
21
  "build:front": "max build",
@@ -22,6 +23,7 @@
22
23
  "panel": "npm run build:back && node static/build/app.js",
23
24
  "schedule": "npm run build:back && node static/build/schedule/index.js",
24
25
  "public": "npm run build:back && node static/build/public.js",
26
+ "update": "npm run build:back && node static/build/update.js",
25
27
  "gen:proto": "protoc --experimental_allow_proto3_optional --plugin=./node_modules/.bin/protoc-gen-ts_proto ./back/protos/*.proto --ts_proto_out=./ --ts_proto_opt=outputServices=grpc-js,env=node,esModuleInterop=true",
26
28
  "prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
27
29
  "postinstall": "max setup 2>/dev/null || true",
@@ -106,7 +108,6 @@
106
108
  "serve-handler": "^6.1.3",
107
109
  "sockjs": "^0.3.24",
108
110
  "sqlite3": "git+https://github.com/whyour/node-sqlite3.git#v1.0.3",
109
- "tar": "^6.1.15",
110
111
  "toad-scheduler": "^1.6.0",
111
112
  "typedi": "^0.10.0",
112
113
  "uuid": "^8.3.2",
@@ -144,7 +145,6 @@
144
145
  "@types/serve-handler": "^6.1.1",
145
146
  "@types/sockjs": "^0.3.33",
146
147
  "@types/sockjs-client": "^1.5.1",
147
- "@types/tar": "^6.1.5",
148
148
  "@types/uuid": "^8.3.4",
149
149
  "@types/request-ip": "0.0.41",
150
150
  "@uiw/codemirror-extensions-langs": "^4.21.9",
@@ -182,7 +182,7 @@
182
182
  "ts-node": "^10.6.0",
183
183
  "ts-proto": "^1.146.0",
184
184
  "tslib": "^2.4.0",
185
- "tsx": "^3.12.3",
185
+ "tsx": "^4.7.3",
186
186
  "typescript": "5.2.2",
187
187
  "vh-check": "^2.0.5",
188
188
  "virtualizedtableforantd4": "1.3.0",
@@ -148,6 +148,15 @@ export AIBOTK_TYPE=""
148
148
  ## aibotk_name (必填)填写群名或用户昵称,和上面的type类型要对应
149
149
  export AIBOTK_NAME=""
150
150
 
151
+ ## 13. CHRONOCAT
152
+ ## CHRONOCAT_URL 推送 http://127.0.0.1:16530
153
+ ## CHRONOCAT_TOKEN 填写在CHRONOCAT文件生成的访问密钥
154
+ ## CHRONOCAT_QQ 个人:user_id=个人QQ 群则填入group_id=QQ群 多个用英文;隔开同时支持个人和群 如:user_id=xxx;group_id=xxxx;group_id=xxxxx
155
+ ## CHRONOCAT相关API https://chronocat.vercel.app/install/docker/official/
156
+ export CHRONOCAT_URL=""
157
+ export CHRONOCAT_QQ=""
158
+ export CHRONOCAT_TOKEN=""
159
+
151
160
  ## 14. SMTP
152
161
  ## 邮箱服务名称,比如126、163、Gmail、QQ等,支持列表 https://github.com/nodemailer/nodemailer/blob/master/lib/well-known/services.json
153
162
  export SMTP_SERVICE=""
@@ -163,13 +172,15 @@ export SMTP_NAME=""
163
172
  ## PUSHME_KEY (必填)填写PushMe APP上获取的push_key
164
173
  export PUSHME_KEY=""
165
174
 
166
- ## 13. CHRONOCAT
167
- ## CHRONOCAT_URL 推送 http://127.0.0.1:16530
168
- ## CHRONOCAT_TOKEN 填写在CHRONOCAT文件生成的访问密钥
169
- ## CHRONOCAT_QQ 个人:user_id=个人QQ 群则填入group_id=QQ群 多个用英文;隔开同时支持个人和群 如:user_id=xxx;group_id=xxxx;group_id=xxxxx
170
- ## CHRONOCAT相关API https://chronocat.vercel.app/install/docker/official/
171
- export CHRONOCAT_URL=""
172
- export CHRONOCAT_QQ=""
173
- export CHRONOCAT_TOKEN=""
175
+ ## 15. 自定义通知
176
+ ## 自定义通知 接收回调的URL
177
+ export WEBHOOK_URL=""
178
+ ## WEBHOOK_BODY WEBHOOK_HEADERS 多个参数时,直接换行或者使用 $'\n' 连接多行字符串,比如 export dd="line 1"$'\n'"line 2"
179
+ export WEBHOOK_BODY=""
180
+ export WEBHOOK_HEADERS=""
181
+ ## 支持 GET/POST/PUT
182
+ export WEBHOOK_METHOD=""
183
+ ## 支持 text/plain、application/json、multipart/form-data、application/x-www-form-urlencoded
184
+ export WEBHOOK_CONTENT_TYPE=""
174
185
 
175
186
  ## 其他需要的变量,脚本中需要的变量使用 export 变量名= 声明即可
package/sample/notify.js CHANGED
@@ -819,11 +819,11 @@ function ChangeUserId(desp) {
819
819
  async function qywxamNotify(text, desp) {
820
820
  const MAX_LENGTH = 900;
821
821
  if (desp.length > MAX_LENGTH) {
822
- let d = desp.substr(0, MAX_LENGTH) + "\n==More==";
822
+ let d = desp.substr(0, MAX_LENGTH) + '\n==More==';
823
823
  await do_qywxamNotify(text, d);
824
824
  await qywxamNotify(text, desp.substr(MAX_LENGTH));
825
825
  } else {
826
- return await do_qywxamNotify(text,desp);
826
+ return await do_qywxamNotify(text, desp);
827
827
  }
828
828
  }
829
829
 
@@ -1121,7 +1121,7 @@ function fsBotNotify(text, desp) {
1121
1121
  console.log(err);
1122
1122
  } else {
1123
1123
  data = JSON.parse(data);
1124
- if (data.StatusCode === 0) {
1124
+ if (data.StatusCode === 0 || data.code === 0) {
1125
1125
  console.log('飞书发送通知消息成功🎉\n');
1126
1126
  } else {
1127
1127
  console.log(`${data.msg}\n`);
@@ -1284,18 +1284,15 @@ function chronocatNotify(title, desp) {
1284
1284
 
1285
1285
  function webhookNotify(text, desp) {
1286
1286
  return new Promise((resolve) => {
1287
- const { formatBody, formatUrl } = formatNotifyContentFun(
1288
- WEBHOOK_URL,
1289
- WEBHOOK_BODY,
1290
- text,
1291
- desp,
1292
- );
1293
- if (!formatUrl && !formatBody) {
1287
+ if (!WEBHOOK_URL.includes('$title') && !WEBHOOK_BODY.includes('$title')) {
1294
1288
  resolve();
1295
1289
  return;
1296
1290
  }
1291
+
1297
1292
  const headers = parseHeaders(WEBHOOK_HEADERS);
1298
- const body = parseBody(formatBody, WEBHOOK_CONTENT_TYPE);
1293
+ const body = parseBody(WEBHOOK_BODY, WEBHOOK_CONTENT_TYPE, (v) =>
1294
+ v?.replaceAll('$title', text)?.replaceAll('$content', desp),
1295
+ );
1299
1296
  const bodyParam = formatBodyFun(WEBHOOK_CONTENT_TYPE, body);
1300
1297
  const options = {
1301
1298
  method: WEBHOOK_METHOD,
@@ -1307,6 +1304,10 @@ function webhookNotify(text, desp) {
1307
1304
  };
1308
1305
 
1309
1306
  if (WEBHOOK_METHOD) {
1307
+ const formatUrl = WEBHOOK_URL.replaceAll(
1308
+ '$title',
1309
+ encodeURIComponent(text),
1310
+ ).replaceAll('$content', encodeURIComponent(desp));
1310
1311
  got(formatUrl, options).then((resp) => {
1311
1312
  try {
1312
1313
  if (resp.statusCode !== 200) {
@@ -1326,7 +1327,7 @@ function webhookNotify(text, desp) {
1326
1327
  });
1327
1328
  }
1328
1329
 
1329
- function parseString(input) {
1330
+ function parseString(input, valueFormatFn) {
1330
1331
  const regex = /(\w+):\s*((?:(?!\n\w+:).)*)/g;
1331
1332
  const matches = {};
1332
1333
 
@@ -1338,9 +1339,10 @@ function parseString(input) {
1338
1339
  continue;
1339
1340
  }
1340
1341
 
1341
- const _value = value.trim();
1342
+ let _value = value.trim();
1342
1343
 
1343
1344
  try {
1345
+ _value = valueFormatFn ? valueFormatFn(_value) : _value;
1344
1346
  const jsonValue = JSON.parse(_value);
1345
1347
  matches[_key] = jsonValue;
1346
1348
  } catch (error) {
@@ -1375,12 +1377,12 @@ function parseHeaders(headers) {
1375
1377
  return parsed;
1376
1378
  }
1377
1379
 
1378
- function parseBody(body, contentType) {
1380
+ function parseBody(body, contentType, valueFormatFn) {
1379
1381
  if (contentType === 'text/plain' || !body) {
1380
- return body;
1382
+ return valueFormatFn && body ? valueFormatFn(body) : body;
1381
1383
  }
1382
1384
 
1383
- const parsed = parseString(body);
1385
+ const parsed = parseString(body, valueFormatFn);
1384
1386
 
1385
1387
  switch (contentType) {
1386
1388
  case 'multipart/form-data':
@@ -1405,6 +1407,7 @@ function formatBodyFun(contentType, body) {
1405
1407
  case 'multipart/form-data':
1406
1408
  return { form: body };
1407
1409
  case 'application/x-www-form-urlencoded':
1410
+ case 'text/plain':
1408
1411
  return { body };
1409
1412
  }
1410
1413
  return {};
package/sample/notify.py CHANGED
@@ -113,7 +113,6 @@ push_config = {
113
113
  'WEBHOOK_METHOD': '', # 自定义通知 请求方法
114
114
  'WEBHOOK_CONTENT_TYPE': '' # 自定义通知 content-type
115
115
  }
116
- notify_function = []
117
116
  # fmt: on
118
117
 
119
118
  # 首先读取 面板变量 或者 github action 运行变量
@@ -214,7 +213,7 @@ def feishu_bot(title: str, content: str) -> None:
214
213
  data = {"msg_type": "text", "content": {"text": f"{title}\n\n{content}"}}
215
214
  response = requests.post(url, data=json.dumps(data)).json()
216
215
 
217
- if response.get("StatusCode") == 0:
216
+ if response.get("StatusCode") == 0 or response.get("code") == 0:
218
217
  print("飞书 推送成功!")
219
218
  else:
220
219
  print("飞书 推送失败!错误信息如下:\n", response)
@@ -750,13 +749,14 @@ def parse_headers(headers):
750
749
  return parsed
751
750
 
752
751
 
753
- def parse_string(input_string):
752
+ def parse_string(input_string, value_format_fn=None):
754
753
  matches = {}
755
- pattern = r'(\w+):\s*((?:(?!\n\w+:).)*)'
754
+ pattern = r"(\w+):\s*((?:(?!\n\w+:).)*)"
756
755
  regex = re.compile(pattern)
757
756
  for match in regex.finditer(input_string):
758
757
  key, value = match.group(1).strip(), match.group(2).strip()
759
758
  try:
759
+ value = value_format_fn(value) if value_format_fn else value
760
760
  json_value = json.loads(value)
761
761
  matches[key] = json_value
762
762
  except:
@@ -764,14 +764,14 @@ def parse_string(input_string):
764
764
  return matches
765
765
 
766
766
 
767
- def parse_body(body, content_type):
767
+ def parse_body(body, content_type, value_format_fn=None):
768
768
  if not body or content_type == "text/plain":
769
- return body
769
+ return value_format_fn(body) if value_format_fn and body else body
770
770
 
771
- parsed = parse_string(input_string)
771
+ parsed = parse_string(body, value_format_fn)
772
772
 
773
773
  if content_type == "application/x-www-form-urlencoded":
774
- data = urlencode(parsed, doseq=True)
774
+ data = urllib.parse.urlencode(parsed, doseq=True)
775
775
  return data
776
776
 
777
777
  if content_type == "application/json":
@@ -781,18 +781,6 @@ def parse_body(body, content_type):
781
781
  return parsed
782
782
 
783
783
 
784
- def format_notify_content(url, body, title, content):
785
- if "$title" not in url and "$title" not in body:
786
- return {}
787
-
788
- formatted_url = url.replace("$title", urllib.parse.quote_plus(title)).replace(
789
- "$content", urllib.parse.quote_plus(content)
790
- )
791
- formatted_body = body.replace("$title", title).replace("$content", content)
792
-
793
- return formatted_url, formatted_body
794
-
795
-
796
784
  def custom_notify(title: str, content: str) -> None:
797
785
  """
798
786
  通过 自定义通知 推送消息。
@@ -809,18 +797,21 @@ def custom_notify(title: str, content: str) -> None:
809
797
  WEBHOOK_BODY = push_config.get("WEBHOOK_BODY")
810
798
  WEBHOOK_HEADERS = push_config.get("WEBHOOK_HEADERS")
811
799
 
812
- formatUrl, formatBody = format_notify_content(
813
- WEBHOOK_URL, WEBHOOK_BODY, title, content
814
- )
815
-
816
- if not formatUrl and not formatBody:
800
+ if "$title" not in WEBHOOK_URL and "$title" not in WEBHOOK_BODY:
817
801
  print("请求头或者请求体中必须包含 $title 和 $content")
818
802
  return
819
803
 
820
804
  headers = parse_headers(WEBHOOK_HEADERS)
821
- body = parse_body(formatBody, WEBHOOK_CONTENT_TYPE)
805
+ body = parse_body(
806
+ WEBHOOK_BODY,
807
+ WEBHOOK_CONTENT_TYPE,
808
+ lambda v: v.replace("$title", title).replace("$content", content),
809
+ )
810
+ formatted_url = WEBHOOK_URL.replace(
811
+ "$title", urllib.parse.quote_plus(title)
812
+ ).replace("$content", urllib.parse.quote_plus(content))
822
813
  response = requests.request(
823
- method=WEBHOOK_METHOD, url=formatUrl, headers=headers, timeout=15, data=body
814
+ method=WEBHOOK_METHOD, url=formatted_url, headers=headers, timeout=15, data=body
824
815
  )
825
816
 
826
817
  if response.status_code == 200:
@@ -840,6 +831,7 @@ def one() -> str:
840
831
 
841
832
 
842
833
  def add_notify_function():
834
+ notify_function = []
843
835
  if push_config.get("BARK_PUSH"):
844
836
  notify_function.append(bark)
845
837
  if push_config.get("CONSOLE"):
@@ -895,8 +887,19 @@ def add_notify_function():
895
887
  if push_config.get("WEBHOOK_URL") and push_config.get("WEBHOOK_METHOD"):
896
888
  notify_function.append(custom_notify)
897
889
 
890
+ if not notify_function:
891
+ print(f"无推送渠道,请检查通知变量是否正确")
892
+ return notify_function
893
+
894
+
895
+ def send(title: str, content: str, ignore_default_config: bool = False, **kwargs):
896
+ if kwargs:
897
+ global push_config
898
+ if ignore_default_config:
899
+ push_config = kwargs # 清空从环境变量获取的配置
900
+ else:
901
+ push_config.update(kwargs)
898
902
 
899
- def send(title: str, content: str) -> None:
900
903
  if not content:
901
904
  print(f"{title} 推送内容为空!")
902
905
  return
@@ -911,7 +914,7 @@ def send(title: str, content: str) -> None:
911
914
  hitokoto = push_config.get("HITOKOTO")
912
915
  content += "\n\n" + one() if hitokoto else ""
913
916
 
914
- add_notify_function()
917
+ notify_function = add_notify_function()
915
918
  ts = [
916
919
  threading.Thread(target=mode, args=(title, content), name=mode.__name__)
917
920
  for mode in notify_function
package/sample/test.js ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * 任务名称
3
+ * name: script name
4
+ * 定时规则
5
+ * cron: 1 9 * * *
6
+ */
7
+
8
+ console.log('test scripts');
package/sample/test.py ADDED
@@ -0,0 +1,8 @@
1
+ """
2
+ 任务名称
3
+ name: script name
4
+ 定时规则
5
+ cron: 1 9 * * *
6
+ """
7
+
8
+ print("test script")
package/shell/check.sh CHANGED
@@ -81,6 +81,7 @@ main() {
81
81
  check_ql
82
82
  check_nginx
83
83
  check_pm2
84
+ reload_update
84
85
  reload_pm2
85
86
  echo -e "\n=====> 检测结束\n"
86
87
  }
package/shell/share.sh CHANGED
@@ -38,8 +38,12 @@ file_task_sample=$dir_sample/task.sample.sh
38
38
  file_extra_sample=$dir_sample/extra.sample.sh
39
39
  file_notify_js_sample=$dir_sample/notify.js
40
40
  file_notify_py_sample=$dir_sample/notify.py
41
+ file_test_js_sample=$dir_sample/test.js
42
+ file_test_py_sample=$dir_sample/test.py
41
43
  file_notify_py=$dir_scripts/notify.py
42
44
  file_notify_js=$dir_scripts/sendNotify.js
45
+ file_test_js=$dir_scripts/test.js
46
+ file_test_py=$dir_scripts/test.py
43
47
  nginx_app_conf=$dir_root/docker/front.conf
44
48
  nginx_conf=$dir_root/docker/nginx.conf
45
49
  dep_notify_py=$dir_dep/notify.py
@@ -239,6 +243,16 @@ fix_config() {
239
243
  echo
240
244
  fi
241
245
 
246
+ if [[ ! -s $file_test_js ]]; then
247
+ cp -fv $file_test_js_sample $file_test_js
248
+ echo
249
+ fi
250
+
251
+ if [[ ! -s $file_test_py ]]; then
252
+ cp -fv $file_test_py_sample $file_test_py
253
+ echo
254
+ fi
255
+
242
256
  if [[ -s /etc/nginx/conf.d/default.conf ]]; then
243
257
  echo -e "检测到默认nginx配置文件,清空...\n"
244
258
  cat /dev/null >/etc/nginx/conf.d/default.conf
@@ -298,7 +312,7 @@ git_clone_scripts() {
298
312
 
299
313
  set_proxy "$proxy"
300
314
 
301
- git clone --depth=1 $part_cmd $url $dir
315
+ git clone -q --depth=1 $part_cmd $url $dir
302
316
  exit_status=$?
303
317
 
304
318
  unset_proxy
@@ -310,6 +324,11 @@ random_range() {
310
324
  echo $((RANDOM % ($end - $beg) + $beg))
311
325
  }
312
326
 
327
+ delete_pm2() {
328
+ cd $dir_root
329
+ pm2 delete ecosystem.config.js
330
+ }
331
+
313
332
  reload_pm2() {
314
333
  cd $dir_root
315
334
  restore_env_vars
@@ -317,6 +336,13 @@ reload_pm2() {
317
336
  pm2 startOrGracefulReload ecosystem.config.js
318
337
  }
319
338
 
339
+ reload_update() {
340
+ cd $dir_root
341
+ restore_env_vars
342
+ pm2 flush &>/dev/null
343
+ pm2 startOrGracefulReload other.config.js
344
+ }
345
+
320
346
  diff_time() {
321
347
  local format="$1"
322
348
  local begin_time="$2"
package/shell/update.sh CHANGED
@@ -34,7 +34,6 @@ output_list_add_drop() {
34
34
  if [[ -s $list ]]; then
35
35
  echo -e "检测到有${type}的定时任务:"
36
36
  cat $list
37
- echo
38
37
  fi
39
38
  }
40
39
 
@@ -45,7 +44,7 @@ del_cron() {
45
44
  local path=$2
46
45
  local detail=""
47
46
  local ids=""
48
- echo -e "开始尝试自动删除失效的定时任务..."
47
+ echo -e "\n开始尝试自动删除失效的定时任务..."
49
48
  for cron in $(cat $list_drop); do
50
49
  local id=$(cat $list_crontab_user | grep -E "$cmd_task.* $cron" | perl -pe "s|.*ID=(.*) $cmd_task.* $cron\.*|\1|" | head -1 | awk -F " " '{print $1}')
51
50
  if [[ $ids ]]; then
@@ -76,7 +75,7 @@ del_cron() {
76
75
  add_cron() {
77
76
  local list_add=$1
78
77
  local path=$2
79
- echo -e "开始尝试自动添加定时任务..."
78
+ echo -e "\n开始尝试自动添加定时任务..."
80
79
  local detail=""
81
80
  cd $dir_scripts
82
81
  for file in $(cat $list_add); do
@@ -86,19 +85,20 @@ add_cron() {
86
85
  cron_line=$(
87
86
  perl -ne "{
88
87
  print if /.*([\d\*]*[\*-\/,\d]*[\d\*] ){4,5}[\d\*]*[\*-\/,\d]*[\d\*]( |,|\").*$file_name/
89
- }" $file |
88
+ }" $file 2>/dev/null |
90
89
  perl -pe "{
91
90
  s|[^\d\*]*(([\d\*]*[\*-\/,\d]*[\d\*] ){4,5}[\d\*]*[\*-\/,\d]*[\d\*])( \|,\|\").*/?$file_name.*|\1|g;
92
91
  s|\*([\d\*])(.*)|\1\2|g;
93
92
  s| | |g;
94
- }" | sort -u | head -1
93
+ }" 2>/dev/null | sort -u | head -1
95
94
  )
96
- cron_name=$(grep "new Env" $file | awk -F "\(" '{print $2}' | awk -F "\)" '{print $1}' | sed 's:.*\('\''\|"\)\([^"'\'']*\)\('\''\|"\).*:\2:' | sed 's:"::g' | sed "s:'::g" | head -1)
97
- [[ -z $cron_name ]] && cron_name="$file_name"
98
95
  [[ -z $cron_line ]] && cron_line=$(grep "cron:" $file | awk -F ":" '{print $2}' | head -1 | xargs)
99
96
  [[ -z $cron_line ]] && cron_line=$(grep "cron " $file | awk -F "cron \"" '{print $2}' | awk -F "\" " '{print $1}' | head -1 | xargs)
100
97
  [[ -z $cron_line ]] && cron_line="$default_cron"
101
- result=$(add_cron_api "$cron_line:$cmd_task $file:$cron_name:$SUB_ID")
98
+ cron_name=$(grep "new Env" $file | awk -F "\(" '{print $2}' | awk -F "\)" '{print $1}' | sed 's:.*\('\''\|"\)\([^"'\'']*\)\('\''\|"\).*:\2:' | sed 's:"::g' | sed "s:'::g" | head -1)
99
+ [[ -z $cron_name ]] && cron_name=$(grep "name:" $file | awk -F ":" '{print $2}' | head -1 | xargs)
100
+ [[ -z $cron_name ]] && cron_name=$(basename "$file_name")
101
+ result=$(add_cron_api "${cron_line}:${cmd_task} ${file}:${cron_name}:${SUB_ID}")
102
102
  echo -e "$result"
103
103
  if [[ $detail ]]; then
104
104
  detail="${detail}${result}\n"
@@ -135,10 +135,10 @@ update_repo() {
135
135
  git_clone_scripts "${formatUrl}" ${repo_path} "${branch}" "${proxy}"
136
136
 
137
137
  if [[ $exit_status -eq 0 ]]; then
138
- echo -e "\n拉取 ${uniq_path} 成功...\n"
138
+ echo -e "拉取 ${uniq_path} 成功...\n"
139
139
  diff_scripts "$repo_path" "$author" "$path" "$blackword" "$dependence" "$extensions" "$autoAddCron" "$autoDelCron"
140
140
  else
141
- echo -e "\n拉取 ${uniq_path} 失败,请检查日志...\n"
141
+ echo -e "拉取 ${uniq_path} 失败,请检查日志...\n"
142
142
  fi
143
143
  }
144
144
 
@@ -195,7 +195,7 @@ update_raw() {
195
195
  [[ -z $cron_line ]] && cron_line=$(grep "cron:" $raw_file_name | awk -F ":" '{print $2}' | head -1 | xargs)
196
196
  [[ -z $cron_line ]] && cron_line=$(grep "cron " $raw_file_name | awk -F "cron \"" '{print $2}' | awk -F "\" " '{print $1}' | head -1 | xargs)
197
197
  [[ -z $cron_line ]] && cron_line="$default_cron"
198
- result=$(add_cron_api "$cron_line:$cmd_task $filename:$cron_name:$SUB_ID")
198
+ result=$(add_cron_api "${cron_line}:${cmd_task} ${filename}:${cron_name}:${SUB_ID}")
199
199
  echo -e "$result\n"
200
200
  notify_api "新增任务通知" "\n$result"
201
201
  # update_cron_api "$cron_line:$cmd_task $filename:$cron_name:$cron_id"
@@ -231,22 +231,25 @@ usage() {
231
231
  }
232
232
 
233
233
  reload_qinglong() {
234
+ delete_pm2
235
+
234
236
  local reload_target="${1}"
235
237
  local primary_branch="master"
236
- if [[ "${QL_BRANCH}" == "develop" ]]; then
237
- primary_branch="develop"
238
+ if [[ "${QL_BRANCH}" == "develop" ]] || [[ "${QL_BRANCH}" == "debian" ]] || [[ "${QL_BRANCH}" == "debian-dev" ]]; then
239
+ primary_branch="${QL_BRANCH}"
238
240
  fi
239
241
 
240
242
  if [[ "$reload_target" == 'system' ]]; then
241
- cp -rf ${dir_tmp}/qinglong-${primary_branch}/* ${dir_root}/
243
+ rm -rf ${dir_root}/back ${dir_root}/cli ${dir_root}/docker ${dir_root}/sample ${dir_root}/shell ${dir_root}/src
244
+ mv -f ${dir_tmp}/qinglong-${primary_branch}/* ${dir_root}/
242
245
  rm -rf $dir_static/*
243
- cp -rf ${dir_tmp}/qinglong-static-${primary_branch}/* ${dir_static}/
246
+ mv -f ${dir_tmp}/qinglong-static-${primary_branch}/* ${dir_static}/
244
247
  cp -f $file_config_sample $dir_config/config.sample.sh
245
248
  fi
246
249
 
247
250
  if [[ "$reload_target" == 'data' ]]; then
248
- rm -rf ${dir_root}/data
249
- cp -rf ${dir_tmp}/data ${dir_root}/
251
+ rm -rf ${dir_root}/data/*
252
+ mv -f ${dir_tmp}/data/* ${dir_root}/data/
250
253
  fi
251
254
 
252
255
  reload_pm2
@@ -258,7 +261,7 @@ update_qinglong() {
258
261
  local mirror="gitee"
259
262
  local downloadQLUrl="https://gitee.com/whyour/qinglong/repository/archive"
260
263
  local downloadStaticUrl="https://gitee.com/whyour/qinglong-static/repository/archive"
261
- local githubStatus=$(curl -s -m 2 -IL "https://google.com" | grep 200)
264
+ local githubStatus=$(curl -s --noproxy "*" -m 2 -IL "https://google.com" | grep 200)
262
265
  if [[ ! -z $githubStatus ]]; then
263
266
  mirror="github"
264
267
  downloadQLUrl="https://github.com/whyour/qinglong/archive/refs/heads"
@@ -310,9 +313,12 @@ check_update_dep() {
310
313
  echo -e "更新包下载成功..."
311
314
 
312
315
  if [[ "$needRestart" == 'true' ]]; then
313
- cp -rf ${dir_tmp}/qinglong-${primary_branch}/* ${dir_root}/
316
+ delete_pm2
317
+
318
+ rm -rf ${dir_root}/back ${dir_root}/cli ${dir_root}/docker ${dir_root}/sample ${dir_root}/shell ${dir_root}/src
319
+ mv -f ${dir_tmp}/qinglong-${primary_branch}/* ${dir_root}/
314
320
  rm -rf $dir_static/*
315
- cp -rf ${dir_tmp}/qinglong-static-${primary_branch}/* ${dir_static}/
321
+ mv -f ${dir_tmp}/qinglong-static-${primary_branch}/* ${dir_static}/
316
322
  cp -f $file_config_sample $dir_config/config.sample.sh
317
323
 
318
324
  reload_pm2
@@ -417,9 +423,15 @@ gen_list_repo() {
417
423
  fi
418
424
 
419
425
  for file in ${files}; do
426
+ dirPath=$(dirname "$file")
420
427
  filename=$(basename "$file")
421
- cp -f $file "$dir_scripts/${uniq_path}/${filename}"
422
- echo "${uniq_path}/${filename}" >>"$dir_list_tmp/${uniq_path}_scripts.list"
428
+ filePath="${uniq_path}/${filename}"
429
+ if [[ $dirPath ]] && [[ $dirPath != '.' ]]; then
430
+ mkdir -p "${dir_scripts}/${uniq_path}/${dirPath}"
431
+ filePath="${uniq_path}/${dirPath}/${filename}"
432
+ fi
433
+ cp -f $file "${dir_scripts}/$filePath"
434
+ echo "$filePath" >>"$dir_list_tmp/${uniq_path}_scripts.list"
423
435
  # cron_id=$(cat $list_crontab_user | grep -E "$cmd_task.* ${uniq_path}_${filename}" | perl -pe "s|.*ID=(.*) $cmd_task.* ${uniq_path}_${filename}\.*|\1|" | head -1 | awk -F " " '{print $1}')
424
436
  # if [[ $cron_id ]]; then
425
437
  # result=$(update_cron_command_api "$cmd_task ${uniq_path}/${filename}:$cron_id")
@@ -123,7 +123,7 @@ exports.default = (app) => {
123
123
  });
124
124
  }
125
125
  if (req.file) {
126
- await fs.rename(req.file.path, (0, path_1.join)(path, req.file.filename));
126
+ await fs.rename(req.file.path, (0, path_1.join)(path, filename));
127
127
  return res.send({ code: 200 });
128
128
  }
129
129
  if (directory) {
@@ -56,6 +56,7 @@ exports.default = {
56
56
  port: parseInt(process.env.BACK_PORT, 10),
57
57
  cronPort: parseInt(process.env.CRON_PORT, 10),
58
58
  publicPort: parseInt(process.env.PUBLIC_PORT, 10),
59
+ updatePort: parseInt(process.env.UPDATE_PORT, 10),
59
60
  secret: process.env.SECRET || (0, share_1.createRandomString)(16, 32),
60
61
  logs: {
61
62
  level: process.env.LOG_LEVEL || 'silly',