@whyour/qinglong 2.19.1-0 → 2.19.2-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 (86) hide show
  1. package/back/protos/api.proto +123 -8
  2. package/package.json +1 -1
  3. package/sample/config.sample.sh +8 -0
  4. package/sample/notify.js +15 -1
  5. package/sample/notify.py +12 -1
  6. package/shell/preload/sitecustomize.js +2 -4
  7. package/shell/preload/sitecustomize.py +2 -4
  8. package/shell/pub.sh +4 -8
  9. package/static/build/api/system.js +20 -2
  10. package/static/build/app.js +131 -26
  11. package/static/build/config/const.js +24 -1
  12. package/static/build/config/index.js +4 -3
  13. package/static/build/data/notify.js +4 -0
  14. package/static/build/protos/api.js +1374 -70
  15. package/static/build/schedule/api.js +5 -1
  16. package/static/build/services/dependence.js +4 -6
  17. package/static/build/services/notify.js +27 -6
  18. package/static/build/services/system.js +26 -4
  19. package/static/dist/2208.3bc521b1.async.js +1 -0
  20. package/static/dist/2995.2eb218b3.async.js +1 -0
  21. package/static/dist/540.481d4708.async.js +1 -0
  22. package/static/dist/5713.8519f547.async.js +1 -0
  23. package/static/dist/7355.b7c0562f.async.js +1 -0
  24. package/static/dist/786.59fc381c.async.js +1 -0
  25. package/static/dist/8826.3ab4ad84.async.js +1 -0
  26. package/static/dist/8851.503b1e64.async.js +1 -0
  27. package/static/dist/index.html +2 -2
  28. package/static/dist/layouts__index.8dcf1576.async.js +1 -0
  29. package/static/dist/preload_helper.0d173b72.js +1 -0
  30. package/static/dist/src__pages__crontab__detail.64ec3a2b.async.js +1 -0
  31. package/static/dist/{src__pages__crontab__index.679a169c.async.js → src__pages__crontab__index.74e7828f.async.js} +1 -1
  32. package/static/dist/src__pages__crontab__modal.21258e08.async.js +1 -0
  33. package/static/dist/src__pages__crontab__viewManageModal.c2724575.async.js +1 -0
  34. package/static/dist/src__pages__dependence__modal.6639424a.async.js +1 -0
  35. package/static/dist/src__pages__env__editNameModal.665393cd.async.js +1 -0
  36. package/static/dist/src__pages__env__index.70340ba7.async.js +1 -0
  37. package/static/dist/src__pages__env__modal.168498f9.async.js +1 -0
  38. package/static/dist/src__pages__error__index.d9beeda3.async.js +1 -0
  39. package/static/dist/src__pages__initialization__index.2403c031.async.js +1 -0
  40. package/static/dist/src__pages__script__editNameModal.e36cd111.async.js +1 -0
  41. package/static/dist/src__pages__script__index.82b42e11.async.js +1 -0
  42. package/static/dist/src__pages__script__renameModal.f9756f26.async.js +1 -0
  43. package/static/dist/src__pages__script__saveModal.e885e133.async.js +1 -0
  44. package/static/dist/src__pages__script__setting.8c2727b4.async.js +1 -0
  45. package/static/dist/src__pages__setting__appModal.5a39121e.async.js +1 -0
  46. package/static/dist/src__pages__setting__dependence.a46e873d.async.js +1 -0
  47. package/static/dist/src__pages__setting__index.32b260ce.async.js +1 -0
  48. package/static/dist/src__pages__setting__notification.299f6b96.async.js +1 -0
  49. package/static/dist/src__pages__setting__other.8b77afcd.async.js +1 -0
  50. package/static/dist/src__pages__setting__security.e7371daa.async.js +1 -0
  51. package/static/dist/src__pages__setting__systemLog.fc5bdc78.async.js +1 -0
  52. package/static/dist/src__pages__subscription__modal.a7fd6a3c.async.js +1 -0
  53. package/static/dist/{umi.1a9e58b8.js → umi.35a646c6.js} +1 -1
  54. package/version.yaml +9 -11
  55. package/static/dist/2208.4c5a62d1.async.js +0 -1
  56. package/static/dist/6439.7ef6c5e3.async.js +0 -1
  57. package/static/dist/7355.5e5e573b.async.js +0 -1
  58. package/static/dist/7528.d8b76d8a.async.js +0 -1
  59. package/static/dist/874.ae8edb1a.async.js +0 -1
  60. package/static/dist/8826.f18157b7.async.js +0 -1
  61. package/static/dist/8851.cf7e0ebc.async.js +0 -1
  62. package/static/dist/8982.d2dba153.async.js +0 -1
  63. package/static/dist/layouts__index.8451cde4.async.js +0 -1
  64. package/static/dist/preload_helper.aa612b58.js +0 -1
  65. package/static/dist/src__pages__crontab__detail.543910fb.async.js +0 -1
  66. package/static/dist/src__pages__crontab__modal.69adde20.async.js +0 -1
  67. package/static/dist/src__pages__crontab__viewManageModal.d1f69531.async.js +0 -1
  68. package/static/dist/src__pages__dependence__modal.53a4782a.async.js +0 -1
  69. package/static/dist/src__pages__env__editNameModal.7c6528e4.async.js +0 -1
  70. package/static/dist/src__pages__env__index.a31f3fe1.async.js +0 -1
  71. package/static/dist/src__pages__env__modal.b0dc95be.async.js +0 -1
  72. package/static/dist/src__pages__error__index.367a8c76.async.js +0 -1
  73. package/static/dist/src__pages__initialization__index.5bd471c5.async.js +0 -1
  74. package/static/dist/src__pages__script__editNameModal.fb125740.async.js +0 -1
  75. package/static/dist/src__pages__script__index.d834bef6.async.js +0 -1
  76. package/static/dist/src__pages__script__renameModal.e1bbbb50.async.js +0 -1
  77. package/static/dist/src__pages__script__saveModal.d4890228.async.js +0 -1
  78. package/static/dist/src__pages__script__setting.b3635f42.async.js +0 -1
  79. package/static/dist/src__pages__setting__appModal.0305916d.async.js +0 -1
  80. package/static/dist/src__pages__setting__dependence.95dd01e7.async.js +0 -1
  81. package/static/dist/src__pages__setting__index.c8d1ca47.async.js +0 -1
  82. package/static/dist/src__pages__setting__notification.989e57d6.async.js +0 -1
  83. package/static/dist/src__pages__setting__other.45f67bd2.async.js +0 -1
  84. package/static/dist/src__pages__setting__security.7623a492.async.js +0 -1
  85. package/static/dist/src__pages__setting__systemLog.2e8cc7a0.async.js +0 -1
  86. package/static/dist/src__pages__subscription__modal.46a69195.async.js +0 -1
@@ -53,14 +53,7 @@ message Response {
53
53
  optional string message = 2;
54
54
  }
55
55
 
56
- message SystemNotifyRequest {
57
- string title = 1;
58
- string content = 2;
59
- }
60
-
61
- message ExtraScheduleItem {
62
- string schedule = 1;
63
- }
56
+ message ExtraScheduleItem { string schedule = 1; }
64
57
 
65
58
  message CronItem {
66
59
  optional int32 id = 1;
@@ -124,6 +117,128 @@ message CronDetailResponse {
124
117
  optional string message = 3;
125
118
  }
126
119
 
120
+ enum NotificationMode {
121
+ gotify = 0;
122
+ goCqHttpBot = 1;
123
+ serverChan = 2;
124
+ pushDeer = 3;
125
+ bark = 4;
126
+ chat = 5;
127
+ telegramBot = 6;
128
+ dingtalkBot = 7;
129
+ weWorkBot = 8;
130
+ weWorkApp = 9;
131
+ aibotk = 10;
132
+ iGot = 11;
133
+ pushPlus = 12;
134
+ wePlusBot = 13;
135
+ email = 14;
136
+ pushMe = 15;
137
+ feishu = 16;
138
+ webhook = 17;
139
+ chronocat = 18;
140
+ ntfy = 19;
141
+ wxPusherBot = 20;
142
+ }
143
+
144
+ message NotificationInfo {
145
+ NotificationMode type = 1;
146
+
147
+ optional string gotifyUrl = 2;
148
+ optional string gotifyToken = 3;
149
+ optional int32 gotifyPriority = 4;
150
+
151
+ optional string goCqHttpBotUrl = 5;
152
+ optional string goCqHttpBotToken = 6;
153
+ optional string goCqHttpBotQq = 7;
154
+
155
+ optional string serverChanKey = 8;
156
+
157
+ optional string pushDeerKey = 9;
158
+ optional string pushDeerUrl = 10;
159
+
160
+ optional string synologyChatUrl = 11;
161
+
162
+ optional string barkPush = 12;
163
+ optional string barkIcon = 13;
164
+ optional string barkSound = 14;
165
+ optional string barkGroup = 15;
166
+ optional string barkLevel = 16;
167
+ optional string barkUrl = 17;
168
+ optional string barkArchive = 18;
169
+
170
+ optional string telegramBotToken = 19;
171
+ optional string telegramBotUserId = 20;
172
+ optional string telegramBotProxyHost = 21;
173
+ optional string telegramBotProxyPort = 22;
174
+ optional string telegramBotProxyAuth = 23;
175
+ optional string telegramBotApiHost = 24;
176
+
177
+ optional string dingtalkBotToken = 25;
178
+ optional string dingtalkBotSecret = 26;
179
+
180
+ optional string weWorkBotKey = 27;
181
+ optional string weWorkOrigin = 28;
182
+
183
+ optional string weWorkAppKey = 29;
184
+
185
+ optional string aibotkKey = 30;
186
+ optional string aibotkType = 31;
187
+ optional string aibotkName = 32;
188
+
189
+ optional string iGotPushKey = 33;
190
+
191
+ optional string pushPlusToken = 34;
192
+ optional string pushPlusUser = 35;
193
+ optional string pushPlusTemplate = 36;
194
+ optional string pushplusChannel = 37;
195
+ optional string pushplusWebhook = 38;
196
+ optional string pushplusCallbackUrl = 39;
197
+ optional string pushplusTo = 40;
198
+
199
+ optional string wePlusBotToken = 41;
200
+ optional string wePlusBotReceiver = 42;
201
+ optional string wePlusBotVersion = 43;
202
+
203
+ optional string emailService = 44;
204
+ optional string emailUser = 45;
205
+ optional string emailPass = 46;
206
+ optional string emailTo = 47;
207
+
208
+ optional string pushMeKey = 48;
209
+ optional string pushMeUrl = 49;
210
+
211
+ optional string chronocatURL = 50;
212
+ optional string chronocatQQ = 51;
213
+ optional string chronocatToken = 52;
214
+
215
+ optional string webhookHeaders = 53;
216
+ optional string webhookBody = 54;
217
+ optional string webhookUrl = 55;
218
+ optional string webhookMethod = 56;
219
+ optional string webhookContentType = 57;
220
+
221
+ optional string larkKey = 58;
222
+
223
+ optional string ntfyUrl = 59;
224
+ optional string ntfyTopic = 60;
225
+ optional string ntfyPriority = 61;
226
+ optional string ntfyToken = 62;
227
+ optional string ntfyUsername = 63;
228
+ optional string ntfyPassword = 64;
229
+ optional string ntfyActions = 65;
230
+
231
+ optional string wxPusherBotAppToken = 66;
232
+ optional string wxPusherBotTopicIds = 67;
233
+ optional string wxPusherBotUids = 68;
234
+ }
235
+
236
+ message SystemNotifyRequest {
237
+ string title = 1;
238
+ string content = 2;
239
+ optional NotificationInfo notificationInfo = 3;
240
+ }
241
+
127
242
  service Api {
128
243
  rpc GetEnvs(GetEnvsRequest) returns (EnvsResponse) {}
129
244
  rpc CreateEnv(CreateEnvRequest) returns (EnvsResponse) {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whyour/qinglong",
3
- "version": "2.19.1-0",
3
+ "version": "2.19.2-0",
4
4
  "description": "Timed task management platform supporting Python3, JavaScript, Shell, Typescript",
5
5
  "repository": {
6
6
  "type": "git",
@@ -226,9 +226,17 @@ export QMSG_TYPE=""
226
226
  ## ntfy_url 填写ntfy地址,如https://ntfy.sh
227
227
  ## ntfy_topic 填写ntfy的消息应用topic
228
228
  ## ntfy_priority 填写推送消息优先级,默认为3
229
+ ## ntfy_token 填写推送token,可选
230
+ ## ntfy_username 填写推送用户名称,可选
231
+ ## ntfy_password 填写推送用户密码,可选
232
+ ## ntfy_actions 填写推送用户动作,可选
229
233
  export NTFY_URL=""
230
234
  export NTFY_TOPIC=""
231
235
  export NTFY_PRIORITY="3"
236
+ export NTFY_TOKEN=""
237
+ export NTFY_USERNAME=""
238
+ export NTFY_PASSWORD=""
239
+ export NTFY_ACTIONS=""
232
240
 
233
241
  ## 21. wxPusher
234
242
  ## 官方文档: https://wxpusher.zjiecode.com/docs/
package/sample/notify.js CHANGED
@@ -140,6 +140,10 @@ const push_config = {
140
140
  NTFY_URL: '', // ntfy地址,如https://ntfy.sh,默认为https://ntfy.sh
141
141
  NTFY_TOPIC: '', // ntfy的消息应用topic
142
142
  NTFY_PRIORITY: '3', // 推送消息优先级,默认为3
143
+ NTFY_TOKEN: '', // 推送token,可选
144
+ NTFY_USERNAME: '', // 推送用户名称,可选
145
+ NTFY_PASSWORD: '', // 推送用户密码,可选
146
+ NTFY_ACTIONS: '', // 推送用户动作,可选
143
147
 
144
148
  // 官方文档: https://wxpusher.zjiecode.com/docs/
145
149
  // 管理后台: https://wxpusher.zjiecode.com/admin/
@@ -1258,7 +1262,7 @@ function ntfyNotify(text, desp) {
1258
1262
  }
1259
1263
 
1260
1264
  return new Promise((resolve) => {
1261
- const { NTFY_URL, NTFY_TOPIC, NTFY_PRIORITY } = push_config;
1265
+ const { NTFY_URL, NTFY_TOPIC, NTFY_PRIORITY, NTFY_TOKEN, NTFY_USERNAME, NTFY_PASSWORD, NTFY_ACTIONS } = push_config;
1262
1266
  if (NTFY_TOPIC) {
1263
1267
  const options = {
1264
1268
  url: `${NTFY_URL || 'https://ntfy.sh'}/${NTFY_TOPIC}`,
@@ -1266,9 +1270,19 @@ function ntfyNotify(text, desp) {
1266
1270
  headers: {
1267
1271
  Title: `${encodeRFC2047(text)}`,
1268
1272
  Priority: NTFY_PRIORITY || '3',
1273
+ Icon: 'https://qn.whyour.cn/logo.png',
1269
1274
  },
1270
1275
  timeout,
1271
1276
  };
1277
+ if (NTFY_TOKEN) {
1278
+ options.headers['Authorization'] = `Bearer ${NTFY_TOKEN}`;
1279
+ } else if (NTFY_USERNAME && NTFY_PASSWORD) {
1280
+ options.headers['Authorization'] = `Basic ${Buffer.from(`${NTFY_USERNAME}:${NTFY_PASSWORD}`).toString('base64')}`;
1281
+ }
1282
+ if (NTFY_ACTIONS) {
1283
+ options.headers['Actions'] = encodeRFC2047(NTFY_ACTIONS);
1284
+ }
1285
+
1272
1286
  $.post(options, (err, resp, data) => {
1273
1287
  try {
1274
1288
  if (err) {
package/sample/notify.py CHANGED
@@ -126,6 +126,10 @@ push_config = {
126
126
  'NTFY_URL': '', # ntfy地址,如https://ntfy.sh
127
127
  'NTFY_TOPIC': '', # ntfy的消息应用topic
128
128
  'NTFY_PRIORITY':'3', # 推送消息优先级,默认为3
129
+ 'NTFY_TOKEN': '', # 推送token,可选
130
+ 'NTFY_USERNAME': '', # 推送用户名称,可选
131
+ 'NTFY_PASSWORD': '', # 推送用户密码,可选
132
+ 'NTFY_ACTIONS': '', # 推送用户动作,可选
129
133
 
130
134
  'WXPUSHER_APP_TOKEN': '', # wxpusher 的 appToken 官方文档: https://wxpusher.zjiecode.com/docs/ 管理后台: https://wxpusher.zjiecode.com/admin/
131
135
  'WXPUSHER_TOPIC_IDS': '', # wxpusher 的 主题ID,多个用英文分号;分隔 topic_ids 与 uids 至少配置一个才行
@@ -806,7 +810,14 @@ def ntfy(title: str, content: str) -> None:
806
810
  encoded_title = encode_rfc2047(title)
807
811
 
808
812
  data = content.encode(encoding="utf-8")
809
- headers = {"Title": encoded_title, "Priority": priority} # 使用编码后的 title
813
+ headers = {"Title": encoded_title, "Priority": priority, "Icon": "https://qn.whyour.cn/logo.png"} # 使用编码后的 title
814
+ if push_config.get("NTFY_TOKEN"):
815
+ headers['Authorization'] = "Bearer " + push_config.get("NTFY_TOKEN")
816
+ elif push_config.get("NTFY_USERNAME") and push_config.get("NTFY_PASSWORD"):
817
+ authStr = push_config.get("NTFY_USERNAME") + ":" + push_config.get("NTFY_PASSWORD")
818
+ headers['Authorization'] = "Basic " + base64.b64encode(authStr.encode('utf-8')).decode('utf-8')
819
+ if push_config.get("NTFY_ACTIONS"):
820
+ headers['Actions'] = encode_rfc2047(push_config.get("NTFY_ACTIONS"))
810
821
 
811
822
  url = push_config.get("NTFY_URL") + "/" + push_config.get("NTFY_TOPIC")
812
823
  response = requests.post(url, data=data, headers=headers)
@@ -87,12 +87,10 @@ function run() {
87
87
  console.log('执行前置命令结束\n');
88
88
  }
89
89
  } catch (error) {
90
- if (!error.message.includes('spawnSync /bin/sh E2BIG')) {
90
+ if (!error.message.includes('spawnSync /bin/bash E2BIG')) {
91
91
  console.log(`\ue926 run task before error: `, error);
92
92
  } else {
93
- console.log(
94
- `\ue926 The environment variable is too large. It is recommended to use task_before.js instead of task_before.sh\n`,
95
- );
93
+ // environment variable is too large
96
94
  }
97
95
  if (task_before) {
98
96
  console.log('执行前置命令结束\n');
@@ -98,10 +98,8 @@ def run():
98
98
  error_message = str(error)
99
99
  if "Argument list too long" not in error_message:
100
100
  print(f"\ue926 run task before error: {error}")
101
- else:
102
- print(
103
- "\ue926 The environment variable is too large. It is recommended to use task_before.py instead of task_before.sh\n"
104
- )
101
+ # else:
102
+ # environment variable is too large
105
103
  if task_before:
106
104
  print("执行前置命令结束\n")
107
105
  except Exception as error:
package/shell/pub.sh CHANGED
@@ -1,14 +1,10 @@
1
1
  #!/usr/bin/env bash
2
2
  echo -e "开始发布"
3
3
 
4
- echo -e "切换master分支"
5
- git checkout master
6
-
7
- echo -e "合并develop代码"
8
- git merge origin/develop
9
-
10
- echo -e "提交master代码"
11
- git push
4
+ echo -e "切换 debian 分支"
5
+ git branch -D debian
6
+ git checkout -b debian
7
+ git push --set-upstream origin debian -f
12
8
 
13
9
  echo -e "更新cdn文件"
14
10
  ts-node-transpile-only sample/tool.ts
@@ -277,10 +277,14 @@ exports.default = (app) => {
277
277
  return next(e);
278
278
  }
279
279
  });
280
- route.put('/data/export', async (req, res, next) => {
280
+ route.put('/data/export', (0, celebrate_1.celebrate)({
281
+ body: celebrate_1.Joi.object({
282
+ type: celebrate_1.Joi.array().items(celebrate_1.Joi.string()).optional(),
283
+ }),
284
+ }), async (req, res, next) => {
281
285
  try {
282
286
  const systemService = typedi_1.Container.get(system_1.default);
283
- await systemService.exportData(res);
287
+ await systemService.exportData(res, req.body.type);
284
288
  }
285
289
  catch (e) {
286
290
  return next(e);
@@ -352,5 +356,19 @@ exports.default = (app) => {
352
356
  return next(e);
353
357
  }
354
358
  });
359
+ route.put('/config/dependence-clean', (0, celebrate_1.celebrate)({
360
+ body: celebrate_1.Joi.object({
361
+ type: celebrate_1.Joi.string().allow(''),
362
+ }),
363
+ }), async (req, res, next) => {
364
+ try {
365
+ const systemService = typedi_1.Container.get(system_1.default);
366
+ const result = await systemService.cleanDependence(req.body.type);
367
+ res.send(result);
368
+ }
369
+ catch (e) {
370
+ return next(e);
371
+ }
372
+ });
355
373
  };
356
374
  //# sourceMappingURL=system.js.map
@@ -27,6 +27,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  require("reflect-metadata");
30
+ const cluster_1 = __importDefault(require("cluster"));
30
31
  const compression_1 = __importDefault(require("compression"));
31
32
  const cors_1 = __importDefault(require("cors"));
32
33
  const express_1 = __importDefault(require("express"));
@@ -38,28 +39,51 @@ const monitoring_1 = require("./middlewares/monitoring");
38
39
  class Application {
39
40
  constructor() {
40
41
  this.isShuttingDown = false;
42
+ this.workerMetadataMap = new Map();
41
43
  this.app = (0, express_1.default)();
42
44
  }
43
45
  async start() {
44
- var _a;
45
46
  try {
46
- await this.initializeDatabase();
47
- await this.initServer();
48
- this.setupMiddlewares();
49
- await this.initializeServices();
50
- this.setupGracefulShutdown();
51
- (_a = process.send) === null || _a === void 0 ? void 0 : _a.call(process, 'ready');
47
+ if (cluster_1.default.isPrimary) {
48
+ await this.initializeDatabase();
49
+ }
50
+ if (cluster_1.default.isPrimary) {
51
+ this.startMasterProcess();
52
+ }
53
+ else {
54
+ await this.startWorkerProcess();
55
+ }
52
56
  }
53
57
  catch (error) {
54
58
  logger_1.default.error('Failed to start application:', error);
55
59
  process.exit(1);
56
60
  }
57
61
  }
58
- async initServer() {
59
- const { HttpServerService } = await Promise.resolve().then(() => __importStar(require('./services/http')));
60
- const { GrpcServerService } = await Promise.resolve().then(() => __importStar(require('./services/grpc')));
61
- this.httpServerService = typedi_1.Container.get(HttpServerService);
62
- this.grpcServerService = typedi_1.Container.get(GrpcServerService);
62
+ startMasterProcess() {
63
+ this.forkWorker('http');
64
+ this.forkWorker('grpc');
65
+ cluster_1.default.on('exit', (worker, code, signal) => {
66
+ const metadata = this.workerMetadataMap.get(worker.id);
67
+ if (metadata) {
68
+ if (!this.isShuttingDown) {
69
+ logger_1.default.error(`${metadata.serviceType} worker ${worker.process.pid} died (${signal || code}). Restarting...`);
70
+ const newWorker = this.forkWorker(metadata.serviceType);
71
+ logger_1.default.info(`Restarted ${metadata.serviceType} worker (New PID: ${newWorker.process.pid})`);
72
+ }
73
+ this.workerMetadataMap.delete(worker.id);
74
+ }
75
+ });
76
+ this.setupMasterShutdown();
77
+ }
78
+ forkWorker(serviceType) {
79
+ const worker = cluster_1.default.fork({ SERVICE_TYPE: serviceType });
80
+ this.workerMetadataMap.set(worker.id, {
81
+ id: worker.id,
82
+ pid: worker.process.pid,
83
+ serviceType,
84
+ startTime: new Date(),
85
+ });
86
+ return worker;
63
87
  }
64
88
  async initializeDatabase() {
65
89
  await require('./loaders/db').default();
@@ -70,35 +94,116 @@ class Application {
70
94
  this.app.use((0, compression_1.default)());
71
95
  this.app.use(monitoring_1.monitoringMiddleware);
72
96
  }
73
- async initializeServices() {
74
- var _a, _b;
75
- await ((_a = this.grpcServerService) === null || _a === void 0 ? void 0 : _a.initialize());
76
- await require('./loaders/app').default({ app: this.app });
77
- const server = await ((_b = this.httpServerService) === null || _b === void 0 ? void 0 : _b.initialize(this.app, config_1.default.port));
78
- await require('./loaders/server').default({ server });
79
- }
80
- setupGracefulShutdown() {
97
+ setupMasterShutdown() {
81
98
  const shutdown = async () => {
82
- var _a, _b;
83
99
  if (this.isShuttingDown)
84
100
  return;
85
101
  this.isShuttingDown = true;
86
- logger_1.default.info('Shutting down services...');
102
+ const workers = Object.values(cluster_1.default.workers || {});
103
+ const workerPromises = [];
104
+ workers.forEach((worker) => {
105
+ if (worker) {
106
+ const exitPromise = new Promise((resolve) => {
107
+ worker.once('exit', () => {
108
+ logger_1.default.info(`Worker ${worker.process.pid} exited`);
109
+ resolve();
110
+ });
111
+ try {
112
+ worker.send('shutdown');
113
+ }
114
+ catch (error) {
115
+ logger_1.default.warn(`Failed to send shutdown to worker ${worker.process.pid}:`, error);
116
+ }
117
+ });
118
+ workerPromises.push(exitPromise);
119
+ }
120
+ });
87
121
  try {
88
- await Promise.all([
89
- (_a = this.grpcServerService) === null || _a === void 0 ? void 0 : _a.shutdown(),
90
- (_b = this.httpServerService) === null || _b === void 0 ? void 0 : _b.shutdown(),
122
+ await Promise.race([
123
+ Promise.all(workerPromises),
124
+ new Promise((resolve) => {
125
+ setTimeout(() => {
126
+ logger_1.default.warn('Worker shutdown timeout reached');
127
+ resolve();
128
+ }, 10000);
129
+ }),
91
130
  ]);
92
131
  process.exit(0);
93
132
  }
94
133
  catch (error) {
95
- logger_1.default.error('Error during shutdown:', error);
134
+ logger_1.default.error('Error during worker shutdown:', error);
96
135
  process.exit(1);
97
136
  }
98
137
  };
99
138
  process.on('SIGTERM', shutdown);
100
139
  process.on('SIGINT', shutdown);
101
140
  }
141
+ async startWorkerProcess() {
142
+ var _a;
143
+ const serviceType = process.env.SERVICE_TYPE;
144
+ if (!serviceType || !['http', 'grpc'].includes(serviceType)) {
145
+ logger_1.default.error('Invalid SERVICE_TYPE:', serviceType);
146
+ process.exit(1);
147
+ }
148
+ logger_1.default.info(`✌️ ${serviceType} worker started (PID: ${process.pid})`);
149
+ try {
150
+ if (serviceType === 'http') {
151
+ await this.startHttpService();
152
+ }
153
+ else {
154
+ await this.startGrpcService();
155
+ }
156
+ (_a = process.send) === null || _a === void 0 ? void 0 : _a.call(process, 'ready');
157
+ }
158
+ catch (error) {
159
+ logger_1.default.error(`${serviceType} worker failed:`, error);
160
+ process.exit(1);
161
+ }
162
+ }
163
+ async startHttpService() {
164
+ this.setupMiddlewares();
165
+ const { HttpServerService } = await Promise.resolve().then(() => __importStar(require('./services/http')));
166
+ this.httpServerService = typedi_1.Container.get(HttpServerService);
167
+ await require('./loaders/app').default({ app: this.app });
168
+ const server = await this.httpServerService.initialize(this.app, config_1.default.port);
169
+ await require('./loaders/server').default({ server });
170
+ this.setupWorkerShutdown('http');
171
+ }
172
+ async startGrpcService() {
173
+ const { GrpcServerService } = await Promise.resolve().then(() => __importStar(require('./services/grpc')));
174
+ this.grpcServerService = typedi_1.Container.get(GrpcServerService);
175
+ await this.grpcServerService.initialize();
176
+ this.setupWorkerShutdown('grpc');
177
+ }
178
+ setupWorkerShutdown(serviceType) {
179
+ process.on('message', (msg) => {
180
+ if (msg === 'shutdown') {
181
+ this.gracefulShutdown(serviceType);
182
+ }
183
+ });
184
+ const shutdown = () => this.gracefulShutdown(serviceType);
185
+ process.on('SIGTERM', shutdown);
186
+ process.on('SIGINT', shutdown);
187
+ }
188
+ async gracefulShutdown(serviceType) {
189
+ var _a, _b;
190
+ if (this.isShuttingDown)
191
+ return;
192
+ this.isShuttingDown = true;
193
+ try {
194
+ if (serviceType === 'http') {
195
+ await ((_a = this.httpServerService) === null || _a === void 0 ? void 0 : _a.shutdown());
196
+ }
197
+ else {
198
+ await ((_b = this.grpcServerService) === null || _b === void 0 ? void 0 : _b.shutdown());
199
+ }
200
+ process.exit(0);
201
+ }
202
+ catch (error) {
203
+ logger_1.default.error(`[${serviceType}] Error during shutdown:`, error);
204
+ process.exit(1);
205
+ }
206
+ }
102
207
  }
103
208
  const app = new Application();
104
209
  app.start().catch((error) => {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LINUX_DEPENDENCE_COMMAND = exports.PYTHON_INSTALL_DIR = exports.SAMPLE_FILES = exports.QL_PREFIX = exports.TASK_PREFIX = exports.QL_COMMAND = exports.TASK_COMMAND = exports.LOG_END_SYMBOL = void 0;
3
+ exports.LINUX_DEPENDENCE_COMMAND = exports.NotificationModeStringMap = exports.PYTHON_INSTALL_DIR = exports.SAMPLE_FILES = exports.QL_PREFIX = exports.TASK_PREFIX = exports.QL_COMMAND = exports.TASK_COMMAND = exports.LOG_END_SYMBOL = void 0;
4
4
  exports.LOG_END_SYMBOL = '     ';
5
5
  exports.TASK_COMMAND = 'task';
6
6
  exports.QL_COMMAND = 'ql';
@@ -24,6 +24,29 @@ exports.SAMPLE_FILES = [
24
24
  },
25
25
  ];
26
26
  exports.PYTHON_INSTALL_DIR = process.env.PYTHON_HOME;
27
+ exports.NotificationModeStringMap = {
28
+ 0: 'gotify',
29
+ 1: 'goCqHttpBot',
30
+ 2: 'serverChan',
31
+ 3: 'pushDeer',
32
+ 4: 'bark',
33
+ 5: 'chat',
34
+ 6: 'telegramBot',
35
+ 7: 'dingtalkBot',
36
+ 8: 'weWorkBot',
37
+ 9: 'weWorkApp',
38
+ 10: 'aibotk',
39
+ 11: 'iGot',
40
+ 12: 'pushPlus',
41
+ 13: 'wePlusBot',
42
+ 14: 'email',
43
+ 15: 'pushMe',
44
+ 16: 'feishu',
45
+ 17: 'webhook',
46
+ 18: 'chronocat',
47
+ 19: 'ntfy',
48
+ 20: 'wxPusherBot',
49
+ };
27
50
  exports.LINUX_DEPENDENCE_COMMAND = {
28
51
  Debian: {
29
52
  install: 'apt-get install -y',
@@ -5,7 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const dotenv_1 = __importDefault(require("dotenv"));
7
7
  const path_1 = __importDefault(require("path"));
8
- const share_1 = require("./share");
9
8
  dotenv_1.default.config({
10
9
  path: path_1.default.join(__dirname, '../../.env'),
11
10
  });
@@ -22,7 +21,7 @@ const config = {
22
21
  prefix: '/api',
23
22
  },
24
23
  jwt: {
25
- secret: process.env.JWT_SECRET || (0, share_1.createRandomString)(16, 32),
24
+ secret: process.env.JWT_SECRET || 'whyour-secret',
26
25
  expiresIn: process.env.JWT_EXPIRES_IN,
27
26
  },
28
27
  cors: {
@@ -60,6 +59,7 @@ const dbPath = path_1.default.join(dataPath, 'db/');
60
59
  const uploadPath = path_1.default.join(dataPath, 'upload/');
61
60
  const sshdPath = path_1.default.join(dataPath, 'ssh.d/');
62
61
  const systemLogPath = path_1.default.join(dataPath, 'syslog/');
62
+ const dependenceCachePath = path_1.default.join(dataPath, 'dep_cache/');
63
63
  const envFile = path_1.default.join(preloadPath, 'env.sh');
64
64
  const jsEnvFile = path_1.default.join(preloadPath, 'env.js');
65
65
  const pyEnvFile = path_1.default.join(preloadPath, 'env.py');
@@ -135,5 +135,6 @@ exports.default = Object.assign(Object.assign({}, config), { jwt: config.jwt, ro
135
135
  lastVersionFile,
136
136
  sqliteFile,
137
137
  sshdPath,
138
- systemLogPath });
138
+ systemLogPath,
139
+ dependenceCachePath });
139
140
  //# sourceMappingURL=index.js.map
@@ -205,6 +205,10 @@ class NtfyNotification extends NotificationBaseInfo {
205
205
  this.ntfyUrl = '';
206
206
  this.ntfyTopic = '';
207
207
  this.ntfyPriority = '';
208
+ this.ntfyToken = '';
209
+ this.ntfyUsername = '';
210
+ this.ntfyPassword = '';
211
+ this.ntfyActions = '';
208
212
  }
209
213
  }
210
214
  exports.NtfyNotification = NtfyNotification;