@whyour/qinglong 2.19.0-9 → 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.
- package/back/protos/api.proto +123 -8
- package/docker/docker-entrypoint.sh +1 -1
- package/package.json +1 -1
- package/sample/config.sample.sh +8 -0
- package/sample/notify.js +15 -1
- package/sample/notify.py +12 -1
- package/shell/preload/sitecustomize.js +2 -4
- package/shell/preload/sitecustomize.py +2 -4
- package/shell/pub.sh +4 -8
- package/shell/share.sh +1 -1
- package/static/build/api/script.js +4 -1
- package/static/build/api/system.js +20 -2
- package/static/build/app.js +131 -26
- package/static/build/config/const.js +24 -1
- package/static/build/config/index.js +4 -3
- package/static/build/config/util.js +21 -1
- package/static/build/data/dependence.js +1 -7
- package/static/build/data/notify.js +4 -0
- package/static/build/loaders/initFile.js +2 -1
- package/static/build/protos/api.js +1374 -70
- package/static/build/schedule/api.js +5 -1
- package/static/build/services/cron.js +22 -9
- package/static/build/services/dependence.js +7 -11
- package/static/build/services/notify.js +27 -6
- package/static/build/services/system.js +26 -4
- package/static/dist/2208.3bc521b1.async.js +1 -0
- package/static/dist/2995.2eb218b3.async.js +1 -0
- package/static/dist/3191.cc1e31cd.async.js +1 -0
- package/static/dist/540.481d4708.async.js +1 -0
- package/static/dist/5713.8519f547.async.js +1 -0
- package/static/dist/7355.b7c0562f.async.js +1 -0
- package/static/dist/786.59fc381c.async.js +1 -0
- package/static/dist/8826.3ab4ad84.async.js +1 -0
- package/static/dist/8851.503b1e64.async.js +1 -0
- package/static/dist/index.html +2 -2
- package/static/dist/layouts__index.8dcf1576.async.js +1 -0
- package/static/dist/preload_helper.0d173b72.js +1 -0
- package/static/dist/src__pages__crontab__detail.64ec3a2b.async.js +1 -0
- package/static/dist/src__pages__crontab__index.74e7828f.async.js +1 -0
- package/static/dist/{src__pages__crontab__logModal.0767c532.async.js → src__pages__crontab__logModal.5fa54b25.async.js} +1 -1
- package/static/dist/src__pages__crontab__modal.21258e08.async.js +1 -0
- package/static/dist/src__pages__crontab__viewManageModal.c2724575.async.js +1 -0
- package/static/dist/{src__pages__dependence__index.c31e50f0.async.js → src__pages__dependence__index.3d87ceac.async.js} +1 -1
- package/static/dist/src__pages__dependence__modal.6639424a.async.js +1 -0
- package/static/dist/src__pages__env__editNameModal.665393cd.async.js +1 -0
- package/static/dist/src__pages__env__index.70340ba7.async.js +1 -0
- package/static/dist/src__pages__env__modal.168498f9.async.js +1 -0
- package/static/dist/{src__pages__error__index.18520dbf.async.js → src__pages__error__index.d9beeda3.async.js} +1 -1
- package/static/dist/src__pages__initialization__index.2403c031.async.js +1 -0
- package/static/dist/src__pages__script__editModal.f1741417.async.js +1 -0
- package/static/dist/src__pages__script__editNameModal.e36cd111.async.js +1 -0
- package/static/dist/src__pages__script__index.82b42e11.async.js +1 -0
- package/static/dist/src__pages__script__renameModal.f9756f26.async.js +1 -0
- package/static/dist/src__pages__script__saveModal.e885e133.async.js +1 -0
- package/static/dist/src__pages__script__setting.8c2727b4.async.js +1 -0
- package/static/dist/src__pages__setting__appModal.5a39121e.async.js +1 -0
- package/static/dist/src__pages__setting__dependence.a46e873d.async.js +1 -0
- package/static/dist/src__pages__setting__index.32b260ce.async.js +1 -0
- package/static/dist/src__pages__setting__notification.299f6b96.async.js +1 -0
- package/static/dist/src__pages__setting__other.8b77afcd.async.js +1 -0
- package/static/dist/src__pages__setting__security.e7371daa.async.js +1 -0
- package/static/dist/src__pages__setting__systemLog.fc5bdc78.async.js +1 -0
- package/static/dist/{src__pages__subscription__index.850531a4.async.js → src__pages__subscription__index.d0ab2abc.async.js} +1 -1
- package/static/dist/{src__pages__subscription__logModal.9bf0b4f6.async.js → src__pages__subscription__logModal.0caa7283.async.js} +1 -1
- package/static/dist/src__pages__subscription__modal.a7fd6a3c.async.js +1 -0
- package/static/dist/{umi.80b4d6a9.js → umi.35a646c6.js} +1 -1
- package/version.yaml +9 -12
- package/static/dist/2208.98ccac5f.async.js +0 -1
- package/static/dist/3191.f56b00f8.async.js +0 -1
- package/static/dist/6439.7ef6c5e3.async.js +0 -1
- package/static/dist/7355.5e5e573b.async.js +0 -1
- package/static/dist/7528.d8b76d8a.async.js +0 -1
- package/static/dist/874.ae8edb1a.async.js +0 -1
- package/static/dist/8826.faecf076.async.js +0 -1
- package/static/dist/8851.cf7e0ebc.async.js +0 -1
- package/static/dist/8982.d2dba153.async.js +0 -1
- package/static/dist/layouts__index.8451cde4.async.js +0 -1
- package/static/dist/preload_helper.6f133e1a.js +0 -1
- package/static/dist/src__pages__crontab__detail.ebbb4abf.async.js +0 -1
- package/static/dist/src__pages__crontab__index.d6d37f6a.async.js +0 -1
- package/static/dist/src__pages__crontab__modal.dcd053b5.async.js +0 -1
- package/static/dist/src__pages__crontab__viewManageModal.c4bfd6a2.async.js +0 -1
- package/static/dist/src__pages__dependence__modal.7f588c0b.async.js +0 -1
- package/static/dist/src__pages__env__editNameModal.411043e2.async.js +0 -1
- package/static/dist/src__pages__env__index.5a863036.async.js +0 -1
- package/static/dist/src__pages__env__modal.7d952f26.async.js +0 -1
- package/static/dist/src__pages__initialization__index.5bd471c5.async.js +0 -1
- package/static/dist/src__pages__script__editModal.10dd9857.async.js +0 -1
- package/static/dist/src__pages__script__editNameModal.32bb2f80.async.js +0 -1
- package/static/dist/src__pages__script__index.53f99bee.async.js +0 -1
- package/static/dist/src__pages__script__renameModal.8232c924.async.js +0 -1
- package/static/dist/src__pages__script__saveModal.8e358e84.async.js +0 -1
- package/static/dist/src__pages__script__setting.dcdd7253.async.js +0 -1
- package/static/dist/src__pages__setting__appModal.25adf30e.async.js +0 -1
- package/static/dist/src__pages__setting__dependence.95dd01e7.async.js +0 -1
- package/static/dist/src__pages__setting__index.3b426f9f.async.js +0 -1
- package/static/dist/src__pages__setting__notification.989e57d6.async.js +0 -1
- package/static/dist/src__pages__setting__other.45f67bd2.async.js +0 -1
- package/static/dist/src__pages__setting__security.7623a492.async.js +0 -1
- package/static/dist/src__pages__setting__systemLog.2e8cc7a0.async.js +0 -1
- package/static/dist/src__pages__subscription__modal.46a69195.async.js +0 -1
package/back/protos/api.proto
CHANGED
|
@@ -53,14 +53,7 @@ message Response {
|
|
|
53
53
|
optional string message = 2;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
message
|
|
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) {}
|
|
@@ -24,7 +24,7 @@ pm2 l &>/dev/null
|
|
|
24
24
|
log_with_style "INFO" "🔄 2. 启动 nginx..."
|
|
25
25
|
nginx -s reload 2>/dev/null || nginx -c /etc/nginx/nginx.conf
|
|
26
26
|
|
|
27
|
-
log_with_style "INFO" "⚙️ 3. 启动 pm2
|
|
27
|
+
log_with_style "INFO" "⚙️ 3. 启动 pm2 服务..."
|
|
28
28
|
reload_pm2
|
|
29
29
|
|
|
30
30
|
if [[ $AutoStartBot == true ]]; then
|
package/package.json
CHANGED
package/sample/config.sample.sh
CHANGED
|
@@ -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/
|
|
90
|
+
if (!error.message.includes('spawnSync /bin/bash E2BIG')) {
|
|
91
91
|
console.log(`\ue926 run task before error: `, error);
|
|
92
92
|
} else {
|
|
93
|
-
|
|
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
|
-
|
|
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 "切换
|
|
5
|
-
git
|
|
6
|
-
|
|
7
|
-
|
|
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
|
package/shell/share.sh
CHANGED
|
@@ -199,11 +199,14 @@ exports.default = (app) => {
|
|
|
199
199
|
route.post('/download', (0, celebrate_1.celebrate)({
|
|
200
200
|
body: celebrate_1.Joi.object({
|
|
201
201
|
filename: celebrate_1.Joi.string().required(),
|
|
202
|
-
path: celebrate_1.Joi.string().allow(''),
|
|
202
|
+
path: celebrate_1.Joi.string().optional().allow(''),
|
|
203
203
|
}),
|
|
204
204
|
}), async (req, res, next) => {
|
|
205
205
|
try {
|
|
206
206
|
let { filename, path } = req.body;
|
|
207
|
+
if (!path) {
|
|
208
|
+
path = '';
|
|
209
|
+
}
|
|
207
210
|
const scriptService = typedi_1.Container.get(script_1.default);
|
|
208
211
|
const filePath = scriptService.checkFilePath(path, filename);
|
|
209
212
|
if (!filePath) {
|
|
@@ -277,10 +277,14 @@ exports.default = (app) => {
|
|
|
277
277
|
return next(e);
|
|
278
278
|
}
|
|
279
279
|
});
|
|
280
|
-
route.put('/data/export',
|
|
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
|
package/static/build/app.js
CHANGED
|
@@ -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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
89
|
-
|
|
90
|
-
(
|
|
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 ||
|
|
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
|
|
@@ -29,7 +29,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
29
29
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
30
30
|
};
|
|
31
31
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
-
exports.updateLinuxMirrorFile = exports.detectOS = exports.isDemoEnv = exports.getUninstallCommand = exports.getInstallCommand = exports.setSystemTimezone = exports.rmPath = exports.safeJSONParse = exports.getUniqPath = exports.parseContentVersion = exports.parseVersion = exports.getPid = exports.killTask = exports.psTree = exports.parseBody = exports.parseHeaders = exports.promiseExecSuccess = exports.promiseExec = exports.readDir = exports.readDirs = exports.dirSort = exports.concurrentRun = exports.handleLogPath = exports.createFile = exports.fileExist = exports.getPlatform = exports.getToken = exports.getLastModifyFilePath = exports.removeAnsi = exports.getFileContentByName = void 0;
|
|
32
|
+
exports.updateLinuxMirrorFile = exports.detectOS = exports.isDemoEnv = exports.getUninstallCommand = exports.getInstallCommand = exports.getGetCommand = exports.setSystemTimezone = exports.rmPath = exports.safeJSONParse = exports.getUniqPath = exports.parseContentVersion = exports.parseVersion = exports.getPid = exports.killTask = exports.psTree = exports.parseBody = exports.parseHeaders = exports.promiseExecSuccess = exports.promiseExec = exports.readDir = exports.readDirs = exports.dirSort = exports.concurrentRun = exports.handleLogPath = exports.createFile = exports.fileExist = exports.getPlatform = exports.getToken = exports.getLastModifyFilePath = exports.removeAnsi = exports.getFileContentByName = void 0;
|
|
33
33
|
const fs = __importStar(require("fs/promises"));
|
|
34
34
|
const path = __importStar(require("path"));
|
|
35
35
|
const child_process_1 = require("child_process");
|
|
@@ -474,6 +474,26 @@ async function setSystemTimezone(timezone) {
|
|
|
474
474
|
}
|
|
475
475
|
}
|
|
476
476
|
exports.setSystemTimezone = setSystemTimezone;
|
|
477
|
+
function getGetCommand(type, name) {
|
|
478
|
+
const baseCommands = {
|
|
479
|
+
[dependence_1.DependenceTypes.nodejs]: `pnpm ls -g | grep "${name}" | head -1`,
|
|
480
|
+
[dependence_1.DependenceTypes.python3]: `
|
|
481
|
+
python3 -c "exec('''
|
|
482
|
+
name='${name}'
|
|
483
|
+
try:
|
|
484
|
+
from importlib.metadata import version
|
|
485
|
+
print(version(name))
|
|
486
|
+
except:
|
|
487
|
+
import importlib.util as u
|
|
488
|
+
import importlib.metadata as m
|
|
489
|
+
spec=u.find_spec(name)
|
|
490
|
+
print(name if spec else '')
|
|
491
|
+
''')"`,
|
|
492
|
+
[dependence_1.DependenceTypes.linux]: `apt-get info ${name}`,
|
|
493
|
+
};
|
|
494
|
+
return baseCommands[type];
|
|
495
|
+
}
|
|
496
|
+
exports.getGetCommand = getGetCommand;
|
|
477
497
|
function getInstallCommand(type, name) {
|
|
478
498
|
const baseCommands = {
|
|
479
499
|
[dependence_1.DependenceTypes.nodejs]: 'pnpm add -g',
|