@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.
- package/.env.example +1 -0
- package/docker/310.Dockerfile +4 -0
- package/docker/docker-entrypoint.sh +1 -0
- package/docker/front.conf +16 -0
- package/other.config.js +13 -0
- package/package.json +4 -4
- package/sample/config.sample.sh +19 -8
- package/sample/notify.js +19 -16
- package/sample/notify.py +32 -29
- package/sample/test.js +8 -0
- package/sample/test.py +8 -0
- package/shell/check.sh +1 -0
- package/shell/share.sh +27 -1
- package/shell/update.sh +34 -22
- package/static/build/api/script.js +1 -1
- package/static/build/config/index.js +1 -0
- package/static/build/config/util.js +9 -8
- package/static/build/loaders/server.js +0 -21
- package/static/build/loaders/update.js +79 -0
- package/static/build/services/cron.js +1 -1
- package/static/build/services/notify.js +5 -14
- package/static/build/services/subscription.js +1 -1
- package/static/build/services/system.js +17 -32
- package/static/build/update.js +29 -0
- package/static/dist/{833.c59c5023.async.js → 833.ea0fd669.async.js} +1 -1
- package/static/dist/index.html +1 -1
- package/static/dist/{src__pages__crontab__detail.2ab4f3e8.async.js → src__pages__crontab__detail.a2bfd72a.async.js} +1 -1
- package/static/dist/src__pages__crontab__index.98d464c0.async.js +1 -0
- package/static/dist/src__pages__log__index.e7377c48.async.js +1 -0
- package/static/dist/src__pages__script__editNameModal.3eabdcdb.async.js +1 -0
- package/static/dist/src__pages__script__index.8d14185b.async.js +1 -0
- package/static/dist/src__pages__setting__checkUpdate.43e62d05.async.js +1 -0
- package/static/dist/src__pages__setting__dependence.28193e94.async.js +1 -0
- package/static/dist/src__pages__setting__index.7ab054fb.async.js +1 -0
- package/static/dist/src__pages__setting__other.2c4534ef.async.js +1 -0
- package/static/dist/src__pages__setting__progress.7d65aebf.async.js +1 -0
- package/static/dist/{umi.cbe4d7e7.js → umi.11c81ea6.js} +1 -1
- package/version.yaml +10 -6
- package/static/build/data/cron.js +0 -69
- package/static/build/data/cronView.js +0 -39
- package/static/build/data/dependence.js +0 -70
- package/static/build/data/env.js +0 -38
- package/static/build/data/index.js +0 -27
- package/static/build/data/notify.js +0 -183
- package/static/build/data/open.js +0 -23
- package/static/build/data/sock.js +0 -12
- package/static/build/data/subscription.js +0 -82
- package/static/build/data/system.js +0 -36
- package/static/dist/8008.89ba3d06.async.js +0 -1
- package/static/dist/src__pages__crontab__index.f4269e9c.async.js +0 -1
- package/static/dist/src__pages__log__index.44c6a008.async.js +0 -1
- package/static/dist/src__pages__script__editNameModal.55a6bcbb.async.js +0 -1
- package/static/dist/src__pages__script__index.364b93d9.async.js +0 -1
- package/static/dist/src__pages__setting__checkUpdate.42020a45.async.js +0 -1
- package/static/dist/src__pages__setting__dependence.2efb8ee3.async.js +0 -1
- package/static/dist/src__pages__setting__index.3e2ad723.async.js +0 -1
- package/static/dist/src__pages__setting__other.a029d99a.async.js +0 -1
- package/static/dist/src__pages__setting__progress.65e2e878.async.js +0 -1
package/.env.example
CHANGED
package/docker/310.Dockerfile
CHANGED
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;
|
package/other.config.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@whyour/qinglong",
|
|
3
|
-
"version": "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": "^
|
|
185
|
+
"tsx": "^4.7.3",
|
|
186
186
|
"typescript": "5.2.2",
|
|
187
187
|
"vh-check": "^2.0.5",
|
|
188
188
|
"virtualizedtableforantd4": "1.3.0",
|
package/sample/config.sample.sh
CHANGED
|
@@ -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
|
-
##
|
|
167
|
-
##
|
|
168
|
-
|
|
169
|
-
##
|
|
170
|
-
|
|
171
|
-
export
|
|
172
|
-
|
|
173
|
-
export
|
|
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) +
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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=
|
|
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
package/sample/test.py
ADDED
package/shell/check.sh
CHANGED
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
|
-
|
|
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 "
|
|
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 "
|
|
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="
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
422
|
-
|
|
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,
|
|
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',
|