mirror of
https://github.com/whyour/qinglong.git
synced 2026-08-06 16:54:33 +08:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 201f578bbc | |||
| ce9aa369d2 | |||
| c5c41c0859 | |||
| d3009f82dd | |||
| 0eb9a1fdb0 | |||
| 83f6d9926a | |||
| 14134842b0 | |||
| 4c094c4710 | |||
| 3ac41075fd | |||
| fdc97773d1 |
@@ -39,11 +39,11 @@ export default defineConfig({
|
||||
scripts: [
|
||||
'https://gw.alipayobjects.com/os/lib/react/16.13.1/umd/react.production.min.js',
|
||||
'https://gw.alipayobjects.com/os/lib/react-dom/16.13.1/umd/react-dom.production.min.js',
|
||||
'https://cdn.jsdelivr.net/npm/darkreader@4.9.40/darkreader.min.js',
|
||||
'https://cdn.jsdelivr.net/npm/codemirror@5/lib/codemirror.min.js',
|
||||
'https://cdn.jsdelivr.net/npm/codemirror@5/mode/shell/shell.js',
|
||||
'https://cdn.jsdelivr.net/npm/codemirror@5/mode/python/python.js',
|
||||
'https://cdn.jsdelivr.net/npm/codemirror@5/mode/javascript/javascript.js',
|
||||
'https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js',
|
||||
'https://unpkg.zhimg.com/darkreader@4.9.40/darkreader.js',
|
||||
'https://unpkg.zhimg.com/codemirror@5/lib/codemirror.js',
|
||||
'https://unpkg.zhimg.com/codemirror@5/mode/shell/shell.js',
|
||||
'https://unpkg.zhimg.com/codemirror@5/mode/python/python.js',
|
||||
'https://unpkg.zhimg.com/codemirror@5/mode/javascript/javascript.js',
|
||||
'https://unpkg.zhimg.com/sockjs-client@1/dist/sockjs.min.js',
|
||||
],
|
||||
});
|
||||
|
||||
+60
-79
@@ -1,7 +1,6 @@
|
||||
import DataStore from 'nedb';
|
||||
import config from '../config';
|
||||
import Logger from './logger';
|
||||
import fs from 'fs';
|
||||
import { fileExist } from '../config/util';
|
||||
import { EnvModel } from '../data/env';
|
||||
import { CrontabModel } from '../data/cron';
|
||||
@@ -10,91 +9,75 @@ import { AppModel } from '../data/open';
|
||||
import { AuthModel } from '../data/auth';
|
||||
import { sequelize } from '../data';
|
||||
|
||||
interface Dbs {
|
||||
cronDb: DataStore;
|
||||
dependenceDb: DataStore;
|
||||
envDb: DataStore;
|
||||
appDb: DataStore;
|
||||
authDb: DataStore;
|
||||
}
|
||||
|
||||
const db: Dbs = {} as any;
|
||||
|
||||
async function truncateDb() {
|
||||
return new Promise(async (resolve) => {
|
||||
const files = [
|
||||
config.cronDbFile,
|
||||
config.dependenceDbFile,
|
||||
config.envDbFile,
|
||||
config.appDbFile,
|
||||
config.authDbFile,
|
||||
];
|
||||
|
||||
for (const file of files) {
|
||||
const _fileExist = await fileExist(file);
|
||||
if (_fileExist && fs.statSync(file).size >= 1024 * 1024 * 500) {
|
||||
fs.truncateSync(file, 1024 * 1024 * 500);
|
||||
}
|
||||
}
|
||||
resolve(null);
|
||||
});
|
||||
}
|
||||
export default async () => {
|
||||
try {
|
||||
await truncateDb();
|
||||
await sequelize.sync({ alter: true });
|
||||
|
||||
db.cronDb = new DataStore({ filename: config.cronDbFile, autoload: true });
|
||||
db.dependenceDb = new DataStore({
|
||||
filename: config.dependenceDbFile,
|
||||
autoload: true,
|
||||
});
|
||||
db.envDb = new DataStore({ filename: config.envDbFile, autoload: true });
|
||||
db.appDb = new DataStore({ filename: config.appDbFile, autoload: true });
|
||||
db.authDb = new DataStore({ filename: config.authDbFile, autoload: true });
|
||||
const crondbExist = await fileExist(config.cronDbFile);
|
||||
const dependenceDbExist = await fileExist(config.dependenceDbFile);
|
||||
const envDbExist = await fileExist(config.envDbFile);
|
||||
const appDbExist = await fileExist(config.appDbFile);
|
||||
const authDbExist = await fileExist(config.authDbFile);
|
||||
|
||||
// compaction data file
|
||||
db.cronDb.persistence.compactDatafile();
|
||||
db.envDb.persistence.compactDatafile();
|
||||
db.dependenceDb.persistence.compactDatafile();
|
||||
db.appDb.persistence.compactDatafile();
|
||||
db.authDb.persistence.compactDatafile();
|
||||
|
||||
try {
|
||||
await sequelize.sync({ alter: true });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
const cronCount = await CrontabModel.count();
|
||||
const dependenceCount = await DependenceModel.count();
|
||||
const envCount = await EnvModel.count();
|
||||
const appCount = await AppModel.count();
|
||||
const authCount = await AuthModel.count();
|
||||
if (crondbExist && cronCount === 0) {
|
||||
const cronDb = new DataStore({
|
||||
filename: config.cronDbFile,
|
||||
autoload: true,
|
||||
});
|
||||
cronDb.persistence.compactDatafile();
|
||||
cronDb.find({}).exec(async (err, docs) => {
|
||||
await CrontabModel.bulkCreate(docs, { ignoreDuplicates: true });
|
||||
});
|
||||
}
|
||||
|
||||
// migrate db to sqlite
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
const count = await CrontabModel.count();
|
||||
if (count !== 0) {
|
||||
return;
|
||||
}
|
||||
db.cronDb.find({}).exec(async (err, docs) => {
|
||||
await CrontabModel.bulkCreate(docs);
|
||||
});
|
||||
if (dependenceDbExist && dependenceCount === 0) {
|
||||
const dependenceDb = new DataStore({
|
||||
filename: config.dependenceDbFile,
|
||||
autoload: true,
|
||||
});
|
||||
dependenceDb.persistence.compactDatafile();
|
||||
dependenceDb.find({}).exec(async (err, docs) => {
|
||||
await DependenceModel.bulkCreate(docs, { ignoreDuplicates: true });
|
||||
});
|
||||
}
|
||||
|
||||
db.dependenceDb.find({}).exec(async (err, docs) => {
|
||||
await DependenceModel.bulkCreate(docs);
|
||||
});
|
||||
if (envDbExist && envCount === 0) {
|
||||
const envDb = new DataStore({
|
||||
filename: config.envDbFile,
|
||||
autoload: true,
|
||||
});
|
||||
envDb.persistence.compactDatafile();
|
||||
envDb.find({}).exec(async (err, docs) => {
|
||||
await EnvModel.bulkCreate(docs, { ignoreDuplicates: true });
|
||||
});
|
||||
}
|
||||
|
||||
db.envDb.find({}).exec(async (err, docs) => {
|
||||
await EnvModel.bulkCreate(docs);
|
||||
});
|
||||
if (appDbExist && appCount === 0) {
|
||||
const appDb = new DataStore({
|
||||
filename: config.appDbFile,
|
||||
autoload: true,
|
||||
});
|
||||
appDb.persistence.compactDatafile();
|
||||
appDb.find({}).exec(async (err, docs) => {
|
||||
await AppModel.bulkCreate(docs, { ignoreDuplicates: true });
|
||||
});
|
||||
}
|
||||
|
||||
db.appDb.find({}).exec(async (err, docs) => {
|
||||
await AppModel.bulkCreate(docs);
|
||||
});
|
||||
|
||||
db.authDb.find({}).exec(async (err, docs) => {
|
||||
await AuthModel.bulkCreate(docs);
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}, 5000);
|
||||
if (authDbExist && authCount === 0) {
|
||||
const authDb = new DataStore({
|
||||
filename: config.authDbFile,
|
||||
autoload: true,
|
||||
});
|
||||
authDb.persistence.compactDatafile();
|
||||
authDb.find({}).exec(async (err, docs) => {
|
||||
await AuthModel.bulkCreate(docs, { ignoreDuplicates: true });
|
||||
});
|
||||
}
|
||||
|
||||
Logger.info('✌️ DB loaded');
|
||||
} catch (error) {
|
||||
@@ -102,5 +85,3 @@ export default async () => {
|
||||
Logger.info(error);
|
||||
}
|
||||
};
|
||||
|
||||
export const dbs: Dbs = db;
|
||||
|
||||
@@ -163,7 +163,10 @@ export default class CronService {
|
||||
}
|
||||
}
|
||||
try {
|
||||
const result = await CrontabModel.findAll({ where: query });
|
||||
const result = await CrontabModel.findAll({
|
||||
where: query,
|
||||
order: [['updatedAt', 'DESC']],
|
||||
});
|
||||
return result as any;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
@@ -209,7 +212,7 @@ export default class CronService {
|
||||
}
|
||||
|
||||
await CrontabModel.update(
|
||||
{ status: CrontabStatus.queued, pid: undefined },
|
||||
{ status: CrontabStatus.idle, pid: undefined },
|
||||
{ where: { id: ids } },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Service, Inject } from 'typedi';
|
||||
import winston from 'winston';
|
||||
import config from '../config';
|
||||
import DataStore from 'nedb';
|
||||
import {
|
||||
Dependence,
|
||||
InstallDependenceCommandTypes,
|
||||
@@ -64,6 +63,7 @@ export default class DependenceService {
|
||||
);
|
||||
const docs = await DependenceModel.findAll({ where: { id: ids } });
|
||||
this.installOrUninstallDependencies(docs, false);
|
||||
return docs;
|
||||
}
|
||||
|
||||
public async removeDb(ids: number[]) {
|
||||
|
||||
@@ -3,7 +3,6 @@ import winston from 'winston';
|
||||
import { getFileContentByName } from '../config/util';
|
||||
import config from '../config';
|
||||
import * as fs from 'fs';
|
||||
import DataStore from 'nedb';
|
||||
import { Env, EnvModel, EnvStatus, initEnvPosition } from '../data/env';
|
||||
import _ from 'lodash';
|
||||
import { Op } from 'sequelize';
|
||||
|
||||
+11
-2
@@ -2,7 +2,6 @@ import { Service, Inject } from 'typedi';
|
||||
import winston from 'winston';
|
||||
import { createRandomString } from '../config/util';
|
||||
import config from '../config';
|
||||
import DataStore from 'nedb';
|
||||
import { App, AppModel } from '../data/open';
|
||||
import { v4 as uuidV4 } from 'uuid';
|
||||
import sequelize, { Op } from 'sequelize';
|
||||
@@ -54,7 +53,17 @@ export default class OpenService {
|
||||
}
|
||||
|
||||
public async resetSecret(id: number): Promise<App> {
|
||||
const tab: any = { client_secret: createRandomString(24, 24), tokens: [] };
|
||||
const tab: any = {
|
||||
client_secret: createRandomString(24, 24),
|
||||
tokens: [],
|
||||
id,
|
||||
};
|
||||
// const doc = await this.get(id);
|
||||
// const tab = new App({ ...doc });
|
||||
// tab.client_secret = createRandomString(24, 24);
|
||||
// tab.tokens = [];
|
||||
// const newDoc = await this.updateDb(tab);
|
||||
// return newDoc;
|
||||
const newDoc = await this.updateDb(tab);
|
||||
return newDoc;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import ScheduleService from './schedule';
|
||||
import { spawn } from 'child_process';
|
||||
import SockService from './sock';
|
||||
import got from 'got';
|
||||
import { dbs } from '../loaders/db';
|
||||
|
||||
@Service()
|
||||
export default class SystemService {
|
||||
|
||||
@@ -16,8 +16,8 @@ DefaultCronRule=""
|
||||
## ql repo命令拉取脚本时需要拉取的文件后缀,直接写文件后缀名即可
|
||||
RepoFileExtensions="js py"
|
||||
|
||||
## 由于github仓库拉取较慢,所以会默认添加代理前缀,如不需要请移除
|
||||
GithubProxyUrl="https://ghproxy.com/"
|
||||
## 代理地址,支持http/https/socks,例如 http://127.0.0.1:7890
|
||||
ProxyUrl=""
|
||||
|
||||
## 设置定时任务执行的超时时间,默认1h,后缀"s"代表秒(默认值), "m"代表分, "h"代表小时, "d"代表天
|
||||
CommandTimeoutTime="1h"
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ dir_shell=/ql/shell
|
||||
. $dir_shell/share.sh
|
||||
|
||||
if [[ -z ${BotRepoUrl} ]]; then
|
||||
url="${github_proxy_url}https://github.com/SuMaiKaDe/bot.git"
|
||||
url="https://github.com/SuMaiKaDe/bot.git"
|
||||
repo_path="${dir_repo}/dockerbot"
|
||||
else
|
||||
url=${BotRepoUrl}
|
||||
|
||||
+21
-1
@@ -67,7 +67,7 @@ import_config() {
|
||||
[[ -f $file_env ]] && . $file_env
|
||||
|
||||
command_timeout_time=${CommandTimeoutTime:-"1h"}
|
||||
github_proxy_url=${GithubProxyUrl:-""}
|
||||
proxy_url=${ProxyUrl:-""}
|
||||
file_extensions=${RepoFileExtensions:-"js py"}
|
||||
|
||||
if [[ -n "${DefaultCronRule}" ]]; then
|
||||
@@ -77,6 +77,18 @@ import_config() {
|
||||
fi
|
||||
}
|
||||
|
||||
set_proxy() {
|
||||
if [[ $proxy_url ]]; then
|
||||
export http_proxy="${proxy_url}"
|
||||
export https_proxy="${proxy_url}"
|
||||
fi
|
||||
}
|
||||
|
||||
unset_proxy() {
|
||||
unset http_proxy
|
||||
unset https_proxy
|
||||
}
|
||||
|
||||
make_dir() {
|
||||
local dir=$1
|
||||
if [[ ! -d $dir ]]; then
|
||||
@@ -287,7 +299,11 @@ git_clone_scripts() {
|
||||
local branch=$3
|
||||
[[ $branch ]] && local part_cmd="-b $branch "
|
||||
echo -e "开始克隆仓库 $url 到 $dir\n"
|
||||
|
||||
set_proxy
|
||||
git clone $part_cmd $url $dir
|
||||
unset_proxy
|
||||
|
||||
exit_status=$?
|
||||
}
|
||||
|
||||
@@ -298,10 +314,14 @@ git_pull_scripts() {
|
||||
[[ $branch ]] && local part_cmd="origin/${branch}"
|
||||
cd $dir_work
|
||||
echo -e "开始更新仓库:$dir_work\n"
|
||||
|
||||
set_proxy
|
||||
git fetch --all
|
||||
exit_status=$?
|
||||
git reset --hard $part_cmd
|
||||
git pull
|
||||
unset_proxy
|
||||
|
||||
cd $dir_current
|
||||
}
|
||||
|
||||
|
||||
+6
-12
@@ -151,11 +151,6 @@ update_repo() {
|
||||
make_dir "${dir_scripts}/${uniq_path}"
|
||||
|
||||
local formatUrl="$url"
|
||||
if [[ $github_proxy_url ]]; then
|
||||
if [[ $url =~ "github.com" ]] || [[ $url =~ "githubusercontent.com" ]]; then
|
||||
[[ ! $url =~ "https://ghproxy.com" ]] && formatUrl="${github_proxy_url}${url}"
|
||||
fi
|
||||
fi
|
||||
if [[ -d ${repo_path}/.git ]]; then
|
||||
reset_romote_url ${repo_path} "${formatUrl}" "${branch}"
|
||||
git_pull_scripts ${repo_path} "${branch}"
|
||||
@@ -183,15 +178,14 @@ update_raw() {
|
||||
echo -e "--------------------------------------------------------------\n"
|
||||
local url="$1"
|
||||
local raw_url="$url"
|
||||
if [[ $github_proxy_url ]]; then
|
||||
if [[ $url =~ "github.com" ]] || [[ $url =~ "githubusercontent.com" ]]; then
|
||||
[[ ! $url =~ "https://ghproxy.com" ]] && raw_url="${github_proxy_url}${url}"
|
||||
fi
|
||||
fi
|
||||
local suffix="${raw_url##*.}"
|
||||
local raw_file_name="${uniq_path}.${suffix}"
|
||||
echo -e "开始下载:${raw_url} \n\n保存路径:$dir_raw/${raw_file_name}\n"
|
||||
|
||||
set_proxy
|
||||
wget -q --no-check-certificate -O "$dir_raw/${raw_file_name}.new" ${raw_url}
|
||||
unset_proxy
|
||||
|
||||
if [[ $? -eq 0 ]]; then
|
||||
mv "$dir_raw/${raw_file_name}.new" "$dir_raw/${raw_file_name}"
|
||||
echo -e "下载 ${raw_file_name} 成功...\n"
|
||||
@@ -259,7 +253,7 @@ update_qinglong() {
|
||||
|
||||
local no_restart="$1"
|
||||
[[ -f $dir_root/package.json ]] && ql_depend_old=$(cat $dir_root/package.json)
|
||||
reset_romote_url ${dir_root} "${github_proxy_url}https://github.com/whyour/qinglong.git" "master"
|
||||
reset_romote_url ${dir_root} "https://github.com/whyour/qinglong.git" "master"
|
||||
git_pull_scripts $dir_root "master"
|
||||
|
||||
if [[ $exit_status -eq 0 ]]; then
|
||||
@@ -274,7 +268,7 @@ update_qinglong() {
|
||||
echo -e "\n更新$dir_root失败,请检查原因...\n"
|
||||
fi
|
||||
|
||||
local url="${github_proxy_url}https://github.com/whyour/qinglong-static.git"
|
||||
local url="https://github.com/whyour/qinglong-static.git"
|
||||
if [[ -d ${ql_static_repo}/.git ]]; then
|
||||
reset_romote_url ${ql_static_repo} ${url} "master"
|
||||
git_pull_scripts ${ql_static_repo} "master"
|
||||
|
||||
@@ -61,7 +61,7 @@ const CronLogModal = ({
|
||||
<Countdown
|
||||
className="inline-countdown"
|
||||
format="ss"
|
||||
value={Date.now() + 1000 * 10}
|
||||
value={Date.now() + 1000 * 30}
|
||||
/>
|
||||
秒后自动刷新
|
||||
</span>
|
||||
@@ -70,7 +70,7 @@ const CronLogModal = ({
|
||||
});
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 10000);
|
||||
}, 30000);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -94,7 +94,22 @@ const Dependence = ({ headerStyle, isPhone, socketMessage }: any) => {
|
||||
dataIndex: 'timestamp',
|
||||
align: 'center' as const,
|
||||
render: (text: string, record: any) => {
|
||||
return <span>{new Date(record.timestamp).toLocaleString()}</span>;
|
||||
const language = navigator.language || navigator.languages[0];
|
||||
const time = record.createdAt || record.timestamp;
|
||||
const date = new Date(time)
|
||||
.toLocaleString(language, {
|
||||
hour12: false,
|
||||
})
|
||||
.replace(' 24:', ' 00:');
|
||||
return (
|
||||
<Tooltip
|
||||
placement="topLeft"
|
||||
title={date}
|
||||
trigger={['hover', 'click']}
|
||||
>
|
||||
<span>{date}</span>
|
||||
</Tooltip>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
Vendored
+2
-1
@@ -151,7 +151,8 @@ const Env = ({ headerStyle, isPhone, theme }: any) => {
|
||||
},
|
||||
render: (text: string, record: any) => {
|
||||
const language = navigator.language || navigator.languages[0];
|
||||
const date = new Date(text)
|
||||
const time = record.updatedAt || record.timestamp;
|
||||
const date = new Date(time)
|
||||
.toLocaleString(language, {
|
||||
hour12: false,
|
||||
})
|
||||
|
||||
Vendored
+13
-9
@@ -36,16 +36,20 @@ const EnvModal = ({
|
||||
} else {
|
||||
payload = { ...values, id: env.id };
|
||||
}
|
||||
const { code, data } = await request[method](`${config.apiPrefix}envs`, {
|
||||
data: payload,
|
||||
});
|
||||
if (code === 200) {
|
||||
message.success(env ? '更新变量成功' : '新建变量成功');
|
||||
} else {
|
||||
message.error(data);
|
||||
try {
|
||||
const { code, data } = await request[method](`${config.apiPrefix}envs`, {
|
||||
data: payload,
|
||||
});
|
||||
if (code === 200) {
|
||||
message.success(env ? '更新变量成功' : '新建变量成功');
|
||||
} else {
|
||||
message.error(data);
|
||||
}
|
||||
setLoading(false);
|
||||
handleCancel(data);
|
||||
} catch (error: any) {
|
||||
setLoading(false);
|
||||
}
|
||||
setLoading(false);
|
||||
handleCancel(data);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -172,7 +172,7 @@ const CheckUpdate = ({ socketMessage }: any) => {
|
||||
<Countdown
|
||||
className="inline-countdown"
|
||||
format="ss"
|
||||
value={Date.now() + 1000 * 10}
|
||||
value={Date.now() + 1000 * 30}
|
||||
/>
|
||||
秒后自动刷新
|
||||
</span>
|
||||
@@ -181,7 +181,7 @@ const CheckUpdate = ({ socketMessage }: any) => {
|
||||
});
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 10000);
|
||||
}, 30000);
|
||||
}
|
||||
}, [socketMessage]);
|
||||
|
||||
|
||||
+12
-7
@@ -1,8 +1,13 @@
|
||||
export const version = '2.11.0';
|
||||
export const changeLogLink = 'https://t.me/jiao_long/254';
|
||||
export const changeLog = `2.11.0 版本说明
|
||||
1. 使用sqlite替换nedb,增加数据库稳定性
|
||||
2. 任务添加标签功能,感谢https://github.com/kilo5hz
|
||||
3. 支持自定义bot仓库,感谢https://github.com/chiupam
|
||||
5. 其他bug修复
|
||||
export const version = '2.11.1';
|
||||
export const changeLogLink = 'https://t.me/jiao_long/261';
|
||||
export const changeLog = `2.11.1 版本说明
|
||||
1. 修复openapi获取token,token认证
|
||||
2. 修复环境变量搜索,排序,更新
|
||||
3. 修复重置应用秘钥
|
||||
4. 修复环境变量更新时间显示
|
||||
5. 修复定时默认任务排序
|
||||
6. task支持运行pyc文件,感谢https://github.com/chiupam
|
||||
6. 移除ghproxy默认代理,增加新配置ProxyUrl,支持http或者socks代理。例如 http://127.0.0.1:7890
|
||||
7. 更换JavaScript cdn地址
|
||||
8. 其他bug修复
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user