@whyour/qinglong 2.18.1 → 2.18.2-1
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/README-en.md +4 -127
- package/README.md +4 -125
- package/SECURITY.md +5 -0
- package/back.d.ts +9 -0
- package/package.json +6 -8
- package/sample/notify.js +5 -5
- package/sample/ql_sample.js +6 -0
- package/sample/ql_sample.py +6 -1
- package/shell/api.sh +4 -1
- package/shell/preload/client.js +45 -0
- package/shell/preload/client.py +113 -0
- package/shell/preload/sitecustomize.js +2 -0
- package/shell/preload/sitecustomize.py +2 -1
- package/shell/share.sh +15 -4
- package/shell/update.sh +2 -1
- package/static/build/api/log.js +1 -1
- package/static/build/app.js +0 -1
- package/static/build/config/index.js +0 -2
- package/static/build/config/util.js +8 -4
- package/static/build/data/env.js +1 -1
- package/static/build/loaders/db.js +0 -70
- package/static/build/loaders/express.js +2 -27
- package/static/build/loaders/initData.js +20 -12
- package/static/build/protos/api.js +1084 -0
- package/static/build/protos/cron.js +36 -27
- package/static/build/protos/health.js +12 -3
- package/static/build/schedule/api.js +140 -0
- package/static/build/schedule/index.js +26 -0
- package/static/build/services/env.js +1 -1
- package/static/build/services/notify.js +19 -34
- package/static/build/services/open.js +8 -7
- package/static/build/services/system.js +1 -1
- package/static/build/shared/pLimit.js +12 -1
- package/static/dist/2208.c1a40612.async.js +1 -0
- package/static/dist/{8528.3dffc548.async.js → 3127.2579e73a.async.js} +1 -1
- package/static/dist/{2237.4d3def87.async.js → 3191.f56b00f8.async.js} +1 -1
- package/static/dist/4402.49bbe98d.async.js +1 -0
- package/static/dist/{5312.5545b3ed.async.js → 5312.74b95311.async.js} +1 -1
- package/static/dist/{1149.33cb7e7a.async.js → 7253.4b9bf133.async.js} +1 -1
- package/static/dist/{872.10bd0974.async.js → 7508.a31662a3.async.js} +1 -1
- package/static/dist/{2081.d0d781b1.async.js → 7984.e6bb9378.async.js} +1 -1
- package/static/dist/8317.c44c1ebd.async.js +1 -0
- package/static/dist/874.ae8edb1a.async.js +1 -0
- package/static/dist/8826.37966028.async.js +1 -0
- package/static/dist/{4799.d5ca9f30.async.js → 9313.37acaf13.async.js} +1 -1
- package/static/dist/index.html +2 -2
- package/static/dist/layouts__index.c986408d.async.js +1 -0
- package/static/dist/preload_helper.6482f199.js +1 -0
- package/static/dist/src__pages__404.771168fc.async.js +1 -0
- package/static/dist/src__pages__config__index.de6dca30.async.js +1 -0
- package/static/dist/{src__pages__crontab__detail.6f7c3205.async.js → src__pages__crontab__detail.80d30a01.async.js} +1 -1
- package/static/dist/src__pages__crontab__index.9e38b6dc.async.js +1 -0
- package/static/dist/{src__pages__crontab__logModal.c88ea3b7.async.js → src__pages__crontab__logModal.6a345e8a.async.js} +1 -1
- package/static/dist/src__pages__crontab__modal.78b1e588.async.js +1 -0
- package/static/dist/{src__pages__crontab__type.5895ed02.async.js → src__pages__crontab__type.bde5cda4.async.js} +1 -1
- package/static/dist/src__pages__crontab__viewManageModal.4874669b.async.js +1 -0
- package/static/dist/src__pages__dependence__index.4a0af2b9.async.js +1 -0
- package/static/dist/src__pages__dependence__modal.e6696a7c.async.js +1 -0
- package/static/dist/{src__pages__dependence__type.bdac3725.async.js → src__pages__dependence__type.e48c5c88.async.js} +1 -1
- package/static/dist/src__pages__diff__index.a4176b58.async.js +1 -0
- package/static/dist/src__pages__env__editNameModal.02322e80.async.js +1 -0
- package/static/dist/src__pages__env__index.f3bfe0c7.async.js +1 -0
- package/static/dist/src__pages__env__modal.066399fd.async.js +1 -0
- package/static/dist/src__pages__error__index.656c9940.async.js +1 -0
- package/static/dist/src__pages__initialization__index.75484c39.async.js +1 -0
- package/static/dist/src__pages__log__index.8a782756.async.js +1 -0
- package/static/dist/src__pages__login__index.8a653852.async.js +1 -0
- package/static/dist/src__pages__script__editModal.e7bf71bd.async.js +1 -0
- package/static/dist/src__pages__script__editNameModal.c048343e.async.js +1 -0
- package/static/dist/src__pages__script__index.9d9099c1.async.js +1 -0
- package/static/dist/src__pages__script__renameModal.357c6c72.async.js +1 -0
- package/static/dist/src__pages__script__saveModal.61fcb1fe.async.js +1 -0
- package/static/dist/src__pages__script__setting.f2d78204.async.js +1 -0
- package/static/dist/{src__pages__setting__about.3a1a6f3b.async.js → src__pages__setting__about.3d3c019f.async.js} +1 -1
- package/static/dist/src__pages__setting__appModal.9eeaeee7.async.js +1 -0
- package/static/dist/{src__pages__setting__checkUpdate.0dfdaf7c.async.js → src__pages__setting__checkUpdate.04c00c9c.async.js} +1 -1
- package/static/dist/src__pages__setting__dependence.0dd0969b.async.js +1 -0
- package/static/dist/src__pages__setting__index.46a8e768.async.js +1 -0
- package/static/dist/{src__pages__setting__loginLog.fc87584a.async.js → src__pages__setting__loginLog.cea6056c.async.js} +1 -1
- package/static/dist/src__pages__setting__notification.b038afec.async.js +1 -0
- package/static/dist/{src__pages__setting__other.34ccb2e8.async.js → src__pages__setting__other.0d869d58.async.js} +1 -1
- package/static/dist/{src__pages__setting__progress.75143dca.async.js → src__pages__setting__progress.8823ac90.async.js} +1 -1
- package/static/dist/src__pages__setting__security.af57bd6a.async.js +1 -0
- package/static/dist/src__pages__setting__systemLog.501844bd.async.js +1 -0
- package/static/dist/src__pages__subscription__index.b43143e7.async.js +1 -0
- package/static/dist/{src__pages__subscription__logModal.b3c7c02c.async.js → src__pages__subscription__logModal.02c80eb3.async.js} +1 -1
- package/static/dist/src__pages__subscription__modal.a61ece75.async.js +1 -0
- package/static/dist/umi.e783bacd.js +1 -0
- package/version.yaml +6 -7
- package/static/build/loaders/sentry.js +0 -53
- package/static/dist/2634.a765cd37.async.js +0 -1
- package/static/dist/4642.9e24d86c.async.js +0 -1
- package/static/dist/4865.98e5a005.async.js +0 -1
- package/static/dist/852.15be2189.async.js +0 -1
- package/static/dist/9065.df8d5dcc.async.js +0 -1
- package/static/dist/layouts__index.c164d41f.async.js +0 -1
- package/static/dist/preload_helper.55b35ae0.js +0 -1
- package/static/dist/src__pages__404.6871535b.async.js +0 -1
- package/static/dist/src__pages__config__index.39b5f99f.async.js +0 -1
- package/static/dist/src__pages__crontab__index.55a8714d.async.js +0 -1
- package/static/dist/src__pages__crontab__modal.328fee41.async.js +0 -1
- package/static/dist/src__pages__crontab__viewManageModal.c71ebc5a.async.js +0 -1
- package/static/dist/src__pages__dependence__index.edec638b.async.js +0 -1
- package/static/dist/src__pages__dependence__modal.9fd1176b.async.js +0 -1
- package/static/dist/src__pages__diff__index.8ba53a1e.async.js +0 -1
- package/static/dist/src__pages__env__editNameModal.c35e96f9.async.js +0 -1
- package/static/dist/src__pages__env__index.c799138c.async.js +0 -1
- package/static/dist/src__pages__env__modal.3b0ca9a6.async.js +0 -1
- package/static/dist/src__pages__error__index.0221fcd9.async.js +0 -1
- package/static/dist/src__pages__initialization__index.346725d1.async.js +0 -1
- package/static/dist/src__pages__log__index.2fd615f2.async.js +0 -1
- package/static/dist/src__pages__login__index.1dd6e684.async.js +0 -1
- package/static/dist/src__pages__script__editModal.28caeb56.async.js +0 -1
- package/static/dist/src__pages__script__editNameModal.1155d34c.async.js +0 -1
- package/static/dist/src__pages__script__index.6a212c2d.async.js +0 -1
- package/static/dist/src__pages__script__renameModal.dabfccfd.async.js +0 -1
- package/static/dist/src__pages__script__saveModal.04d43882.async.js +0 -1
- package/static/dist/src__pages__script__setting.9d5ad53c.async.js +0 -1
- package/static/dist/src__pages__setting__appModal.7b3bff1e.async.js +0 -1
- package/static/dist/src__pages__setting__dependence.a9b7ed43.async.js +0 -1
- package/static/dist/src__pages__setting__index.ffa1cdd6.async.js +0 -1
- package/static/dist/src__pages__setting__notification.97b1d997.async.js +0 -1
- package/static/dist/src__pages__setting__security.c777fb87.async.js +0 -1
- package/static/dist/src__pages__setting__systemLog.63e9c69d.async.js +0 -1
- package/static/dist/src__pages__subscription__index.69a6de02.async.js +0 -1
- package/static/dist/src__pages__subscription__modal.aefaf070.async.js +0 -1
- package/static/dist/umi.fb3ed7a0.js +0 -1
- /package/static/dist/{2625.675b6a18.chunk.css → 1883.675b6a18.chunk.css} +0 -0
- /package/static/dist/{872.3fffed15.chunk.css → 7508.3fffed15.chunk.css} +0 -0
package/README-en.md
CHANGED
|
@@ -56,138 +56,15 @@ npm i @whyour/qinglong
|
|
|
56
56
|
|
|
57
57
|
## Deployment
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
[View Documentation](https://qinglong.online/guide/getting-started/installation-guide)
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
# curl -sSL get.docker.com | sh
|
|
63
|
-
docker run -dit \
|
|
64
|
-
-v $PWD/ql/data:/ql/data \
|
|
65
|
-
# The 5700 after the colon is the default port, if QlPort is set, it needs to be the same as QlPort.
|
|
66
|
-
-p 5700:5700 \
|
|
67
|
-
# Deployment paths are not required, e.g. /test.
|
|
68
|
-
-e QlBaseUrl="/" \
|
|
69
|
-
# Deployment port is not required, when using host mode, you can set the port after service startup, default 5700
|
|
70
|
-
-e QlPort="5700" \
|
|
71
|
-
--name qinglong \
|
|
72
|
-
--hostname qinglong \
|
|
73
|
-
--restart unless-stopped \
|
|
74
|
-
whyour/qinglong:latest
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### BaoTa Panel one-click deployment (Recommended)
|
|
78
|
-
|
|
79
|
-
1. To install Pagoda Panel, go to the official website of [BaoTa Panel](https://www.bt.cn/u/EcDAFU), select the official version of the script to download and install.
|
|
80
|
-
|
|
81
|
-
2. After installation, login to Pagoda Panel, click `Docker` in the menu bar, the first time you enter, you will be prompted to install `Docker` service, click Install Now, follow the prompts to complete the installation.
|
|
82
|
-
|
|
83
|
-
3. After the installation is complete, find `Qinglong Panel` in the app shop, click Install, configure the domain name and other basic information to complete the installation.
|
|
84
|
-
|
|
85
|
-
### Docker-compose (Recommended)
|
|
86
|
-
|
|
87
|
-
```bash
|
|
88
|
-
# curl -L https://github.com/docker/compose/releases/download/1.16.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
|
|
89
|
-
mkdir qinglong
|
|
90
|
-
wget https://raw.githubusercontent.com/whyour/qinglong/master/docker/docker-compose.yml
|
|
91
|
-
|
|
92
|
-
# start
|
|
93
|
-
docker-compose up -d
|
|
94
|
-
# stop
|
|
95
|
-
docker-compose down
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
### Podman (Recommended)
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
|
-
# https://podman.io/getting-started/installation
|
|
102
|
-
podman run -dit \
|
|
103
|
-
--network bridge \
|
|
104
|
-
-v $PWD/ql/data:/ql/data \
|
|
105
|
-
# The 5700 after the colon is the default port, if QlPort is set, it needs to be the same as QlPort.
|
|
106
|
-
-p 5700:5700 \
|
|
107
|
-
# Deployment paths are not required, e.g. /test.
|
|
108
|
-
-e QlBaseUrl="/" \
|
|
109
|
-
# Deployment port is not required, when using host mode, you can set the port after service startup, default 5700
|
|
110
|
-
-e QlPort="5700" \
|
|
111
|
-
--name qinglong \
|
|
112
|
-
--hostname qinglong \
|
|
113
|
-
docker.io/whyour/qinglong:latest
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
### Npm (Local)
|
|
61
|
+
## Built-in API
|
|
117
62
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
```bash
|
|
121
|
-
# Debian/Ubuntu
|
|
122
|
-
curl -sL https://deb.nodesource.com/setup_20.x | sudo -E bash -
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
```bash
|
|
126
|
-
npm install -g node-pre-gyp pnpm@8.3.1
|
|
127
|
-
npm install -g @whyour/qinglong
|
|
128
|
-
qinglong
|
|
129
|
-
# Add the environment variables QL_DIR and QL_DATA_DIR when prompted, QL_DATA_DIR must end with /data.
|
|
130
|
-
export QL_DIR=""
|
|
131
|
-
export QL_DATA_DIR=""
|
|
132
|
-
# Run again
|
|
133
|
-
qinglong
|
|
134
|
-
```
|
|
63
|
+
[View Documentation](https://qinglong.online/guide/user-guide/built-in-api)
|
|
135
64
|
|
|
136
65
|
## Built-in commands
|
|
137
66
|
|
|
138
|
-
-
|
|
139
|
-
|
|
140
|
-
```bash
|
|
141
|
-
# Execute in sequence, if a random delay is set, it will be randomly delayed by a certain number of seconds
|
|
142
|
-
task <file_path>
|
|
143
|
-
# Execute in sequence, regardless of whether a random delay is set, all run immediately,
|
|
144
|
-
# and the foreground will output the day, while recorded in the log file
|
|
145
|
-
task <file_path> now
|
|
146
|
-
# Concurrent execution, regardless of whether a random delay is set, are run immediately,
|
|
147
|
-
# the foreground does not generate the day, directly recorded in the log file, and can be specified account execution
|
|
148
|
-
task <file_path> conc <env_name> <account_number>(Optional)
|
|
149
|
-
# Specify the account to execute and run immediately regardless of whether a random delay is set
|
|
150
|
-
task <file_path> desi <env_name> <account_number>
|
|
151
|
-
# Set task timeout
|
|
152
|
-
task -m <max_time> <file_path>
|
|
153
|
-
# Use -- to split, -- followed by a parameter that is passed to the script, as in the following example, the script receives the parameter -u whyour -p password
|
|
154
|
-
task <file_path> -- -u whyour -p password
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
- ql
|
|
158
|
-
|
|
159
|
-
```bash
|
|
160
|
-
# Update and restart Green Dragon
|
|
161
|
-
ql update
|
|
162
|
-
# Run custom scripts extra.sh
|
|
163
|
-
ql extra
|
|
164
|
-
# Adding a single script file
|
|
165
|
-
ql raw <file_url>
|
|
166
|
-
# Add a specific script for a single repository
|
|
167
|
-
ql repo <repo_url> <whitelist> <blacklist> <dependence> <branch>
|
|
168
|
-
# Delete old logs
|
|
169
|
-
ql rmlog <days>
|
|
170
|
-
# Start bot
|
|
171
|
-
ql bot
|
|
172
|
-
# Detecting the Green Dragon environment and repairing it
|
|
173
|
-
ql check
|
|
174
|
-
# Reset the number of login errors
|
|
175
|
-
ql resetlet
|
|
176
|
-
# Disable two-step login
|
|
177
|
-
ql resettfa
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
| **Parameter** | **Description** |
|
|
181
|
-
|---|---|
|
|
182
|
-
| file_url | Script address |
|
|
183
|
-
| repo_url | Repository address |
|
|
184
|
-
| whitelist | The whitelist when pulling the repository, i.e., the string contained in the path of the script to be pulled |
|
|
185
|
-
| blacklist | Blacklisting when pulling repositories, i.e. strings that are not included in the path of the script to be pulled |
|
|
186
|
-
| dependence | Pulling the dependencies needed for the repository will be copied directly from the repository to the repository directory under scripts, regardless of the blacklist |
|
|
187
|
-
| extensions | Pull the branch of the repository |
|
|
188
|
-
| branch | Number of days of logs to be kept |
|
|
189
|
-
| days | File path for task execution |
|
|
190
|
-
| file_path | The name of the environment variable that needs to be concurrent or specified at the time of task execution |
|
|
67
|
+
[View Documentation](https://qinglong.online/guide/user-guide/basic-explanation)
|
|
191
68
|
|
|
192
69
|
## Development
|
|
193
70
|
|
package/README.md
CHANGED
|
@@ -58,136 +58,15 @@ npm i @whyour/qinglong
|
|
|
58
58
|
|
|
59
59
|
## 部署
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
[查看文档](https://qinglong.online/guide/getting-started/installation-guide)
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
# curl -sSL get.docker.com | sh
|
|
65
|
-
docker run -dit \
|
|
66
|
-
-v $PWD/ql/data:/ql/data \
|
|
67
|
-
# 冒号后面的 5700 为默认端口,如果设置了 QlPort, 需要跟 QlPort 保持一致
|
|
68
|
-
-p 5700:5700 \
|
|
69
|
-
# 部署路径非必须,比如 /test
|
|
70
|
-
-e QlBaseUrl="/" \
|
|
71
|
-
# 部署端口非必须,当使用 host 模式时,可以设置服务启动后的端口,默认 5700
|
|
72
|
-
-e QlPort="5700" \
|
|
73
|
-
--name qinglong \
|
|
74
|
-
--hostname qinglong \
|
|
75
|
-
--restart unless-stopped \
|
|
76
|
-
whyour/qinglong:latest
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### 宝塔面板一键部署(推荐)
|
|
80
|
-
|
|
81
|
-
1. 安装宝塔面板,前往 [宝塔面板](https://www.bt.cn/u/EcDAFU) 官网,选择正式版的脚本下载安装
|
|
82
|
-
|
|
83
|
-
2. 安装后登录宝塔面板,在菜单栏中点击 `Docker`,首次进入会提示安装`Docker`服务,点击立即安装,按提示完成安装
|
|
84
|
-
|
|
85
|
-
3. 安装完成后在应用商店中找到`青龙面板`,点击安装,配置域名等基本信息即可完成安装
|
|
86
|
-
|
|
87
|
-
### docker-compose (推荐)
|
|
88
|
-
|
|
89
|
-
```bash
|
|
90
|
-
# curl -L https://github.com/docker/compose/releases/download/1.16.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
|
|
91
|
-
mkdir qinglong && cd $_
|
|
92
|
-
wget https://raw.githubusercontent.com/whyour/qinglong/master/docker/docker-compose.yml
|
|
93
|
-
|
|
94
|
-
# 启动
|
|
95
|
-
docker-compose up -d
|
|
96
|
-
# 停止
|
|
97
|
-
docker-compose down
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
### podman (推荐)
|
|
101
|
-
|
|
102
|
-
```bash
|
|
103
|
-
# https://podman.io/getting-started/installation
|
|
104
|
-
podman run -dit \
|
|
105
|
-
--network bridge \
|
|
106
|
-
-v $PWD/ql/data:/ql/data \
|
|
107
|
-
# 冒号后面的 5700 为默认端口,如果设置了 QlPort, 需要跟 QlPort 保持一致
|
|
108
|
-
-p 5700:5700 \
|
|
109
|
-
# 部署路径非必须,比如 /test
|
|
110
|
-
-e QlBaseUrl="/" \
|
|
111
|
-
# 部署端口非必须,当使用 host 模式时,可以设置服务启动后的端口,默认 5700
|
|
112
|
-
-e QlPort="5700" \
|
|
113
|
-
--name qinglong \
|
|
114
|
-
--hostname qinglong \
|
|
115
|
-
docker.io/whyour/qinglong:latest
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### npm (本地)
|
|
63
|
+
## 内置 API
|
|
119
64
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
```bash
|
|
123
|
-
# Debian/Ubuntu
|
|
124
|
-
curl -sL https://deb.nodesource.com/setup_20.x | sudo -E bash -
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
```bash
|
|
128
|
-
npm install -g node-pre-gyp pnpm@8.3.1
|
|
129
|
-
npm install -g @whyour/qinglong
|
|
130
|
-
qinglong
|
|
131
|
-
# 根据提示增加环境变量 QL_DIR 和 QL_DATA_DIR,QL_DATA_DIR 必须以 /data 结尾
|
|
132
|
-
export QL_DIR=""
|
|
133
|
-
export QL_DATA_DIR=""
|
|
134
|
-
# 再次执行
|
|
135
|
-
qinglong
|
|
136
|
-
```
|
|
65
|
+
[查看文档](https://qinglong.online/guide/user-guide/built-in-api)
|
|
137
66
|
|
|
138
67
|
## 内置命令
|
|
139
68
|
|
|
140
|
-
-
|
|
141
|
-
|
|
142
|
-
```bash
|
|
143
|
-
# 依次执行,如果设置了随机延迟,将随机延迟一定秒数
|
|
144
|
-
task <file_path>
|
|
145
|
-
# 依次执行,无论是否设置了随机延迟,均立即运行,前台会输出日,同时记录在日志文件中
|
|
146
|
-
task <file_path> now
|
|
147
|
-
# 并发执行,无论是否设置了随机延迟,均立即运行,前台不产生日,直接记录在日志文件中,且可指定账号执行
|
|
148
|
-
task <file_path> conc <env_name> <account_number>(可选的)
|
|
149
|
-
# 指定账号执行,无论是否设置了随机延迟,均立即运行
|
|
150
|
-
task <file_path> desi <env_name> <account_number>
|
|
151
|
-
# 设置任务超时时间
|
|
152
|
-
task -m <max_time> <file_path>
|
|
153
|
-
# 使用 -- 分割,-- 后面的参数会传给脚本,下面的例子,脚本就可接收到参数 -u whyour -p password
|
|
154
|
-
task <file_path> -- -u whyour -p password
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
- ql
|
|
158
|
-
|
|
159
|
-
```bash
|
|
160
|
-
# 更新并重启青龙
|
|
161
|
-
ql update
|
|
162
|
-
# 运行自定义脚本extra.sh
|
|
163
|
-
ql extra
|
|
164
|
-
# 添加单个脚本文件
|
|
165
|
-
ql raw <file_url>
|
|
166
|
-
# 添加单个仓库的指定脚本
|
|
167
|
-
ql repo <repo_url> <whitelist> <blacklist> <dependence> <branch> <extensions>
|
|
168
|
-
# 删除旧日志
|
|
169
|
-
ql rmlog <days>
|
|
170
|
-
# 启动tg-bot
|
|
171
|
-
ql bot
|
|
172
|
-
# 检测青龙环境并修复
|
|
173
|
-
ql check
|
|
174
|
-
# 重置登录错误次数
|
|
175
|
-
ql resetlet
|
|
176
|
-
# 禁用两步登录
|
|
177
|
-
ql resettfa
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
| **参数** | **说明** |
|
|
181
|
-
|------------|---------------------------------------------------------------------------------------------|
|
|
182
|
-
| file_url | 脚本地址 |
|
|
183
|
-
| repo_url | 仓库地址 |
|
|
184
|
-
| whitelist | 拉取仓库时的白名单,即就是需要拉取的脚本的路径包含的字符串,多个竖线分割 |
|
|
185
|
-
| blacklist | 拉取仓库时的黑名单,即就是需要拉取的脚本的路径不包含的字符串,多个竖线分割 |
|
|
186
|
-
| dependence | 拉取仓库需要的依赖文件,会直接从仓库拷贝到scripts下的仓库目录,不受黑名单影响,多个竖线分割 |
|
|
187
|
-
| extensions | 拉取仓库的文件后缀,多个竖线分割 |
|
|
188
|
-
| branch | 拉取仓库的分支 |
|
|
189
|
-
| days | 需要保留的日志的天数 |
|
|
190
|
-
| file_path | 任务执行时的文件路径 |
|
|
69
|
+
[查看文档](https://qinglong.online/guide/user-guide/basic-explanation)
|
|
191
70
|
|
|
192
71
|
## 开发
|
|
193
72
|
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
## Reporting a Vulnerability
|
|
2
|
+
|
|
3
|
+
To report a vulnerability, please open a private vulnerability report at <https://github.com/whyour/qinglong/security>.
|
|
4
|
+
|
|
5
|
+
While the discovery of new vulnerabilities is rare, we also recommend always using the latest versions of Qinglong to ensure your application remains as secure as possible.
|
package/back.d.ts
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@whyour/qinglong",
|
|
3
|
-
"version": "2.18.1",
|
|
3
|
+
"version": "2.18.2-1",
|
|
4
4
|
"description": "Timed task management platform supporting Python3, JavaScript, Shell, Typescript",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"public": "npm run build:back && node static/build/public.js",
|
|
26
26
|
"update": "npm run build:back && node static/build/update.js",
|
|
27
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",
|
|
28
|
+
"gen:api": "python3 -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. ./back/protos/api.proto",
|
|
28
29
|
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
|
|
29
30
|
"postinstall": "max setup 2>/dev/null || true",
|
|
30
31
|
"test": "umi-test",
|
|
@@ -77,8 +78,8 @@
|
|
|
77
78
|
},
|
|
78
79
|
"dependencies": {
|
|
79
80
|
"@grpc/grpc-js": "^1.12.3",
|
|
81
|
+
"@grpc/proto-loader": "^0.7.13",
|
|
80
82
|
"@otplib/preset-default": "^12.0.1",
|
|
81
|
-
"@sentry/node": "^8.42.0",
|
|
82
83
|
"body-parser": "^1.20.3",
|
|
83
84
|
"celebrate": "^15.0.3",
|
|
84
85
|
"chokidar": "^4.0.1",
|
|
@@ -87,7 +88,7 @@
|
|
|
87
88
|
"cross-spawn": "^7.0.6",
|
|
88
89
|
"dayjs": "^1.11.13",
|
|
89
90
|
"dotenv": "^16.4.6",
|
|
90
|
-
"express": "^4.21.
|
|
91
|
+
"express": "^4.21.2",
|
|
91
92
|
"express-jwt": "^8.4.1",
|
|
92
93
|
"express-rate-limit": "^7.4.1",
|
|
93
94
|
"express-urlrewrite": "^2.0.3",
|
|
@@ -100,7 +101,6 @@
|
|
|
100
101
|
"jsonwebtoken": "^9.0.2",
|
|
101
102
|
"lodash": "^4.17.21",
|
|
102
103
|
"multer": "1.4.5-lts.1",
|
|
103
|
-
"nedb": "^1.8.0",
|
|
104
104
|
"node-schedule": "^2.1.0",
|
|
105
105
|
"nodemailer": "^6.9.16",
|
|
106
106
|
"p-queue-cjs": "7.3.4",
|
|
@@ -131,7 +131,6 @@
|
|
|
131
131
|
"@monaco-editor/react": "4.2.1",
|
|
132
132
|
"@react-hook/resize-observer": "^2.0.2",
|
|
133
133
|
"react-router-dom": "6.26.1",
|
|
134
|
-
"@sentry/react": "^8.42.0",
|
|
135
134
|
"@types/body-parser": "^1.19.2",
|
|
136
135
|
"@types/cors": "^2.8.12",
|
|
137
136
|
"@types/cross-spawn": "^6.0.2",
|
|
@@ -142,7 +141,6 @@
|
|
|
142
141
|
"@types/jsonwebtoken": "^8.5.8",
|
|
143
142
|
"@types/lodash": "^4.14.185",
|
|
144
143
|
"@types/multer": "^1.4.7",
|
|
145
|
-
"@types/nedb": "^1.8.12",
|
|
146
144
|
"@types/node": "^17.0.21",
|
|
147
145
|
"@types/node-schedule": "^1.3.2",
|
|
148
146
|
"@types/nodemailer": "^6.4.4",
|
|
@@ -158,11 +156,11 @@
|
|
|
158
156
|
"@types/proper-lockfile": "^4.1.4",
|
|
159
157
|
"@uiw/codemirror-extensions-langs": "^4.21.9",
|
|
160
158
|
"@uiw/react-codemirror": "^4.21.9",
|
|
161
|
-
"@umijs/max": "^4.
|
|
159
|
+
"@umijs/max": "^4.4.4",
|
|
162
160
|
"@umijs/ssr-darkreader": "^4.9.45",
|
|
163
161
|
"ahooks": "^3.7.8",
|
|
164
162
|
"ansi-to-react": "^6.1.6",
|
|
165
|
-
"antd": "^4.24.
|
|
163
|
+
"antd": "^4.24.16",
|
|
166
164
|
"antd-img-crop": "^4.23.0",
|
|
167
165
|
"axios": "^1.4.0",
|
|
168
166
|
"compression-webpack-plugin": "9.2.0",
|
package/sample/notify.js
CHANGED
|
@@ -428,7 +428,7 @@ function tgBotNotify(text, desp) {
|
|
|
428
428
|
TG_PROXY_AUTH,
|
|
429
429
|
} = push_config;
|
|
430
430
|
if (TG_BOT_TOKEN && TG_USER_ID) {
|
|
431
|
-
|
|
431
|
+
let options = {
|
|
432
432
|
url: `${TG_API_HOST}/bot${TG_BOT_TOKEN}/sendMessage`,
|
|
433
433
|
json: {
|
|
434
434
|
chat_id: `${TG_USER_ID}`,
|
|
@@ -442,20 +442,20 @@ function tgBotNotify(text, desp) {
|
|
|
442
442
|
};
|
|
443
443
|
if (TG_PROXY_HOST && TG_PROXY_PORT) {
|
|
444
444
|
const { HttpProxyAgent, HttpsProxyAgent } = require('hpagent');
|
|
445
|
-
const
|
|
445
|
+
const _options = {
|
|
446
446
|
keepAlive: true,
|
|
447
447
|
keepAliveMsecs: 1000,
|
|
448
448
|
maxSockets: 256,
|
|
449
449
|
maxFreeSockets: 256,
|
|
450
450
|
proxy: `http://${TG_PROXY_AUTH}${TG_PROXY_HOST}:${TG_PROXY_PORT}`,
|
|
451
451
|
};
|
|
452
|
-
const httpAgent = new HttpProxyAgent(
|
|
453
|
-
const httpsAgent = new HttpsProxyAgent(
|
|
452
|
+
const httpAgent = new HttpProxyAgent(_options);
|
|
453
|
+
const httpsAgent = new HttpsProxyAgent(_options);
|
|
454
454
|
const agent = {
|
|
455
455
|
http: httpAgent,
|
|
456
456
|
https: httpsAgent,
|
|
457
457
|
};
|
|
458
|
-
|
|
458
|
+
options.agent = agent;
|
|
459
459
|
}
|
|
460
460
|
$.post(options, (err, resp, data) => {
|
|
461
461
|
try {
|
package/sample/ql_sample.js
CHANGED
|
@@ -6,4 +6,10 @@
|
|
|
6
6
|
*/
|
|
7
7
|
console.log('test scripts');
|
|
8
8
|
QLAPI.notify('test scripts', 'test desc');
|
|
9
|
+
QLAPI.getEnvs({ searchValue: 'dddd' }).then((x) => {
|
|
10
|
+
console.log('getEnvs', x);
|
|
11
|
+
});
|
|
12
|
+
QLAPI.systemNotify({ title: '123', content: '231' }).then((x) => {
|
|
13
|
+
console.log('systemNotify', x);
|
|
14
|
+
});
|
|
9
15
|
console.log('test desc');
|
package/sample/ql_sample.py
CHANGED
|
@@ -4,6 +4,11 @@ name: script name
|
|
|
4
4
|
定时规则
|
|
5
5
|
cron: 1 9 * * *
|
|
6
6
|
"""
|
|
7
|
+
|
|
7
8
|
print("test script")
|
|
8
|
-
QLAPI.notify(
|
|
9
|
+
print(QLAPI.notify("test script", "test desc"))
|
|
10
|
+
print("test systemNotify")
|
|
11
|
+
print(QLAPI.systemNotify({"title": "test script", "content": "dddd"}))
|
|
12
|
+
print("test getEnvs")
|
|
13
|
+
print(QLAPI.getEnvs({"searchValue": "1"}))
|
|
9
14
|
print("test desc")
|
package/shell/api.sh
CHANGED
|
@@ -178,7 +178,10 @@ update_cron() {
|
|
|
178
178
|
code=$(echo "$api" | jq -r .code)
|
|
179
179
|
message=$(echo "$api" | jq -r .message)
|
|
180
180
|
if [[ $code != 200 ]]; then
|
|
181
|
-
|
|
181
|
+
if [[ ! $message ]]; then
|
|
182
|
+
message="$api"
|
|
183
|
+
fi
|
|
184
|
+
echo -e "${message}"
|
|
182
185
|
fi
|
|
183
186
|
}
|
|
184
187
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const grpc = require('@grpc/grpc-js');
|
|
2
|
+
const protoLoader = require('@grpc/proto-loader');
|
|
3
|
+
|
|
4
|
+
const PROTO_PATH = `${process.env.QL_DIR}/back/protos/api.proto`;
|
|
5
|
+
const options = {
|
|
6
|
+
keepCase: true,
|
|
7
|
+
longs: String,
|
|
8
|
+
enums: String,
|
|
9
|
+
defaults: true,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const packageDefinition = protoLoader.loadSync(PROTO_PATH, options);
|
|
13
|
+
const apiProto = grpc.loadPackageDefinition(packageDefinition).com.ql.api;
|
|
14
|
+
|
|
15
|
+
const client = new apiProto.Api(
|
|
16
|
+
`0.0.0.0:5500`,
|
|
17
|
+
grpc.credentials.createInsecure(),
|
|
18
|
+
{ 'grpc.enable_http_proxy': 0 },
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
const promisify = (fn) => {
|
|
22
|
+
return (...args) => {
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
fn.call(client, ...args, (err, response) => {
|
|
25
|
+
if (err) return reject(err);
|
|
26
|
+
resolve(response);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const api = {
|
|
33
|
+
getEnvs: promisify(client.GetEnvs),
|
|
34
|
+
createEnv: promisify(client.CreateEnv),
|
|
35
|
+
updateEnv: promisify(client.UpdateEnv),
|
|
36
|
+
deleteEnvs: promisify(client.DeleteEnvs),
|
|
37
|
+
moveEnv: promisify(client.MoveEnv),
|
|
38
|
+
disableEnvs: promisify(client.DisableEnvs),
|
|
39
|
+
enableEnvs: promisify(client.EnableEnvs),
|
|
40
|
+
updateEnvNames: promisify(client.UpdateEnvNames),
|
|
41
|
+
getEnvById: promisify(client.GetEnvById),
|
|
42
|
+
systemNotify: promisify(client.SystemNotify),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
module.exports = api;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import json
|
|
3
|
+
import tempfile
|
|
4
|
+
import os
|
|
5
|
+
from typing import Dict, List
|
|
6
|
+
from functools import wraps
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def error_handler(func):
|
|
10
|
+
@wraps(func)
|
|
11
|
+
def wrapper(*args, **kwargs):
|
|
12
|
+
try:
|
|
13
|
+
return func(*args, **kwargs)
|
|
14
|
+
except json.JSONDecodeError as e:
|
|
15
|
+
raise Exception(f"parse json error: {str(e)}")
|
|
16
|
+
except subprocess.SubprocessError as e:
|
|
17
|
+
raise Exception(f"node process error: {str(e)}")
|
|
18
|
+
except Exception as e:
|
|
19
|
+
raise Exception(f"unknown error: {str(e)}")
|
|
20
|
+
|
|
21
|
+
return wrapper
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Client:
|
|
25
|
+
def __init__(self):
|
|
26
|
+
self.temp_dir = tempfile.mkdtemp(prefix="node_client_")
|
|
27
|
+
self.temp_script = os.path.join(self.temp_dir, "temp_script.js")
|
|
28
|
+
|
|
29
|
+
def __del__(self):
|
|
30
|
+
try:
|
|
31
|
+
if os.path.exists(self.temp_script):
|
|
32
|
+
os.remove(self.temp_script)
|
|
33
|
+
os.rmdir(self.temp_dir)
|
|
34
|
+
except Exception:
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
@error_handler
|
|
38
|
+
def _execute_node(self, method: str, params: Dict = None) -> Dict:
|
|
39
|
+
node_code = f"""
|
|
40
|
+
const api = require('{os.getenv("QL_DIR")}/shell/preload/client.js');
|
|
41
|
+
|
|
42
|
+
(async () => {{
|
|
43
|
+
try {{
|
|
44
|
+
const result = await api.{method}({json.dumps(params) if params else ''});
|
|
45
|
+
console.log(JSON.stringify(result));
|
|
46
|
+
}} catch (error) {{
|
|
47
|
+
console.error(JSON.stringify({{
|
|
48
|
+
error: error.message,
|
|
49
|
+
stack: error.stack
|
|
50
|
+
}}));
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}}
|
|
53
|
+
}})();
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
with open(self.temp_script, "w", encoding="utf-8") as f:
|
|
57
|
+
f.write(node_code)
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
result = subprocess.run(
|
|
61
|
+
["node", self.temp_script],
|
|
62
|
+
capture_output=True,
|
|
63
|
+
text=True,
|
|
64
|
+
timeout=30,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
if result.returncode != 0:
|
|
68
|
+
error_data = json.loads(result.stderr)
|
|
69
|
+
raise Exception(f"{error_data.get('stack')}")
|
|
70
|
+
|
|
71
|
+
return json.loads(result.stdout)
|
|
72
|
+
except subprocess.TimeoutExpired:
|
|
73
|
+
raise Exception("node process timeout")
|
|
74
|
+
|
|
75
|
+
@error_handler
|
|
76
|
+
def getEnvs(self, params: Dict = None) -> Dict:
|
|
77
|
+
return self._execute_node("getEnvs", params)
|
|
78
|
+
|
|
79
|
+
@error_handler
|
|
80
|
+
def createEnv(self, data: Dict) -> Dict:
|
|
81
|
+
return self._execute_node("createEnv", data)
|
|
82
|
+
|
|
83
|
+
@error_handler
|
|
84
|
+
def updateEnv(self, data: Dict) -> Dict:
|
|
85
|
+
return self._execute_node("updateEnv", data)
|
|
86
|
+
|
|
87
|
+
@error_handler
|
|
88
|
+
def deleteEnvs(self, data: Dict) -> Dict:
|
|
89
|
+
return self._execute_node("deleteEnvs", data)
|
|
90
|
+
|
|
91
|
+
@error_handler
|
|
92
|
+
def moveEnv(self, data: Dict) -> Dict:
|
|
93
|
+
return self._execute_node("moveEnv", data)
|
|
94
|
+
|
|
95
|
+
@error_handler
|
|
96
|
+
def disableEnvs(self, data: Dict) -> Dict:
|
|
97
|
+
return self._execute_node("disableEnvs", data)
|
|
98
|
+
|
|
99
|
+
@error_handler
|
|
100
|
+
def enableEnvs(self, data: Dict) -> Dict:
|
|
101
|
+
return self._execute_node("enableEnvs", data)
|
|
102
|
+
|
|
103
|
+
@error_handler
|
|
104
|
+
def updateEnvNames(self, data: Dict) -> Dict:
|
|
105
|
+
return self._execute_node("updateEnvNames", data)
|
|
106
|
+
|
|
107
|
+
@error_handler
|
|
108
|
+
def getEnvById(self, data: Dict) -> Dict:
|
|
109
|
+
return self._execute_node("getEnvById", data)
|
|
110
|
+
|
|
111
|
+
@error_handler
|
|
112
|
+
def systemNotify(self, data: Dict) -> Dict:
|
|
113
|
+
return self._execute_node("systemNotify", data)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const { execSync } = require('child_process');
|
|
2
|
+
const client = require('./client.js');
|
|
2
3
|
require(`./env.js`);
|
|
3
4
|
|
|
4
5
|
function expandRange(rangeStr, max) {
|
|
@@ -100,6 +101,7 @@ try {
|
|
|
100
101
|
const { sendNotify } = require('./notify.js');
|
|
101
102
|
global.QLAPI = {
|
|
102
103
|
notify: sendNotify,
|
|
104
|
+
...client,
|
|
103
105
|
};
|
|
104
106
|
} catch (error) {
|
|
105
107
|
console.log(`run builtin code error: `, error, '\n');
|
|
@@ -6,6 +6,7 @@ import builtins
|
|
|
6
6
|
import sys
|
|
7
7
|
import env
|
|
8
8
|
import signal
|
|
9
|
+
from client import Client
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
def try_parse_int(value):
|
|
@@ -108,7 +109,7 @@ try:
|
|
|
108
109
|
|
|
109
110
|
from notify import send
|
|
110
111
|
|
|
111
|
-
class BaseApi:
|
|
112
|
+
class BaseApi(Client):
|
|
112
113
|
def notify(self, *args, **kwargs):
|
|
113
114
|
return send(*args, **kwargs)
|
|
114
115
|
|
package/shell/share.sh
CHANGED
|
@@ -438,8 +438,14 @@ clear_env() {
|
|
|
438
438
|
}
|
|
439
439
|
|
|
440
440
|
handle_task_start() {
|
|
441
|
-
|
|
442
|
-
|
|
441
|
+
local error_message=""
|
|
442
|
+
if [[ $ID ]]; then
|
|
443
|
+
local error=$(update_cron "\"$ID\"" "0" "$$" "$log_path" "$begin_timestamp")
|
|
444
|
+
if [[ $error ]]; then
|
|
445
|
+
error_message=", 任务状态更新失败(${error})"
|
|
446
|
+
fi
|
|
447
|
+
fi
|
|
448
|
+
echo -e "## 开始执行... ${begin_time}${error_message}\n"
|
|
443
449
|
}
|
|
444
450
|
|
|
445
451
|
run_task_before() {
|
|
@@ -472,8 +478,13 @@ handle_task_end() {
|
|
|
472
478
|
|
|
473
479
|
[[ "$diff_time" == 0 ]] && diff_time=1
|
|
474
480
|
|
|
475
|
-
|
|
476
|
-
|
|
481
|
+
if [[ $ID ]]; then
|
|
482
|
+
local error=$(update_cron "\"$ID\"" "1" "" "$log_path" "$begin_timestamp" "$diff_time")
|
|
483
|
+
if [[ $error ]]; then
|
|
484
|
+
error_message=", 任务状态更新失败(${error})"
|
|
485
|
+
fi
|
|
486
|
+
fi
|
|
487
|
+
echo -e "\n## 执行结束$suffix... $end_time 耗时 $diff_time 秒${error_message} "
|
|
477
488
|
}
|
|
478
489
|
|
|
479
490
|
init_env
|