mirror of
https://github.com/whyour/qinglong.git
synced 2025-05-22 22:36:06 +08:00
全新青龙2.0 (#65)
* 重构shell (#17) * 更新正则 * 更新update命令 * 移除测试代码 * 重构删除日志命令 * 更新entrypoint * 更新dockerfile * 完善shell调用 * 修复share shell引用 * 修复entrypoint * 修复share shell * 修复share.sh * 修改依赖重装逻辑 * 更新docker entrypoint * curl 使用静默模式 * 更新ql raw * 修复添加单个任务 * 修复shell语法 * 添加定时任务进程 * 更新默认定时任务 * 更新定时任务重启schedule * 更新青龙重启逻辑 * 修复定时任务列表创建 * 修复schedule进程 * 修复entrypoint * 更新task命令 * pm2 restart替换成reload * 修复task命令参数引入 * 完善ql repo命令 * 修复update.sh * 更新ql repo命令 * ql repo添加登录验证,修复package.json示例 * 修复定时任务命令补全 * 修改默认cron端口 * 修复cron日志弹框异常 * 修改cron新建label * 修复ql repo命令 * 修复cron格式验证 * 修改日志目录格式 * 修改青龙remote url * 修复添加定时cron匹配 * 添加定时任务超时时间设置 * 暂时移除timeout命令 * 恢复定时任务timeout * 修复cookie.sh引用 * 修复shell变量自加 * 修复ck更新状态同步 * 增加tg bot测试,修改增删任务通知 * 修复shell函数返回值 * 修改添加任务日志打印 * 修改entrypoint日志 * 修复api日志打印 * 修改api日志打印 * 定时任务支持批量启用禁用删除运行 * 修改cron管理操作按钮响应样式 * 更新bot启动脚本 * 更新bot启动脚本 * 增加timeout默认值,修改session管理逻辑 * 更新config示例和通知日志 * 更新bot.sh * 更新启动bot命令 * 更新启动bot命令 * 修复task运行参数合并 * 增加停止定时任务功能 * 修复停止定时任务api * 更新停止定时任务日志 * 更新停止任务日志 * 修复删除cron api * 更新删除cron通知文本 * 更新命令提示 * 更新bot启动脚本
This commit is contained in:
parent
489846d2e6
commit
5b3687f7b6
|
@ -1,6 +1,7 @@
|
|||
MONGODB_URI='mongodb://'
|
||||
YIYAN_MONGODB_URI=''
|
||||
|
||||
CRON_PORT=5500
|
||||
PORT=5600
|
||||
|
||||
LOG_LEVEL='debug'
|
||||
|
|
|
@ -35,9 +35,9 @@ python和javaScript的定时任务管理面板
|
|||
|
||||
## 多谢
|
||||
|
||||
* [https://github.com/nevinee/jd_shell](https://github.com/nevinee/jd_shell)
|
||||
* [nevinee](https://gitee.com/evine)
|
||||
|
||||
* [https://github.com/alseambusher/crontab-ui](https://github.com/alseambusher/crontab-ui)
|
||||
* [crontab-ui](https://github.com/alseambusher/crontab-ui)
|
||||
|
||||
* [Ant Design](https://ant.design)
|
||||
|
||||
|
|
|
@ -26,10 +26,6 @@ export default (app: Router) => {
|
|||
case 'crontab':
|
||||
content = getFileContentByName(config.crontabFile);
|
||||
break;
|
||||
case 'shareCode':
|
||||
let shareCodeFile = getLastModifyFilePath(config.shareCodeDir);
|
||||
content = getFileContentByName(shareCodeFile);
|
||||
break;
|
||||
case 'extra':
|
||||
content = getFileContentByName(config.extraFile);
|
||||
break;
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import { Router, Request, Response, NextFunction } from 'express';
|
||||
import { Container } from 'typedi';
|
||||
import { Logger } from 'winston';
|
||||
import * as fs from 'fs';
|
||||
import config from '../config';
|
||||
import CronService from '../services/cron';
|
||||
import { celebrate, Joi } from 'celebrate';
|
||||
import cron_parser from 'cron-parser';
|
||||
const route = Router();
|
||||
|
||||
export default (app: Router) => {
|
||||
|
@ -32,15 +31,19 @@ export default (app: Router) => {
|
|||
body: Joi.object({
|
||||
command: Joi.string().required(),
|
||||
schedule: Joi.string().required(),
|
||||
name: Joi.string(),
|
||||
name: Joi.string().optional(),
|
||||
}),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
try {
|
||||
if (cron_parser.parseExpression(req.body.schedule).hasNext()) {
|
||||
const cronService = Container.get(CronService);
|
||||
const data = await cronService.create(req.body);
|
||||
return res.send({ code: 200, data });
|
||||
} else {
|
||||
return res.send({ code: 400, message: 'param schedule error' });
|
||||
}
|
||||
} catch (e) {
|
||||
logger.error('🔥 error: %o', e);
|
||||
return next(e);
|
||||
|
@ -48,18 +51,16 @@ export default (app: Router) => {
|
|||
},
|
||||
);
|
||||
|
||||
route.get(
|
||||
'/crons/:id/run',
|
||||
route.put(
|
||||
'/crons/run',
|
||||
celebrate({
|
||||
params: Joi.object({
|
||||
id: Joi.string().required(),
|
||||
}),
|
||||
body: Joi.array().items(Joi.string().required()),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
try {
|
||||
const cronService = Container.get(CronService);
|
||||
const data = await cronService.run(req.params.id);
|
||||
const data = await cronService.run(req.body);
|
||||
return res.send({ code: 200, data });
|
||||
} catch (e) {
|
||||
logger.error('🔥 error: %o', e);
|
||||
|
@ -68,18 +69,16 @@ export default (app: Router) => {
|
|||
},
|
||||
);
|
||||
|
||||
route.get(
|
||||
'/crons/:id/disable',
|
||||
route.put(
|
||||
'/crons/stop',
|
||||
celebrate({
|
||||
params: Joi.object({
|
||||
id: Joi.string().required(),
|
||||
}),
|
||||
body: Joi.array().items(Joi.string().required()),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
try {
|
||||
const cronService = Container.get(CronService);
|
||||
const data = await cronService.disabled(req.params.id);
|
||||
const data = await cronService.stop(req.body);
|
||||
return res.send({ code: 200, data });
|
||||
} catch (e) {
|
||||
logger.error('🔥 error: %o', e);
|
||||
|
@ -88,18 +87,34 @@ export default (app: Router) => {
|
|||
},
|
||||
);
|
||||
|
||||
route.get(
|
||||
'/crons/:id/enable',
|
||||
route.put(
|
||||
'/crons/disable',
|
||||
celebrate({
|
||||
params: Joi.object({
|
||||
id: Joi.string().required(),
|
||||
}),
|
||||
body: Joi.array().items(Joi.string().required()),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
try {
|
||||
const cronService = Container.get(CronService);
|
||||
const data = await cronService.enabled(req.params.id);
|
||||
const data = await cronService.disabled(req.body);
|
||||
return res.send({ code: 200, data });
|
||||
} catch (e) {
|
||||
logger.error('🔥 error: %o', e);
|
||||
return next(e);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
route.put(
|
||||
'/crons/enable',
|
||||
celebrate({
|
||||
body: Joi.array().items(Joi.string().required()),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
try {
|
||||
const cronService = Container.get(CronService);
|
||||
const data = await cronService.enabled(req.body);
|
||||
return res.send({ code: 200, data });
|
||||
} catch (e) {
|
||||
logger.error('🔥 error: %o', e);
|
||||
|
@ -134,16 +149,20 @@ export default (app: Router) => {
|
|||
body: Joi.object({
|
||||
command: Joi.string().required(),
|
||||
schedule: Joi.string().required(),
|
||||
name: Joi.string(),
|
||||
name: Joi.string().optional(),
|
||||
_id: Joi.string().required(),
|
||||
}),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
try {
|
||||
if (cron_parser.parseExpression(req.body.schedule).hasNext()) {
|
||||
const cronService = Container.get(CronService);
|
||||
const data = await cronService.update(req.body);
|
||||
return res.send({ code: 200, data });
|
||||
} else {
|
||||
return res.send({ code: 400, message: 'param schedule error' });
|
||||
}
|
||||
} catch (e) {
|
||||
logger.error('🔥 error: %o', e);
|
||||
return next(e);
|
||||
|
@ -152,17 +171,15 @@ export default (app: Router) => {
|
|||
);
|
||||
|
||||
route.delete(
|
||||
'/crons/:id',
|
||||
'/crons',
|
||||
celebrate({
|
||||
params: Joi.object({
|
||||
id: Joi.string().required(),
|
||||
}),
|
||||
body: Joi.array().items(Joi.string().required()),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
try {
|
||||
const cronService = Container.get(CronService);
|
||||
const data = await cronService.remove(req.params.id);
|
||||
const data = await cronService.remove(req.body);
|
||||
return res.send({ code: 200, data });
|
||||
} catch (e) {
|
||||
logger.error('🔥 error: %o', e);
|
||||
|
|
|
@ -7,11 +7,10 @@ const envFound = dotenv.config();
|
|||
const rootPath = path.resolve(__dirname, '../../');
|
||||
const cookieFile = path.join(rootPath, 'config/cookie.sh');
|
||||
const confFile = path.join(rootPath, 'config/config.sh');
|
||||
const sampleFile = path.join(rootPath, 'sample/config.sh.sample');
|
||||
const sampleFile = path.join(rootPath, 'sample/config.sample.sh');
|
||||
const crontabFile = path.join(rootPath, 'config/crontab.list');
|
||||
const confBakDir = path.join(rootPath, 'config/bak/');
|
||||
const authConfigFile = path.join(rootPath, 'config/auth.json');
|
||||
const shareCodeDir = path.join(rootPath, 'log/export_sharecodes/');
|
||||
const extraFile = path.join(rootPath, 'config/extra.sh');
|
||||
const logPath = path.join(rootPath, 'log/');
|
||||
const authError = '错误的用户名密码,请重试';
|
||||
|
@ -28,6 +27,7 @@ if (envFound.error) {
|
|||
|
||||
export default {
|
||||
port: parseInt(process.env.PORT as string, 10),
|
||||
cronPort: parseInt(process.env.CRON_PORT as string, 10),
|
||||
secret: process.env.SECRET,
|
||||
logs: {
|
||||
level: process.env.LOG_LEVEL || 'silly',
|
||||
|
@ -40,7 +40,6 @@ export default {
|
|||
authError,
|
||||
logPath,
|
||||
extraFile,
|
||||
shareCodeDir,
|
||||
authConfigFile,
|
||||
confBakDir,
|
||||
crontabFile,
|
||||
|
|
|
@ -8,6 +8,7 @@ export class Crontab {
|
|||
_id?: string;
|
||||
status?: CrontabStatus;
|
||||
isSystem?: 1 | 0;
|
||||
pid?: number;
|
||||
|
||||
constructor(options: Crontab) {
|
||||
this.name = options.name;
|
||||
|
@ -19,6 +20,7 @@ export class Crontab {
|
|||
this.status = options.status || CrontabStatus.idle;
|
||||
this.timestamp = new Date().toString();
|
||||
this.isSystem = options.isSystem || 0;
|
||||
this.pid = options.pid;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,10 @@ export default ({ app }: { app: Application }) => {
|
|||
next: NextFunction,
|
||||
) => {
|
||||
if (err.name === 'UnauthorizedError') {
|
||||
return res.status(err.status).send({ message: err.message }).end();
|
||||
return res
|
||||
.status(err.status)
|
||||
.send({ code: 401, message: err.message })
|
||||
.end();
|
||||
}
|
||||
return next(err);
|
||||
},
|
||||
|
@ -64,6 +67,7 @@ export default ({ app }: { app: Application }) => {
|
|||
) => {
|
||||
res.status(err.status || 500);
|
||||
res.json({
|
||||
code: err.status || 500,
|
||||
message: err.message,
|
||||
});
|
||||
},
|
||||
|
|
|
@ -5,10 +5,7 @@ import CronService from '../services/cron';
|
|||
const initData = [
|
||||
{
|
||||
name: '更新面板',
|
||||
command: `sleep ${randomSchedule(
|
||||
60,
|
||||
1,
|
||||
)} && git_pull >> $QL_DIR/log/git_pull.log 2>&1`,
|
||||
command: `sleep ${randomSchedule(60, 1)} && ql update`,
|
||||
schedule: `${randomSchedule(60, 1)} ${randomSchedule(
|
||||
24,
|
||||
7,
|
||||
|
@ -16,46 +13,22 @@ const initData = [
|
|||
status: CrontabStatus.idle,
|
||||
},
|
||||
{
|
||||
name: 'build面板',
|
||||
command: 'rebuild >> ${QL_DIR}/log/rebuild.log 2>&1',
|
||||
name: '重启并编译面板',
|
||||
command: 'ql restart',
|
||||
schedule: '30 7 */7 * *',
|
||||
status: CrontabStatus.disabled,
|
||||
},
|
||||
{
|
||||
name: '自定义仓库',
|
||||
command: `sleep ${randomSchedule(
|
||||
60,
|
||||
1,
|
||||
)} && diy https://ghproxy.com/https://github.com/whyour/hundun.git "quanx/jx|quanx/jd" tokens >> $QL_DIR/log/diy_pull.log 2>&1`,
|
||||
schedule: `${randomSchedule(60, 1)} ${randomSchedule(
|
||||
24,
|
||||
6,
|
||||
).toString()} * * *`,
|
||||
status: CrontabStatus.idle,
|
||||
},
|
||||
{
|
||||
name: '互助码导出',
|
||||
command: 'export_sharecodes',
|
||||
schedule: '48 5 * * *',
|
||||
status: CrontabStatus.idle,
|
||||
},
|
||||
{
|
||||
name: '删除日志',
|
||||
command: 'rm_log >/dev/null 2>&1',
|
||||
command: 'ql rmlog 7',
|
||||
schedule: '30 7 */7 * *',
|
||||
status: CrontabStatus.disabled,
|
||||
status: CrontabStatus.idle,
|
||||
},
|
||||
{
|
||||
name: '重置密码',
|
||||
command: 'js resetpwd',
|
||||
schedule: '33 6 */7 * *',
|
||||
status: CrontabStatus.disabled,
|
||||
},
|
||||
{
|
||||
name: '运行所有脚本(慎用)',
|
||||
command: 'js runall',
|
||||
schedule: '33 6 */7 * *',
|
||||
status: CrontabStatus.disabled,
|
||||
name: '互助码',
|
||||
command: 'ql code',
|
||||
schedule: '30 7 * * *',
|
||||
status: CrontabStatus.idle,
|
||||
},
|
||||
];
|
||||
|
||||
|
|
59
back/schedule.ts
Normal file
59
back/schedule.ts
Normal file
|
@ -0,0 +1,59 @@
|
|||
import schedule from 'node-schedule';
|
||||
import express from 'express';
|
||||
import { exec } from 'child_process';
|
||||
import Logger from './loaders/logger';
|
||||
import { Container } from 'typedi';
|
||||
import CronService from './services/cron';
|
||||
import { CrontabStatus } from './data/cron';
|
||||
import config from './config';
|
||||
|
||||
const app = express();
|
||||
|
||||
const run = async () => {
|
||||
const cronService = Container.get(CronService);
|
||||
const cronDb = cronService.getDb();
|
||||
|
||||
cronDb
|
||||
.find({})
|
||||
.sort({ created: 1 })
|
||||
.exec((err, docs) => {
|
||||
if (err) {
|
||||
Logger.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (docs && docs.length > 0) {
|
||||
for (let i = 0; i < docs.length; i++) {
|
||||
const task = docs[i];
|
||||
const _schedule = task.schedule && task.schedule.split(' ');
|
||||
if (
|
||||
_schedule &&
|
||||
_schedule.length > 5 &&
|
||||
task.status !== CrontabStatus.disabled
|
||||
) {
|
||||
schedule.scheduleJob(task.schedule, function () {
|
||||
let command = task.command as string;
|
||||
if (!command.includes('task ') && !command.includes('ql ')) {
|
||||
command = `task ${command}`;
|
||||
}
|
||||
exec(command);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
app
|
||||
.listen(config.cronPort, () => {
|
||||
run();
|
||||
Logger.info(`
|
||||
################################################
|
||||
🛡️ Schedule listening on port: ${config.cronPort} 🛡️
|
||||
################################################
|
||||
`);
|
||||
})
|
||||
.on('error', (err) => {
|
||||
Logger.error(err);
|
||||
process.exit(1);
|
||||
});
|
|
@ -121,6 +121,16 @@ export default class CookieService {
|
|||
});
|
||||
}
|
||||
|
||||
private async formatCookies(cookies: Cookie[]) {
|
||||
const result = [];
|
||||
for (let i = 0; i < cookies.length; i++) {
|
||||
const cookie = cookies[i];
|
||||
const { status, nickname } = await this.getJdInfo(cookie.value);
|
||||
result.push({ ...cookie, status, nickname });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public async create(payload: string[]): Promise<Cookie[]> {
|
||||
const cookies = await this.cookies('');
|
||||
let position = initCookiePosition;
|
||||
|
@ -135,7 +145,7 @@ export default class CookieService {
|
|||
});
|
||||
const docs = await this.insert(tabs);
|
||||
await this.set_cookies();
|
||||
return docs;
|
||||
return await this.formatCookies(docs);
|
||||
}
|
||||
|
||||
public async insert(payload: Cookie[]): Promise<Cookie[]> {
|
||||
|
@ -156,20 +166,21 @@ export default class CookieService {
|
|||
const tab = new Cookie({ ...doc, ...other });
|
||||
const newDoc = await this.updateDb(tab);
|
||||
await this.set_cookies();
|
||||
return newDoc;
|
||||
const [newCookie] = await this.formatCookies([newDoc]);
|
||||
return newCookie;
|
||||
}
|
||||
|
||||
public async updateDb(payload: Cookie): Promise<Cookie> {
|
||||
private async updateDb(payload: Cookie): Promise<Cookie> {
|
||||
return new Promise((resolve) => {
|
||||
this.cronDb.update(
|
||||
{ _id: payload._id },
|
||||
payload,
|
||||
{ returnUpdatedDocs: true },
|
||||
(err, docs) => {
|
||||
(err, num, doc) => {
|
||||
if (err) {
|
||||
this.logger.error(err);
|
||||
} else {
|
||||
resolve(docs as Cookie);
|
||||
resolve(doc as Cookie);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
@ -228,6 +239,11 @@ export default class CookieService {
|
|||
],
|
||||
};
|
||||
}
|
||||
const newDocs = await this.find(query, sort);
|
||||
return await this.formatCookies(newDocs);
|
||||
}
|
||||
|
||||
private async find(query: any, sort: any): Promise<Cookie[]> {
|
||||
return new Promise((resolve) => {
|
||||
this.cronDb
|
||||
.find(query)
|
||||
|
|
|
@ -22,12 +22,20 @@ export default class CronService {
|
|||
return this.cronDb;
|
||||
}
|
||||
|
||||
private isSixCron(cron: Crontab) {
|
||||
const { schedule } = cron;
|
||||
if (schedule.split(' ').length === 6) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public async create(payload: Crontab): Promise<Crontab> {
|
||||
const tab = new Crontab(payload);
|
||||
tab.created = new Date().valueOf();
|
||||
tab.saved = false;
|
||||
const doc = await this.insert(tab);
|
||||
await this.set_crontab();
|
||||
await this.set_crontab(this.isSixCron(doc));
|
||||
return doc;
|
||||
}
|
||||
|
||||
|
@ -74,9 +82,9 @@ export default class CronService {
|
|||
this.cronDb.update({ _id }, { $set: { stopped, saved: false } });
|
||||
}
|
||||
|
||||
public async remove(_id: string) {
|
||||
this.cronDb.remove({ _id }, {});
|
||||
await this.set_crontab();
|
||||
public async remove(ids: string[]) {
|
||||
this.cronDb.remove({ _id: { $in: ids } }, { multi: true });
|
||||
await this.set_crontab(true);
|
||||
}
|
||||
|
||||
public async crontabs(searchText?: string): Promise<Crontab[]> {
|
||||
|
@ -112,26 +120,49 @@ export default class CronService {
|
|||
});
|
||||
}
|
||||
|
||||
public async run(_id: string) {
|
||||
this.cronDb.find({ _id }).exec((err, docs: Crontab[]) => {
|
||||
let res = docs[0];
|
||||
public async run(ids: string[]) {
|
||||
this.cronDb.find({ _id: { $in: ids } }).exec((err, docs: Crontab[]) => {
|
||||
for (let i = 0; i < docs.length; i++) {
|
||||
const doc = docs[i];
|
||||
this.runSingle(doc);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async stop(ids: string[]) {
|
||||
this.cronDb.find({ _id: { $in: ids } }).exec((err, docs: Crontab[]) => {
|
||||
for (let i = 0; i < docs.length; i++) {
|
||||
const doc = docs[i];
|
||||
if (doc.pid) {
|
||||
exec(`kill -9 ${doc.pid}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async runSingle(cron: Crontab) {
|
||||
let { _id, command } = cron;
|
||||
|
||||
this.logger.silly('Running job');
|
||||
this.logger.silly('ID: ' + _id);
|
||||
this.logger.silly('Original command: ' + res.command);
|
||||
this.logger.silly('Original command: ' + command);
|
||||
|
||||
let logFile = `${config.manualLogPath}${res._id}.log`;
|
||||
let logFile = `${config.manualLogPath}${_id}.log`;
|
||||
fs.writeFileSync(logFile, `开始执行...\n\n${new Date().toString()}\n`);
|
||||
|
||||
let cmdStr = res.command;
|
||||
if (res.command.startsWith('js') && !res.command.endsWith('now')) {
|
||||
cmdStr = `${res.command} now`;
|
||||
} else if (/&& (.*) >>/.test(res.command)) {
|
||||
cmdStr = res.command.match(/&& (.*) >>/)[1];
|
||||
let cmdStr = command;
|
||||
if (!cmdStr.includes('task ') && !cmdStr.includes('ql ')) {
|
||||
cmdStr = `task ${cmdStr}`;
|
||||
}
|
||||
if (cmdStr.endsWith('.js')) {
|
||||
cmdStr = `${cmdStr} now`;
|
||||
}
|
||||
const cmd = spawn(cmdStr, { shell: true });
|
||||
|
||||
this.cronDb.update({ _id }, { $set: { status: CrontabStatus.running } });
|
||||
this.cronDb.update(
|
||||
{ _id },
|
||||
{ $set: { status: CrontabStatus.running, pid: cmd.pid } },
|
||||
);
|
||||
|
||||
cmd.stdout.on('data', (data) => {
|
||||
this.logger.silly(`stdout: ${data}`);
|
||||
|
@ -164,16 +195,23 @@ export default class CronService {
|
|||
this.cronDb.update({ _id }, { $set: { status: CrontabStatus.idle } });
|
||||
fs.appendFileSync(logFile, `\n\n连接断开...`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async disabled(_id: string) {
|
||||
this.cronDb.update({ _id }, { $set: { status: CrontabStatus.disabled } });
|
||||
public async disabled(ids: string[]) {
|
||||
this.cronDb.update(
|
||||
{ _id: { $in: ids } },
|
||||
{ $set: { status: CrontabStatus.disabled } },
|
||||
{ multi: true },
|
||||
);
|
||||
await this.set_crontab();
|
||||
}
|
||||
|
||||
public async enabled(_id: string) {
|
||||
this.cronDb.update({ _id }, { $set: { status: CrontabStatus.idle } });
|
||||
public async enabled(ids: string[]) {
|
||||
this.cronDb.update(
|
||||
{ _id: { $in: ids } },
|
||||
{ $set: { status: CrontabStatus.idle } },
|
||||
{ multi: true },
|
||||
);
|
||||
}
|
||||
|
||||
public async log(_id: string) {
|
||||
|
@ -186,11 +224,12 @@ export default class CronService {
|
|||
return crontab_job_string;
|
||||
}
|
||||
|
||||
private async set_crontab() {
|
||||
private async set_crontab(needReloadSchedule: boolean = false) {
|
||||
const tabs = await this.crontabs();
|
||||
var crontab_string = '';
|
||||
tabs.forEach((tab) => {
|
||||
if (tab.status === CrontabStatus.disabled) {
|
||||
const _schedule = tab.schedule && tab.schedule.split(' ');
|
||||
if (tab.status === CrontabStatus.disabled || _schedule.length !== 5) {
|
||||
crontab_string += '# ';
|
||||
crontab_string += tab.schedule;
|
||||
crontab_string += ' ';
|
||||
|
@ -208,6 +247,9 @@ export default class CronService {
|
|||
fs.writeFileSync(config.crontabFile, crontab_string);
|
||||
|
||||
execSync(`crontab ${config.crontabFile}`);
|
||||
if (needReloadSchedule) {
|
||||
exec(`pm2 reload schedule`);
|
||||
}
|
||||
this.cronDb.update({}, { $set: { saved: true } }, { multi: true });
|
||||
}
|
||||
|
||||
|
@ -226,11 +268,11 @@ export default class CronService {
|
|||
var command = line.replace(regex, '').trim();
|
||||
var schedule = line.replace(command, '').trim();
|
||||
|
||||
var is_valid = false;
|
||||
try {
|
||||
is_valid = cron_parser.parseString(line).expressions.length > 0;
|
||||
} catch (e) {}
|
||||
if (command && schedule && is_valid) {
|
||||
if (
|
||||
command &&
|
||||
schedule &&
|
||||
cron_parser.parseExpression(schedule).hasNext()
|
||||
) {
|
||||
var name = namePrefix + '_' + index;
|
||||
|
||||
this.cronDb.findOne({ command, schedule }, (err, doc) => {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
FROM node:lts-alpine
|
||||
LABEL maintainer="whyour"
|
||||
ARG QL_BASE_URL=https://github.com.cnpmjs.org/whyour/qinglong
|
||||
ARG QL_BASE_BRANCH=master
|
||||
ARG QL_URL=https://ghproxy.com/https://github.com/whyour/qinglong.git
|
||||
ARG QL_BRANCH=master
|
||||
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
|
||||
LANG=zh_CN.UTF-8 \
|
||||
SHELL=/bin/bash \
|
||||
|
@ -27,17 +27,9 @@ RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
|||
&& echo "Asia/Shanghai" > /etc/timezone \
|
||||
&& touch ~/.bashrc \
|
||||
&& mkdir /run/nginx \
|
||||
&& git clone -b ${QL_BASE_BRANCH} ${QL_BASE_URL} ${QL_DIR} \
|
||||
&& git clone -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} \
|
||||
&& cd ${QL_DIR} \
|
||||
&& cp -f .env.example .env \
|
||||
&& ln -sf ${QL_DIR}/shell/js.sh /usr/local/bin/js \
|
||||
&& ln -sf ${QL_DIR}/shell/git_pull.sh /usr/local/bin/git_pull \
|
||||
&& ln -sf ${QL_DIR}/shell/rm_log.sh /usr/local/bin/rm_log \
|
||||
&& ln -sf ${QL_DIR}/shell/export_sharecodes.sh /usr/local/bin/export_sharecodes \
|
||||
&& ln -sf ${QL_DIR}/shell/git_diy.sh /usr/local/bin/diy \
|
||||
&& ln -sf ${QL_DIR}/shell/notify.sh /usr/local/bin/notify \
|
||||
&& ln -sf ${QL_DIR}/shell/rebuild.sh /usr/local/bin/rebuild \
|
||||
&& ln -sf ${QL_DIR}/docker/docker-entrypoint.sh /usr/local/bin/entrypoint \
|
||||
&& chmod 777 ${QL_DIR}/shell/*.sh \
|
||||
&& chmod 777 ${QL_DIR}/docker/*.sh \
|
||||
&& npm install -g pm2 \
|
||||
|
@ -47,4 +39,4 @@ RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
|||
&& yarn build-back \
|
||||
&& yarn install --production --network-timeout 100000 \
|
||||
&& yarn cache clean
|
||||
ENTRYPOINT ["entrypoint"]
|
||||
ENTRYPOINT ["./docker/docker-entrypoint.sh"]
|
|
@ -1,64 +1,37 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo -e "======================1. 检测配置文件========================\n"
|
||||
[ ! -d ${QL_DIR}/config ] && mkdir -p ${QL_DIR}/config
|
||||
[ ! -d ${QL_DIR}/log ] && mkdir -p ${QL_DIR}/log
|
||||
[ ! -d ${QL_DIR}/db ] && mkdir -p ${QL_DIR}/db
|
||||
[ ! -d ${QL_DIR}/manual_log ] && mkdir -p ${QL_DIR}/manual_log
|
||||
|
||||
if [ ! -s ${QL_DIR}/config/crontab.list ]
|
||||
then
|
||||
echo -e "检测到config配置目录下不存在crontab.list或存在但文件为空,从示例文件复制一份用于初始化...\n"
|
||||
cp -fv ${QL_DIR}/sample/crontab.list.sample ${QL_DIR}/config/crontab.list
|
||||
sed -i "s,MY_PATH,${QL_DIR},g" ${QL_DIR}/config/crontab.list
|
||||
sed -i "s,ENV_PATH=,PATH=$PATH,g" ${QL_DIR}/config/crontab.list
|
||||
fi
|
||||
crond
|
||||
crontab ${QL_DIR}/config/crontab.list
|
||||
echo -e "成功添加定时任务...\n"
|
||||
|
||||
if [ ! -s ${QL_DIR}/config/cookie.sh ]; then
|
||||
echo -e "检测到config配置目录下不存在cookie.sh,从示例文件复制一份用于初始化...\n"
|
||||
touch ${QL_DIR}/config/cookie.sh
|
||||
echo
|
||||
fi
|
||||
|
||||
if [ ! -s ${QL_DIR}/config/config.sh ]; then
|
||||
echo -e "检测到config配置目录下不存在config.sh,从示例文件复制一份用于初始化...\n"
|
||||
cp -fv ${QL_DIR}/sample/config.sh.sample ${QL_DIR}/config/config.sh
|
||||
echo
|
||||
fi
|
||||
|
||||
if [ ! -s ${QL_DIR}/config/auth.json ]; then
|
||||
echo -e "检测到config配置目录下不存在auth.json,从示例文件复制一份用于初始化...\n"
|
||||
cp -fv ${QL_DIR}/sample/auth.json ${QL_DIR}/config/auth.json
|
||||
echo
|
||||
fi
|
||||
|
||||
if [ -s /etc/nginx/conf.d/default.conf ]; then
|
||||
echo -e "检测到默认nginx配置文件,删除...\n"
|
||||
rm -f /etc/nginx/conf.d/default.conf
|
||||
echo
|
||||
fi
|
||||
|
||||
cp -fv ${QL_DIR}/docker/front.conf /etc/nginx/conf.d/front.conf
|
||||
|
||||
echo -e "======================2. 启动nginx========================\n"
|
||||
nginx -c /etc/nginx/nginx.conf
|
||||
dir_shell=/ql/shell
|
||||
. $dir_shell/share.sh
|
||||
link_shell
|
||||
echo -e "======================1. 更新源代码========================\n"
|
||||
ql update
|
||||
echo
|
||||
|
||||
echo -e "======================3. 启动控制面板========================\n"
|
||||
pm2 start ${QL_DIR}/build/app.js -n panel
|
||||
echo -e "======================2. 检测配置文件========================\n"
|
||||
fix_config
|
||||
cp -fv $dir_root/docker/front.conf /etc/nginx/conf.d/front.conf
|
||||
echo
|
||||
|
||||
echo -e "======================3. 启动nginx========================\n"
|
||||
nginx -s reload 2>/dev/null || nginx -c /etc/nginx/nginx.conf
|
||||
echo -e "nginx启动成功...\n"
|
||||
|
||||
echo -e "======================4. 启动控制面板========================\n"
|
||||
cd $dir_root
|
||||
pm2 reload panel 2>/dev/null || pm2 start $dir_root/build/app.js -n panel
|
||||
echo -e "控制面板启动成功...\n"
|
||||
|
||||
echo -e "\n容器启动成功...\n"
|
||||
echo -e "\n请先访问5700端口,登录面板成功之后先手动执行一次git_pull命令...\n"
|
||||
echo -e "\n如果需要启动挂机程序手动执行docker exec -it qinglong js hangup...\n"
|
||||
echo -e "\n或者去cron管理搜索hangup手动执行挂机任务...\n"
|
||||
echo -e "======================5. 启动定时任务========================\n"
|
||||
cd $dir_root
|
||||
pm2 reload schedule 2>/dev/null || pm2 start $dir_root/build/schedule.js -n schedule
|
||||
echo -e "定时任务启动成功...\n"
|
||||
|
||||
if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ]; then
|
||||
set -- node "$@"
|
||||
fi
|
||||
echo -e "############################################################\n"
|
||||
echo -e "容器启动成功..."
|
||||
echo -e "\n请先访问5700端口,登录成功面板之后再执行添加定时任务..."
|
||||
echo -e "############################################################\n"
|
||||
|
||||
crond -f
|
||||
|
||||
exec "$@"
|
26
package.json
26
package.json
|
@ -5,7 +5,8 @@
|
|||
"build": "umi build",
|
||||
"build-back": "tsc -p tsconfig.back.json",
|
||||
"start-back": "nodemon",
|
||||
"pm2": "npm run build-back && node build/app.js",
|
||||
"panel": "npm run build-back && node build/app.js",
|
||||
"schedule": "npm run build-back && node build/schedule.js",
|
||||
"prepare": "umi generate tmp",
|
||||
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
|
||||
"test": "umi-test",
|
||||
|
@ -26,7 +27,7 @@
|
|||
"body-parser": "^1.19.0",
|
||||
"celebrate": "^13.0.3",
|
||||
"cors": "^2.8.5",
|
||||
"cron-parser": "^3.3.0",
|
||||
"cron-parser": "^3.5.0",
|
||||
"dotenv": "^8.2.0",
|
||||
"express": "^4.17.1",
|
||||
"express-jwt": "^6.0.0",
|
||||
|
@ -34,22 +35,13 @@
|
|||
"jsonwebtoken": "^8.5.1",
|
||||
"nedb": "^1.8.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"node-schedule": "^2.0.0",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"typedi": "^0.8.0",
|
||||
"winston": "^3.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"umi": "^3.3.9",
|
||||
"umi-request": "^1.3.5",
|
||||
"react-codemirror2": "^7.2.1",
|
||||
"react-diff-viewer": "^3.1.1",
|
||||
"react-dnd": "^14.0.2",
|
||||
"react-dnd-html5-backend": "^14.0.0",
|
||||
"qrcode.react": "^1.0.1",
|
||||
"darkreader": "^4.9.27",
|
||||
"codemirror": "^5.59.4",
|
||||
"@ant-design/pro-layout": "^6.5.0",
|
||||
"@umijs/plugin-antd": "^0.9.1",
|
||||
"@types/cors": "^2.8.10",
|
||||
"@types/express": "^4.17.8",
|
||||
"@types/express-jwt": "^6.0.1",
|
||||
|
@ -60,15 +52,25 @@
|
|||
"@types/qrcode.react": "^1.0.1",
|
||||
"@types/react": "^17.0.0",
|
||||
"@types/react-dom": "^17.0.0",
|
||||
"@umijs/plugin-antd": "^0.9.1",
|
||||
"@umijs/test": "^3.3.9",
|
||||
"codemirror": "^5.59.4",
|
||||
"compression-webpack-plugin": "6.1.1",
|
||||
"darkreader": "^4.9.27",
|
||||
"lint-staged": "^10.0.7",
|
||||
"nodemon": "^2.0.4",
|
||||
"prettier": "^2.2.0",
|
||||
"qrcode.react": "^1.0.1",
|
||||
"react": "17.x",
|
||||
"react-codemirror2": "^7.2.1",
|
||||
"react-diff-viewer": "^3.1.1",
|
||||
"react-dnd": "^14.0.2",
|
||||
"react-dnd-html5-backend": "^14.0.0",
|
||||
"react-dom": "17.x",
|
||||
"ts-node": "^9.0.0",
|
||||
"typescript": "^4.1.2",
|
||||
"umi": "^3.3.9",
|
||||
"umi-request": "^1.3.5",
|
||||
"webpack": "^5.28.0",
|
||||
"yorkie": "^2.0.0"
|
||||
}
|
||||
|
|
117
sample/config.sample.sh
Normal file
117
sample/config.sample.sh
Normal file
|
@ -0,0 +1,117 @@
|
|||
## Version: v2.0.0
|
||||
## Date: 2021-05-10
|
||||
## Update Content: 青龙v2
|
||||
|
||||
## 上面版本号中,如果第2位数字有变化,那么代表增加了新的参数,如果只有第3位数字有变化,仅代表更新了注释,没有增加新的参数,可更新可不更新
|
||||
|
||||
## 在运行 ql repo 命令时,是否自动删除失效的脚本与定时任务
|
||||
AutoDelCron="true"
|
||||
|
||||
## 在运行 ql repo 命令时,是否自动增加新的本地定时任务
|
||||
AutoAddCron="true"
|
||||
|
||||
## 设置定时任务执行的超时时间,默认1h,后缀"s"代表秒(默认值), "m"代表分, "h"代表小时, "d"代表天
|
||||
CommandTimeoutTime="1h"
|
||||
|
||||
## 在运行 task 命令时,随机延迟启动任务的最大延迟时间
|
||||
## 如果任务不是必须准点运行的任务,那么给它增加一个随机延迟,由你定义最大延迟时间,单位为秒,如 RandomDelay="300" ,表示任务将在 1-300 秒内随机延迟一个秒数,然后再运行
|
||||
## 在crontab.list中,在每小时第0-2分、第30-31分、第59分这几个时间内启动的任务,均算作必须准点运行的任务,在启动这些任务时,即使你定义了RandomDelay,也将准点运行,不启用随机延迟
|
||||
## 在crontab.list中,除掉每小时上述时间启动的任务外,其他任务在你定义了 RandomDelay 的情况下,一律启用随机延迟,但如果你给某些任务添加了 "now" 或者 "conc",那么这些任务也将无视随机延迟直接启动
|
||||
RandomDelay="300"
|
||||
|
||||
## 如果你自己会写shell脚本,并且希望在每次运行 ql update 命令时,额外运行你的 shell 脚本,请赋值为 "true",默认为true
|
||||
EnableExtraShell="true"
|
||||
|
||||
## 自动按顺序进行账号间互助(选填) 设置为 true 时,将直接导入code最新日志来进行互助
|
||||
AutoHelpOther=""
|
||||
|
||||
## 定义 jcode 脚本导出的互助码模板样式(选填)
|
||||
## 不填 使用“按编号顺序助力模板”,Cookie编号在前的优先助力
|
||||
## 填 0 使用“全部一致助力模板”,所有账户要助力的码全部一致
|
||||
## 填 1 使用“均等机会助力模板”,所有账户获得助力次数一致
|
||||
## 填 2 使用“随机顺序助力模板”,本套脚本内账号间随机顺序助力,每次生成的顺序都不一致。
|
||||
HelpType=""
|
||||
|
||||
|
||||
## 需组合的环境变量列表,env_name需要和var_name一一对应,如何有新活动按照格式添加(不懂勿动)
|
||||
env_name=(
|
||||
JD_COOKIE
|
||||
FRUITSHARECODES
|
||||
PETSHARECODES
|
||||
PLANT_BEAN_SHARECODES
|
||||
DREAM_FACTORY_SHARE_CODES
|
||||
DDFACTORY_SHARECODES
|
||||
JDZZ_SHARECODES
|
||||
JDJOY_SHARECODES
|
||||
JXNC_SHARECODES
|
||||
BOOKSHOP_SHARECODES
|
||||
JD_CASH_SHARECODES
|
||||
JDSGMH_SHARECODES
|
||||
JDCFD_SHARECODES
|
||||
JDHEALTH_SHARECODES
|
||||
)
|
||||
var_name=(
|
||||
Cookie
|
||||
ForOtherFruit
|
||||
ForOtherPet
|
||||
ForOtherBean
|
||||
ForOtherDreamFactory
|
||||
ForOtherJdFactory
|
||||
ForOtherJdzz
|
||||
ForOtherJoy
|
||||
ForOtherJxnc
|
||||
ForOtherBookShop
|
||||
ForOtherCash
|
||||
ForOtherSgmh
|
||||
ForOtherCfd
|
||||
ForOtherHealth
|
||||
)
|
||||
|
||||
## name_js为脚本文件名,如果使用ql repo命令拉取,文件名含有作者名
|
||||
## 所有有互助码的活动,把脚本名称列在 name_js 中,对应 config.sh 中互助码后缀列在 name_config 中,中文名称列在 name_chinese 中。
|
||||
## name_js、name_config 和 name_chinese 中的三个名称必须一一对应。
|
||||
name_js=(
|
||||
jd_fruit
|
||||
jd_pet
|
||||
jd_plantBean
|
||||
jd_dreamFactory
|
||||
jd_jdfactory
|
||||
jd_jdzz
|
||||
jd_crazy_joy
|
||||
jd_jxnc
|
||||
jd_bookshop
|
||||
jd_cash
|
||||
jd_sgmh
|
||||
jd_cfd
|
||||
jd_health
|
||||
)
|
||||
name_config=(
|
||||
Fruit
|
||||
Pet
|
||||
Bean
|
||||
DreamFactory
|
||||
JdFactory
|
||||
Jdzz
|
||||
Joy
|
||||
Jxnc
|
||||
BookShop
|
||||
Cash
|
||||
Sgmh
|
||||
Cfd
|
||||
Health
|
||||
)
|
||||
name_chinese=(
|
||||
东东农场
|
||||
东东萌宠
|
||||
京东种豆得豆
|
||||
京喜工厂
|
||||
东东工厂
|
||||
京东赚赚
|
||||
crazyJoy任务
|
||||
京喜农场
|
||||
口袋书店
|
||||
签到领现金
|
||||
闪购盲盒
|
||||
京喜财富岛
|
||||
东东健康社区
|
||||
)
|
|
@ -1,599 +0,0 @@
|
|||
## Version: v3.30.6
|
||||
## Date: 2021-3-8
|
||||
## Update Content: 京小兑控制变量,宠汪汪自己内部账户互助变量,环球挑战赛互助变量。
|
||||
|
||||
## 上面版本号中,如果第2位数字有变化,那么代表增加了新的参数,如果只有第3位数字有变化,仅代表更新了注释,没有增加新的参数,可更新可不更新
|
||||
|
||||
################################## 说明 ##################################
|
||||
## 以下配置中,带有 export 申明的,均由LXK9301大佬定义,详见:https://gitee.com/lxk0301/jd_scripts/blob/master/githubAction.md
|
||||
## 其他互助码,考虑到直接按LXK9301大佬定义的变量去填的话,一是不方便记忆,二是容易搞混,所以最终的变量将由脚本去组合,你只要按注释去填即可
|
||||
## 除此之外,还额外增加了是否自动删除失效任务AutoDelCron、是否自动增加新任务AutoAddCron、删除旧日志时间RmLogDaysAgo、随机延迟启动任务RandomDelay、是否添加自定义脚本EnableExtraShell五个人性化的设置供选择
|
||||
## 所有赋值等号两边不能有空格,所有的值请一律在两侧添加半角的双引号,如果变量值中含有双引号,则外侧改为一对半角的单引号。
|
||||
## 所有的赋值都可以参考 “定义东东萌宠是否静默运行” 部分,在不同时间设置不同的值,以达到你想要的效果,具体判断条件如下:
|
||||
## $(date "+%d") 当前的日期,如:13
|
||||
## $(date "+%w") 当前是星期几,如:3
|
||||
## $(date "+%H") 当前的小时数,如:23
|
||||
## $(date "+%M") 当前的分钟数,如:49
|
||||
## 其他date命令的更多用法,可以在命令行中输入 date --help 查看
|
||||
## 判断条件 -eq -ne -gt -ge -lt -le ,具体含义可百度一下
|
||||
|
||||
|
||||
################################## 临时屏蔽某个Cookie(选填) ##################################
|
||||
## 如果某些Cookie已经失效了,但暂时还没法更新,可以使用此功能在不删除该Cookie和重新修改Cookie编号的前提下,临时屏蔽掉某些编号的Cookie
|
||||
## 多个Cookie编号以半角的空格分隔,两侧一对半角双引号,使用此功能后,在运行js脚本时账户编号将发生变化
|
||||
## 举例1:TempBlockCookie="2" 临时屏蔽掉Cookie2
|
||||
## 举例2:TempBlockCookie="2 4" 临时屏蔽掉Cookie2和Cookie4
|
||||
## 如果只是想要屏蔽某个账号不玩某些小游戏,可以参考下面 case 这个命令的例子来控制,脚本名称请去掉后缀 “.js”
|
||||
## case $1 in
|
||||
## jd_fruit)
|
||||
## TempBlockCookie="5" # 账号5不玩东东农场
|
||||
## ;;
|
||||
## jd_dreamFactory | jd_jdfactory)
|
||||
## TempBlockCookie="2" # 账号2不玩京喜工厂和东东工厂
|
||||
## ;;
|
||||
## jd_jdzz | jd_joy)
|
||||
## TempBlockCookie="3 6" # 账号3、账号6不玩京东赚赚和宠汪汪
|
||||
## ;;
|
||||
## esac
|
||||
TempBlockCookie=""
|
||||
|
||||
|
||||
################################## 定义是否自动删除失效的脚本与定时任务(选填) ##################################
|
||||
## 有的时候,某些JS脚本只在特定的时间有效,过了时间就失效了,需要自动删除失效的本地定时任务,则设置为 "true" ,否则请设置为 "false"
|
||||
## 检测文件:LXK9301/jd_scripts 仓库中的 docker/crontab_list.sh,和 shylocks/Loon 仓库中的 docker/crontab_list.sh
|
||||
## 当设置为 "true" 时,会自动从检测文件中读取比对删除的任务(识别以“jd_”、“jr_”、“jx_”开头的任务)
|
||||
## 当设置为 "true" 时,脚本只会删除一整行失效的定时任务,不会修改其他现有任务,所以任何时候,你都可以自己调整你的crontab.list
|
||||
## 当设置为 "true" 时,如果你有添加额外脚本是以“jd_”“jr_”“jx_”开头的,如检测文件中,会被删除,不是以“jd_”“jr_”“jx_”开头的任务则不受影响
|
||||
AutoDelCron="true"
|
||||
|
||||
|
||||
################################## 定义是否自动增加新的本地定时任务(选填) ##################################
|
||||
## LXK9301 大佬会在有需要的时候,增加定时任务,如需要本地自动增加新的定时任务,则设置为 "true" ,否则请设置为 "false"
|
||||
## 检测文件:LXK9301/jd_scripts 仓库中的 docker/crontab_list.sh,和 shylocks/Loon 仓库中的 docker/crontab_list.sh
|
||||
## 当设置为 "true" 时,如果检测到检测文件中有增加新的定时任务,那么在本地也增加(识别以“jd_”、“jr_”、“jx_”开头的任务)
|
||||
## 当设置为 "true" 时,会自动从检测文件新增加的任务中读取时间,该时间为北京时间
|
||||
## 当设置为 "true" 时,脚本只会增加新的定时任务,不会修改其他现有任务,所以任何时候,你都可以自己调整你的crontab.list
|
||||
AutoAddCron="true"
|
||||
|
||||
|
||||
################################## 定义删除日志的时间(选填) ##################################
|
||||
## 定义在运行删除旧的日志任务时,要删除多少天以前的日志,请输入正整数,不填则禁用删除日志的功能
|
||||
RmLogDaysAgo="7"
|
||||
|
||||
|
||||
################################## 定义随机延迟启动任务(选填) ##################################
|
||||
## 如果任务不是必须准点运行的任务,那么给它增加一个随机延迟,由你定义最大延迟时间,单位为秒,如 RandomDelay="300" ,表示任务将在 1-300 秒内随机延迟一个秒数,然后再运行
|
||||
## 在crontab.list中,在每小时第0-2分、第30-31分、第59分这几个时间内启动的任务,均算作必须准点运行的任务,在启动这些任务时,即使你定义了RandomDelay,也将准点运行,不启用随机延迟
|
||||
## 在crontab.list中,除掉每小时上述时间启动的任务外,其他任务在你定义了 RandomDelay 的情况下,一律启用随机延迟,但如果你按照Wiki教程给某些任务添加了 "now",那么这些任务也将无视随机延迟直接启动
|
||||
RandomDelay="300"
|
||||
|
||||
|
||||
################################## 定义User-Agent(选填) ##################################
|
||||
## 自定义LXK9301大佬仓库里京东系列js脚本的User-Agent,不懂不知不会User-Agent的请不要随意填写内容,随意填写了出错概不负责
|
||||
## 如需使用,请自行解除下一行注释
|
||||
# export JD_USER_AGENT=""
|
||||
|
||||
|
||||
################################## 定义通知TOKEN(选填) ##################################
|
||||
## 想通过什么渠道收取通知,就填入对应渠道的值
|
||||
## 1. ServerChan,教程:http://sc.ftqq.com/3.version
|
||||
export PUSH_KEY=""
|
||||
|
||||
## 2. BARK,教程(看BARK_PUSH和BARK_SOUND的说明):https://gitee.com/lxk0301/jd_scripts/blob/master/githubAction.md
|
||||
export BARK_PUSH=""
|
||||
export BARK_SOUND=""
|
||||
|
||||
## 3. Telegram,如需使用,TG_BOT_TOKEN和TG_USER_ID必须同时赋值,教程:https://gitee.com/lxk0301/jd_scripts/blob/master/backUp/TG_PUSH.md
|
||||
export TG_BOT_TOKEN=""
|
||||
export TG_USER_ID=""
|
||||
|
||||
## 4. 钉钉,教程(看DD_BOT_TOKEN和DD_BOT_SECRET部分):https://gitee.com/lxk0301/jd_scripts/blob/master/githubAction.md
|
||||
export DD_BOT_TOKEN=""
|
||||
export DD_BOT_SECRET=""
|
||||
|
||||
## 5. iGot聚合推送,支持多方式推送,填写iGot的推送key。教程:https://gitee.com/lxk0301/jd_scripts/blob/master/githubAction.md
|
||||
export IGOT_PUSH_KEY=""
|
||||
|
||||
## 6. Push Plus,微信扫码登录后一对一推送或一对多推送,参考文档:http://pushplus.hxtrip.com/
|
||||
## 其中PUSH_PLUS_USER是一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码)注:(1、需订阅者扫描二维码 2、如果您是创建群组所属人,也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送),只填PUSH_PLUS_TOKEN默认为一对一推送
|
||||
export PUSH_PLUS_TOKEN=""
|
||||
export PUSH_PLUS_USER=""
|
||||
|
||||
## 7. 企业微信机器人消息推送 webhook 后面的 key,文档:https://work.weixin.qq.com/api/doc/90000/90136/91770
|
||||
export QYWX_KEY=""
|
||||
|
||||
## 8. 企业微信应用消息推送的值,教程:https://note.youdao.com/ynoteshare1/index.html?id=351e08a72378206f9dd64d2281e9b83b&type=note
|
||||
## 依次填上corpid的值,corpsecret的值,touser的值,agentid,media_id的值,注意用,号隔开,例如:"wwcff56746d9adwers,B-791548lnzXBE6_BWfxdf3kSTMJr9vFEPKAbh6WERQ,mingcheng,1000001,2COXgjH2UIfERF2zxrtUOKgQ9XklUqMdGSWLBoW_lSDAdafat"
|
||||
export QYWX_AM=""
|
||||
|
||||
|
||||
################################## 定义每日签到的通知形式(选填) ##################################
|
||||
## js脚本每日签到提供3种通知方式,分别为:
|
||||
## 关闭通知,那么请在下方填入0
|
||||
## 简洁通知,那么请在下方填入1,其效果见:https://github.com/LXK9301/jd_scripts/blob/master/icon/bean_sign_simple.jpg
|
||||
## 原始通知,那么请在下方填入2,如果不填也默认为2,内容比较长,这也是默认通知方式
|
||||
NotifyBeanSign=""
|
||||
|
||||
|
||||
################################## 定义每日签到每个接口间的延迟时间(选填) ##################################
|
||||
## 默认每个签到接口并发无延迟,如需要依次进行每个接口,请自定义延迟时间,单位为毫秒,延迟作用于每个签到接口, 如填入延迟则切换顺序签到(耗时较长)
|
||||
export JD_BEAN_STOP=""
|
||||
|
||||
|
||||
################################## 定义东东农场互助(选填) ##################################
|
||||
## 具体填法及要求详见本文件最下方“互助码填法示例”
|
||||
MyFruit1=""
|
||||
MyFruit2=""
|
||||
MyFruit3=""
|
||||
MyFruit4=""
|
||||
MyFruit5=""
|
||||
MyFruit6=""
|
||||
MyFruitA=""
|
||||
MyFruitB=""
|
||||
|
||||
ForOtherFruit1=""
|
||||
ForOtherFruit2=""
|
||||
ForOtherFruit3=""
|
||||
ForOtherFruit4=""
|
||||
ForOtherFruit5=""
|
||||
ForOtherFruit6=""
|
||||
|
||||
|
||||
################################## 定义东东萌宠互助(选填) ##################################
|
||||
## 具体填法及要求详见本文件最下方“互助码填法示例”
|
||||
MyPet1=""
|
||||
MyPet2=""
|
||||
MyPet3=""
|
||||
MyPet4=""
|
||||
MyPet5=""
|
||||
MyPet6=""
|
||||
MyPetA=""
|
||||
MyPetB=""
|
||||
|
||||
ForOtherPet1=""
|
||||
ForOtherPet2=""
|
||||
ForOtherPet3=""
|
||||
ForOtherPet4=""
|
||||
ForOtherPet5=""
|
||||
ForOtherPet6=""
|
||||
|
||||
|
||||
################################## 定义种豆得豆互助(选填) ##################################
|
||||
## 具体填法及要求详见本文件最下方“互助码填法示例”
|
||||
MyBean1=""
|
||||
MyBean2=""
|
||||
MyBean3=""
|
||||
MyBean4=""
|
||||
MyBean5=""
|
||||
MyBean6=""
|
||||
MyBeanA=""
|
||||
MyBeanB=""
|
||||
|
||||
ForOtherBean1=""
|
||||
ForOtherBean2=""
|
||||
ForOtherBean3=""
|
||||
ForOtherBean4=""
|
||||
ForOtherBean5=""
|
||||
ForOtherBean6=""
|
||||
|
||||
|
||||
################################## 定义京喜工厂互助(选填) ##################################
|
||||
## 具体填法及要求详见本文件最下方“互助码填法示例”
|
||||
MyDreamFactory1=""
|
||||
MyDreamFactory2=""
|
||||
MyDreamFactory3=""
|
||||
MyDreamFactory4=""
|
||||
MyDreamFactory5=""
|
||||
MyDreamFactory6=""
|
||||
MyDreamFactoryA=""
|
||||
MyDreamFactoryB=""
|
||||
|
||||
ForOtherDreamFactory1=""
|
||||
ForOtherDreamFactory2=""
|
||||
ForOtherDreamFactory3=""
|
||||
ForOtherDreamFactory4=""
|
||||
ForOtherDreamFactory5=""
|
||||
ForOtherDreamFactory6=""
|
||||
|
||||
|
||||
################################## 定义东东工厂互助(选填) ##################################
|
||||
## 具体填法及要求详见本文件最下方“互助码填法示例”
|
||||
MyJdFactory1=""
|
||||
MyJdFactory2=""
|
||||
MyJdFactory3=""
|
||||
MyJdFactory4=""
|
||||
MyJdFactory5=""
|
||||
MyJdFactory6=""
|
||||
MyJdFactoryA=""
|
||||
MyJdFactoryB=""
|
||||
|
||||
ForOtherJdFactory1=""
|
||||
ForOtherJdFactory2=""
|
||||
ForOtherJdFactory3=""
|
||||
ForOtherJdFactory4=""
|
||||
ForOtherJdFactory5=""
|
||||
ForOtherJdFactory6=""
|
||||
|
||||
|
||||
################################## 定义京东赚赚互助(选填) ##################################
|
||||
## 具体填法及要求详见本文件最下方“互助码填法示例”
|
||||
MyJdzz1=""
|
||||
MyJdzz2=""
|
||||
MyJdzz3=""
|
||||
MyJdzz4=""
|
||||
MyJdzz5=""
|
||||
MyJdzz6=""
|
||||
MyJdzzA=""
|
||||
MyJdzzB=""
|
||||
|
||||
ForOtherJdzz1=""
|
||||
ForOtherJdzz2=""
|
||||
ForOtherJdzz3=""
|
||||
ForOtherJdzz4=""
|
||||
ForOtherJdzz5=""
|
||||
ForOtherJdzz6=""
|
||||
|
||||
|
||||
################################## 定义疯狂的JOY互助(选填) ##################################
|
||||
## 具体填法及要求详见本文件最下方“互助码填法示例”
|
||||
MyJoy1=""
|
||||
MyJoy2=""
|
||||
MyJoy3=""
|
||||
MyJoy4=""
|
||||
MyJoy5=""
|
||||
MyJoy6=""
|
||||
MyJoyA=""
|
||||
MyJoyB=""
|
||||
|
||||
ForOtherJoy1=""
|
||||
ForOtherJoy2=""
|
||||
ForOtherJoy3=""
|
||||
ForOtherJoy4=""
|
||||
ForOtherJoy5=""
|
||||
ForOtherJoy6=""
|
||||
|
||||
|
||||
################################## 定义京喜农场互助(选填) ##################################
|
||||
## 具体填法及要求详见本文件最下方“互助码填法示例”
|
||||
## 京喜农场助力码为 JSON 格式因此使用单引号,json 格式如下
|
||||
## {"smp":"22bdadsfaadsfadse8a","active":"jdnc_1_btorange210113_2","joinnum":"1"}
|
||||
## 助力码获取可以通过 js jd_get_share_code now 命令获取
|
||||
## 注意:京喜农场 种植种子发生变化的时候,互助码也会变!!
|
||||
MyJxnc1=''
|
||||
MyJxnc2=''
|
||||
MyJxnc3=''
|
||||
MyJxnc4=''
|
||||
MyJxnc5=''
|
||||
MyJxnc6=''
|
||||
MyJxncA=''
|
||||
MyJxncB=''
|
||||
|
||||
ForOtherJxnc1=""
|
||||
ForOtherJxnc2=""
|
||||
ForOtherJxnc3=""
|
||||
ForOtherJxnc4=""
|
||||
ForOtherJxnc5=""
|
||||
ForOtherJxnc6=""
|
||||
|
||||
|
||||
################################## 定义京喜农场TOKEN(选填) ##################################
|
||||
## 如果某个Cookie的账号种植的是app种子,则必须填入有效的TOKEN;而种植非app种子则不需要TOKEN
|
||||
## TOKEN的形式:{"farm_jstoken":"749a90f871adsfads8ffda7bf3b1576760","timestamp":"1610165423873","phoneid":"42c7e3dadfadsfdsaac-18f0e4f4a0cf"}
|
||||
## 因TOKEN中带有双引号,因此,变量值两侧必须由一对单引号引起来
|
||||
## TOKEN如何获取请阅读以下文件的注释:https://github.com/LXK9301/jd_scripts/blob/master/jd_jxnc.js
|
||||
TokenJxnc1=''
|
||||
TokenJxnc2=''
|
||||
TokenJxnc3=''
|
||||
TokenJxnc4=''
|
||||
TokenJxnc5=''
|
||||
TokenJxnc6=''
|
||||
|
||||
|
||||
################################## 定义口袋书店互助(选填) ##################################
|
||||
## 具体填法及要求详见本文件最下方“互助码填法示例”
|
||||
MyBookShop1=""
|
||||
MyBookShop2=""
|
||||
MyBookShop3=""
|
||||
MyBookShop4=""
|
||||
MyBookShop5=""
|
||||
MyBookShop6=""
|
||||
MyBookShopA=""
|
||||
MyBookShopB=""
|
||||
|
||||
ForOtherBookShop1=""
|
||||
ForOtherBookShop2=""
|
||||
ForOtherBookShop3=""
|
||||
ForOtherBookShop4=""
|
||||
ForOtherBookShop5=""
|
||||
ForOtherBookShop6=""
|
||||
|
||||
|
||||
################################## 定义签到领现金互助(选填) ##################################
|
||||
## 具体填法及要求详见本文件最下方“互助码填法示例”
|
||||
MyCash1=""
|
||||
MyCash2=""
|
||||
MyCash3=""
|
||||
MyCash4=""
|
||||
MyCash5=""
|
||||
MyCash6=""
|
||||
MyCashA=""
|
||||
MyCashB=""
|
||||
|
||||
ForOtherCash1=""
|
||||
ForOtherCash2=""
|
||||
ForOtherCash3=""
|
||||
ForOtherCash4=""
|
||||
ForOtherCash5=""
|
||||
ForOtherCash6=""
|
||||
|
||||
|
||||
################################## 定义闪购盲盒互助(选填) ##################################
|
||||
## 具体填法及要求详见本文件最下方“互助码填法示例”
|
||||
MySgmh1=""
|
||||
MySgmh2=""
|
||||
MySgmh3=""
|
||||
MySgmh4=""
|
||||
MySgmh5=""
|
||||
MySgmh6=""
|
||||
MySgmhA=""
|
||||
MySgmhB=""
|
||||
|
||||
ForOtherSgmh1=""
|
||||
ForOtherSgmh2=""
|
||||
ForOtherSgmh3=""
|
||||
ForOtherSgmh4=""
|
||||
ForOtherSgmh5=""
|
||||
ForOtherSgmh6=""
|
||||
|
||||
|
||||
################################## 定义京东环球挑战赛活动互助(选填) ##################################
|
||||
## 具体填法及要求详见本文件最下方“互助码填法示例”
|
||||
## 仅2021年2月22日(含)前有效
|
||||
MyGLOBAL1=""
|
||||
MyGLOBAL2=""
|
||||
MyGLOBAL3=""
|
||||
MyGLOBAL4=""
|
||||
MyGLOBAL5=""
|
||||
MyGLOBAL6=""
|
||||
MyGLOBALA=""
|
||||
MyGLOBALB=""
|
||||
|
||||
ForOtherGLOBAL1=""
|
||||
ForOtherGLOBAL2=""
|
||||
ForOtherGLOBAL3=""
|
||||
ForOtherGLOBAL4=""
|
||||
ForOtherGLOBAL5=""
|
||||
ForOtherGLOBAL6=""
|
||||
|
||||
################################## 定义惊喜财富岛互助(选填) ##################################
|
||||
## 具体填法及要求详见本文件最下方“互助码填法示例”
|
||||
MyJdcfd1=""
|
||||
MyJdcfd2=""
|
||||
MyJdcfd3=""
|
||||
MyJdcfd4=""
|
||||
MyJdcfd5=""
|
||||
MyJdcfd6=""
|
||||
MyJdcfdA=""
|
||||
MyJdcfdB=""
|
||||
|
||||
|
||||
ForOtherJdcfd1=""
|
||||
ForOtherJdcfd2=""
|
||||
ForOtherJdcfd3=""
|
||||
ForOtherJdcfd4=""
|
||||
ForOtherJdcfd5=""
|
||||
ForOtherJdcfd6=""
|
||||
|
||||
################################## 定义东东超市蓝币兑换数量(选填) ##################################
|
||||
## 东东超市蓝币兑换,可用值包括:
|
||||
## 一、0:表示不兑换京豆,这也是js脚本的默认值
|
||||
## 二、20:表示兑换20个京豆
|
||||
## 三、1000:表示兑换1000个京豆
|
||||
## 四、可兑换清单的商品名称,输入能跟唯一识别出来的关键词即可,比如:MARKET_COIN_TO_BEANS="抽纸"
|
||||
## 注意:有些比较贵的实物商品京东只是展示出来忽悠人的,即使你零点用脚本去抢,也会提示没有或提示已下架
|
||||
export MARKET_COIN_TO_BEANS="0"
|
||||
|
||||
|
||||
################################## 定义东东超市蓝币成功兑换奖品是否静默运行(选填) ##################################
|
||||
## 默认 "false" 关闭(即:奖品兑换成功后会发出通知提示),如需要静默运行不发出通知,请改为 "true"
|
||||
export MARKET_REWARD_NOTIFY=""
|
||||
|
||||
|
||||
################################## 定义东东超市是否自动升级商品和货架(选填) ##################################
|
||||
## 升级顺序:解锁升级商品、升级货架,默认 "true" 自动升级,如需关闭自动升级,请改为 "false"
|
||||
export SUPERMARKET_UPGRADE=""
|
||||
|
||||
|
||||
################################## 定义东东超市是否自动更换商圈(选填) ##################################
|
||||
## 小于对方300热力值自动更换商圈队伍,默认 "true" 自动更换,如不想更换商圈,请改为 "false"
|
||||
## 目前已无此功能,申明了也无效
|
||||
# export BUSINESS_CIRCLE_JUMP=""
|
||||
|
||||
|
||||
################################## 定义东东超市是否自动使用金币去抽奖(选填) ##################################
|
||||
## 是否用金币去抽奖,默认 "false" 关闭,如需开启,请修改为 "true"
|
||||
export SUPERMARKET_LOTTERY=""
|
||||
|
||||
|
||||
################################## 定义东东超市是否自动参加PK队伍(选填) ##################################
|
||||
## 是否每次PK活动参加脚本作者创建的PK队伍,"true" 表示参加,"false" 表示不参加,默认为 "true"
|
||||
export JOIN_PK_TEAM=""
|
||||
|
||||
|
||||
################################## 定义东东农场是否静默运行(选填) ##################################
|
||||
## 默认为 "false",不静默,发送推送通知消息,如不想收到通知,请修改为 "true"
|
||||
## 如果你不想完全关闭或者完全开启通知,只想在特定的时间发送通知,可以参考下面的“定义东东萌宠是否静默运行”部分,设定几个if判断条件
|
||||
export FRUIT_NOTIFY_CONTROL=""
|
||||
|
||||
|
||||
################################## 定义东东农场是否使用水滴换豆卡(选填) ##################################
|
||||
## 如果出现限时活动时100g水换20豆,此时比浇水划算,"true" 表示换豆(不浇水),"false" 表示不换豆(继续浇水),默认是"false"
|
||||
## 如需切换为换豆(不浇水),请修改为 "true"
|
||||
export FRUIT_BEAN_CARD=""
|
||||
|
||||
|
||||
################################## 定义宠汪汪喂食克数(选填) ##################################
|
||||
## 你期望的宠汪汪每次喂食克数,只能填入10、20、40、80,默认为10
|
||||
## 如实际持有食物量小于所设置的克数,脚本会自动降一档,直到降无可降
|
||||
## 具体情况请自行在宠汪汪游戏中去查阅攻略
|
||||
export JOY_FEED_COUNT=""
|
||||
|
||||
|
||||
################################## 定义宠汪汪兑换京豆数量(选填) ##################################
|
||||
## 目前的可用值包括:0、20、500、1000,其中0表示为不自动兑换京豆,如不设置,将默认为"20"
|
||||
## 不同等级可兑换不同数量的京豆,详情请见宠汪汪游戏中兑换京豆选项
|
||||
## 500、1000的京豆每天有总量限制,设置了并且你也有足够积分时,也并不代表就一定能抢到
|
||||
export JD_JOY_REWARD_NAME=""
|
||||
|
||||
|
||||
################################## 定义宠汪汪兑换京豆是否静默运行(选填) ##################################
|
||||
## 默认为 "false",在成功兑换京豆时将发送推送通知消息(失败不发送),如想要静默不发送通知,请修改为 "true"
|
||||
export JD_JOY_REWARD_NOTIFY=""
|
||||
|
||||
|
||||
################################## 定义宠汪汪是否自动给好友的汪汪喂食(选填) ##################################
|
||||
## 默认 "false" 不会自动给好友的汪汪喂食,如想自动喂食,请改成 "true"
|
||||
export JOY_HELP_FEED=""
|
||||
|
||||
|
||||
################################## 定义宠汪汪是否自动报名宠物赛跑(选填) ##################################
|
||||
## 默认 "true" 参加宠物赛跑,如需关闭,请改成 "false"
|
||||
export JOY_RUN_FLAG=""
|
||||
|
||||
|
||||
################################## 定义宠汪汪参加比赛类型(选填) ##################################
|
||||
## 当JOY_RUN_FLAG不设置或设置为 "true" 时生效
|
||||
## 可选值:2,10,50,其他值不可以。其中2代表参加双人PK赛,10代表参加10人突围赛,50代表参加50人挑战赛,不填时默认为2
|
||||
## 各个账号间请使用 & 分隔,比如:JOY_TEAM_LEVEL="2&2&50&10"
|
||||
## 如果你有5个账号但只写了四个数字,那么第5个账号将默认参加2人赛,账号如果更多,与此类似
|
||||
export JOY_TEAM_LEVEL=""
|
||||
|
||||
|
||||
################################## 定义宠汪汪赛跑获胜后是否推送通知(选填) ##################################
|
||||
## 控制jd_joy.js脚本宠汪汪赛跑获胜后是否推送通知,"false" 为否(不推送通知消息),"true" 为是(即:发送推送通知消息),默认为 "true"
|
||||
export JOY_RUN_NOTIFY=""
|
||||
|
||||
|
||||
################################## 定义摇钱树是否自动将金果卖出变成金币(选填) ##################################
|
||||
## 金币有时效,默认为 "false",不卖出金果为金币,如想希望自动卖出,请修改为 "true"
|
||||
export MONEY_TREE_SELL_FRUIT=""
|
||||
|
||||
|
||||
################################## 定义东东萌宠是否静默运行(选填) ##################################
|
||||
## 默认 "false"(不静默,发送推送通知消息),如想静默请修改为 true
|
||||
## 每次执行脚本通知太频繁了,改成只在周三和周六中午那一次运行时发送通知提醒
|
||||
## 除掉上述提及时间之外,均设置为 true,静默不发通知
|
||||
## 特别说明:针对北京时间有效。
|
||||
if [ $(date "+%w") -eq 6 ] && [ $(date "+%H") -ge 9 ] && [ $(date "+%H") -lt 14 ]; then
|
||||
export PET_NOTIFY_CONTROL="false"
|
||||
elif [ $(date "+%w") -eq 3 ] && [ $(date "+%H") -ge 9 ] && [ $(date "+%H") -lt 14 ]; then
|
||||
export PET_NOTIFY_CONTROL="false"
|
||||
else
|
||||
export PET_NOTIFY_CONTROL="true"
|
||||
fi
|
||||
|
||||
|
||||
################################## 定义京喜工厂控制哪个京东账号不运行此脚本(选填) ##################################
|
||||
## 输入"1"代表第一个京东账号不运行,多个使用 & 连接,例:"1&3" 代表账号1和账号3不运行京喜工厂脚本,注:输入"0",代表全部账号不运行京喜工厂脚本
|
||||
## 如果使用了 “临时屏蔽某个Cookie” TempBlockCookie 功能,编号会发生变化
|
||||
export DREAMFACTORY_FORBID_ACCOUNT=""
|
||||
|
||||
|
||||
################################## 定义东东工厂控制哪个京东账号不运行此脚本(选填) ##################################
|
||||
## 输入"1"代表第一个京东账号不运行,多个使用 & 连接,例:"1&3" 代表账号1和账号3不运行东东工厂脚本,注:输入"0",代表全部账号不运行东东工厂脚本
|
||||
## 如果使用了 “临时屏蔽某个Cookie” TempBlockCookie 功能,编号会发生变化
|
||||
export JDFACTORY_FORBID_ACCOUNT=""
|
||||
|
||||
|
||||
################################## 定义东东工厂心仪的商品(选填) ##################################
|
||||
## 只有在满足以下条件时,才自动投入电力:一是存储的电力满足生产商品所需的电力,二是心仪的商品有库存,如果没有输入心仪的商品,那么当前你正在生产的商品视作心仪的商品
|
||||
## 如果你看不懂上面的话,请去东东工厂游戏中查阅攻略
|
||||
## 心仪的商品请输入商品的全称或能唯一识别出该商品的关键字
|
||||
export FACTORAY_WANTPRODUCT_NAME=""
|
||||
|
||||
|
||||
################################## 定义京喜农场通知级别(选填) ##################################
|
||||
## 可用值: 0(不通知); 1(本次获得水滴>0); 2(任务执行); 3(任务执行+未种植种子),默认为"3"
|
||||
export JXNC_NOTIFY_LEVEL="3"
|
||||
|
||||
|
||||
################################## 定义取关参数(选填) ##################################
|
||||
## jd_unsubscribe这个任务是用来取关每天做任务关注的商品和店铺,默认在每次运行时取关20个商品和20个店铺
|
||||
## 如果取关数量不够,可以根据情况增加,还可以设置 jdUnsubscribeStopGoods 和 jdUnsubscribeStopShop
|
||||
## 商品取关数量
|
||||
goodPageSize=""
|
||||
## 店铺取关数量
|
||||
shopPageSize=""
|
||||
## 遇到此商品不再取关此商品以及它后面的商品,需去商品详情页长按拷贝商品信息
|
||||
jdUnsubscribeStopGoods=""
|
||||
## 遇到此店铺不再取关此店铺以及它后面的店铺,请从头开始输入店铺名称
|
||||
jdUnsubscribeStopShop=""
|
||||
|
||||
|
||||
################################## 疯狂的JOY(选填) ##################################
|
||||
## 疯狂的JOY循环助力,"true" 表示循环助力,"false" 表示不循环助力,默认 "false"
|
||||
export JDJOY_HELPSELF=""
|
||||
|
||||
## 疯狂的JOY京豆兑换,目前最小值为500/1000京豆,默认为 "0" 不开启京豆兑换
|
||||
export JDJOY_APPLYJDBEAN=""
|
||||
|
||||
## 疯狂的JOY自动购买什么等级的JOY,如需要使用请自行解除注释
|
||||
# export BUY_JOY_LEVEL=""
|
||||
|
||||
|
||||
################################## 定义是否自动加购物车(选填) ##################################
|
||||
## 口袋书店和东东小窝有些任务需要将商品加进购物车才能完成,默认 "false" 不做这些任务,如想做,请设置为 "true"
|
||||
export PURCHASE_SHOPS=""
|
||||
|
||||
################################## 定义京喜财富岛通知(选填) ##################################
|
||||
## 输入true为通知,默认 "false",不填则为不通知
|
||||
export CFD_NOTIFY_CONTROL=""
|
||||
|
||||
|
||||
################################## 定义京小兑是否自动把抽奖卷兑换为兑币,(选填) ##################################
|
||||
## 输入true为自动兑换,不填则为不兑换
|
||||
export JD_JXD_EXCHANGE=""
|
||||
|
||||
|
||||
################################## 定义宠汪汪是否开启内部互助,(选填) ##################################
|
||||
## 输入true为开启内部互助,不填默认关闭
|
||||
export JOY_RUN_HELP_MYSELF=""
|
||||
|
||||
################################## Telegram 代理(选填) ##################################
|
||||
## Telegram 代理的 IP,代理类型为 http,比如你代理是 http://127.0.0.1:1080,则填写 "127.0.0.1"
|
||||
## 如需使用,请自行解除下一行的注释
|
||||
# export TG_PROXY_HOST=""
|
||||
|
||||
## Telegram 代理的端口,代理类型为 http,比如你代理是 http://127.0.0.1:1080,则填写 "1080"
|
||||
## 如需使用,请自行解除下一行的注释
|
||||
# export TG_PROXY_PORT=""
|
||||
|
||||
|
||||
################################## 是否添加DIY脚本(选填) ##################################
|
||||
## 如果你自己会写shell脚本,并且希望在每次git_pull.sh这个脚本运行时,额外运行你的DIY脚本,请赋值为 "true"
|
||||
## 同时,请务必将你的脚本命名为 extra.sh (只能叫这个文件名),放在 config 目录下
|
||||
## 仓库下已经上传extra.sh模板,如果你想使用;可以参考本仓库下 extra.sh 文件;地址:https://raw.githubusercontent.com/dockere/jd-base/master/sample/diy.sh
|
||||
EnableExtraShell=""
|
||||
|
||||
|
||||
################################## 互助码填法示例 ##################################
|
||||
## **互助码是填在My系列变量中的,ForOther系统变量中只要填入My系列的变量名即可,按注释中的例子拼接,以东东农场为例,如下所示。**
|
||||
## **实际上东东农场一个账号只能给别人助力3次,我多写的话,只有前几个会被助力。但如果前面的账号获得的助力次数已经达到上限了,那么还是会尝试继续给余下的账号助力,所以多填也是有意义的。**
|
||||
## **ForOther系列变量必须从1开始编号,依次编下去。**
|
||||
|
||||
# MyFruit1="e6e04602d5e343258873af1651b603ec" # 这是Cookie1这个账号的互助码
|
||||
# MyFruit2="52801b06ce2a462f95e1d59d7e856ef4" # 这是Cookie2这个账号的互助码
|
||||
# MyFruit3="e2fd1311229146cc9507528d0b054da8" # 这是Cookie3这个账号的互助码
|
||||
# MyFruit4="6dc9461f662d490991a31b798f624128" # 这是Cookie4这个账号的互助码
|
||||
# MyFruit5="30f29addd75d44e88fb452bbfe9f2110" # 这是Cookie5这个账号的互助码
|
||||
# MyFruit6="1d02fc9e0e574b4fa928e84cb1c5e70b" # 这是Cookie6这个账号的互助码
|
||||
# MyFruitA="5bc73a365ff74a559bdee785ea97fcc5" # 这是我和别人交换互助,另外一个用户A的互助码
|
||||
# MyFruitB="6d402dcfae1043fba7b519e0d6579a6f" # 这是我和别人交换互助,另外一个用户B的互助码
|
||||
# MyFruitC="5efc7fdbb8e0436f8694c4c393359576" # 这是我和别人交换互助,另外一个用户C的互助码
|
||||
|
||||
# ForOtherFruit1="${MyFruit2}@${MyFruitB}@${MyFruit4}" # Cookie1这个账号助力Cookie2的账号的账号、Cookie4的账号以及用户B
|
||||
# ForOtherFruit2="${MyFruit1}@${MyFruitA}@${MyFruit4}" # Cookie2这个账号助力Cookie1的账号的账号、Cookie4的账号以及用户A
|
||||
# ForOtherFruit3="${MyFruit1}@${MyFruit2}@${MyFruitC}@${MyFruit4}@${MyFruitA}@${MyFruit6}" # 解释同上,东东农场实际上只能助力3次
|
||||
# ForOtherFruit4="${MyFruit1}@${MyFruit2}@${MyFruit3}@${MyFruitC}@${MyFruit6}@${MyFruitA}" # 解释同上,东东农场实际上只能助力3次
|
||||
# ForOtherFruit5="${MyFruit1}@${MyFruit2}@${MyFruit3}@${MyFruitB}@${MyFruit4}@${MyFruit6}@${MyFruitC}@${MyFruitA}"
|
||||
# ForOtherFruit6="${MyFruit1}@${MyFruit2}@${MyFruit3}@${MyFruitA}@${MyFruit4}@${MyFruit5}@${MyFruitC}"
|
|
@ -1,27 +0,0 @@
|
|||
# 更新shell及面板代码
|
||||
55 2,13 * * * git_pull >> ${QL_DIR}/log/git_pull.log 2>&1
|
||||
|
||||
# 更新你需要的仓库的代码
|
||||
# diy test作者 test仓库 test路径1|test路径2 黑名单1文件名|黑名单2文件名
|
||||
33 * * * * diy whyour hundun "quanx/jx|quanx/jd" tokens >> ${QL_DIR}/log/diy_pull.log 2>&1
|
||||
31 * * * * diy monk-coder dust i-chenzhe >> ${QL_DIR}/log/diy_pull.log 2>&1
|
||||
|
||||
# 重新build面板
|
||||
# 30 7 */7 * * rebuild >> ${QL_DIR}/log/rebuild.log 2>&1
|
||||
|
||||
# 删除 RmLogDaysAgo 指定天数以前的旧日志,本行为不记录日志
|
||||
57 13 * * * rm_log >/dev/null 2>&1
|
||||
|
||||
# 导出所有互助码清单,日志在log/export_sharecodes下
|
||||
48 5 * * * export_sharecodes
|
||||
|
||||
# 重启挂机脚本
|
||||
# 33 3 * * * js hangup
|
||||
|
||||
# 重置密码
|
||||
# 33 6 */7 * * js resetpwd
|
||||
|
||||
# 运行所有脚本(慎用)
|
||||
# 33 9 */7 * * js runall
|
||||
|
||||
# 其他定时任务
|
742
sample/notify.js
Normal file
742
sample/notify.js
Normal file
File diff suppressed because one or more lines are too long
277
sample/notify.py
Normal file
277
sample/notify.py
Normal file
|
@ -0,0 +1,277 @@
|
|||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import sys
|
||||
import os
|
||||
cur_path = os.path.abspath(os.path.dirname(__file__))
|
||||
root_path = os.path.split(cur_path)[0]
|
||||
sys.path.append(root_path)
|
||||
import requests
|
||||
import json
|
||||
import traceback
|
||||
import time
|
||||
import hmac
|
||||
import hashlib
|
||||
import base64
|
||||
import urllib.parse
|
||||
from requests.adapters import HTTPAdapter
|
||||
from urllib3.util import Retry
|
||||
import re
|
||||
|
||||
# 通知服务
|
||||
BARK = '' # bark服务,此参数如果以http或者https开头则判定为自建bark服务; secrets可填;
|
||||
SCKEY = '' # Server酱的SCKEY; secrets可填
|
||||
TG_BOT_TOKEN = '' # tg机器人的TG_BOT_TOKEN; secrets可填
|
||||
TG_USER_ID = '' # tg机器人的TG_USER_ID; secrets可填
|
||||
TG_PROXY_IP = '' # tg机器人的TG_PROXY_IP; secrets可填
|
||||
TG_PROXY_PORT = '' # tg机器人的TG_PROXY_PORT; secrets可填
|
||||
DD_BOT_ACCESS_TOKEN = '' # 钉钉机器人的DD_BOT_ACCESS_TOKEN; secrets可填
|
||||
DD_BOT_SECRET = '' # 钉钉机器人的DD_BOT_SECRET; secrets可填
|
||||
QYWX_APP = '' # 企业微信应用的QYWX_APP; secrets可填 参考http://note.youdao.com/s/HMiudGkb
|
||||
|
||||
notify_mode = []
|
||||
|
||||
# GitHub action运行需要填写对应的secrets
|
||||
if "BARK" in os.environ and os.environ["BARK"]:
|
||||
BARK = os.environ["BARK"]
|
||||
if "SCKEY" in os.environ and os.environ["SCKEY"]:
|
||||
SCKEY = os.environ["SCKEY"]
|
||||
if "TG_BOT_TOKEN" in os.environ and os.environ["TG_BOT_TOKEN"] and "TG_USER_ID" in os.environ and os.environ["TG_USER_ID"]:
|
||||
TG_BOT_TOKEN = os.environ["TG_BOT_TOKEN"]
|
||||
TG_USER_ID = os.environ["TG_USER_ID"]
|
||||
if "DD_BOT_ACCESS_TOKEN" in os.environ and os.environ["DD_BOT_ACCESS_TOKEN"] and "DD_BOT_SECRET" in os.environ and os.environ["DD_BOT_SECRET"]:
|
||||
DD_BOT_ACCESS_TOKEN = os.environ["DD_BOT_ACCESS_TOKEN"]
|
||||
DD_BOT_SECRET = os.environ["DD_BOT_SECRET"]
|
||||
if "QYWX_APP" in os.environ and os.environ["QYWX_APP"]:
|
||||
QYWX_APP = os.environ["QYWX_APP"]
|
||||
|
||||
if BARK:
|
||||
notify_mode.append('bark')
|
||||
print("BARK 推送打开")
|
||||
if SCKEY:
|
||||
notify_mode.append('sc_key')
|
||||
print("Server酱 推送打开")
|
||||
if TG_BOT_TOKEN and TG_USER_ID:
|
||||
notify_mode.append('telegram_bot')
|
||||
print("Telegram 推送打开")
|
||||
if DD_BOT_ACCESS_TOKEN and DD_BOT_SECRET:
|
||||
notify_mode.append('dingding_bot')
|
||||
print("钉钉机器人 推送打开")
|
||||
if QYWX_APP:
|
||||
notify_mode.append('qywxapp_bot')
|
||||
print("企业微信应用 推送打开")
|
||||
|
||||
def bark(title, content):
|
||||
print("\n")
|
||||
if not BARK:
|
||||
print("bark服务的bark_token未设置!!\n取消推送")
|
||||
return
|
||||
print("bark服务启动")
|
||||
url = None
|
||||
if BARK.startswith('http'):
|
||||
url = f"""{BARK}/{title}/{content}"""
|
||||
else:
|
||||
url = f"""https://api.day.app/{BARK}/{title}/{content}"""
|
||||
response = requests.get(url).json()
|
||||
if response['code'] == 200:
|
||||
print('推送成功!')
|
||||
else:
|
||||
print('推送失败!')
|
||||
|
||||
def serverJ(title, content):
|
||||
print("\n")
|
||||
if not SCKEY:
|
||||
print("server酱服务的SCKEY未设置!!\n取消推送")
|
||||
return
|
||||
print("serverJ服务启动")
|
||||
data = {
|
||||
"text": title,
|
||||
"desp": content.replace("\n", "\n\n")
|
||||
}
|
||||
response = requests.post(f"https://sc.ftqq.com/{SCKEY}.send", data=data).json()
|
||||
if response['errno'] == 0:
|
||||
print('推送成功!')
|
||||
else:
|
||||
print('推送失败!')
|
||||
|
||||
def telegram_bot(title, content):
|
||||
print("\n")
|
||||
bot_token = TG_BOT_TOKEN
|
||||
user_id = TG_USER_ID
|
||||
if not bot_token or not user_id:
|
||||
print("tg服务的bot_token或者user_id未设置!!\n取消推送")
|
||||
return
|
||||
print("tg服务启动")
|
||||
url=f"https://api.telegram.org/bot{TG_BOT_TOKEN}/sendMessage"
|
||||
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
|
||||
payload = {'chat_id': str(TG_USER_ID), 'text': f'{title}\n\n{content}', 'disable_web_page_preview': 'true'}
|
||||
proxies = None
|
||||
if TG_PROXY_IP and TG_PROXY_PORT:
|
||||
proxyStr = "http://{}:{}".format(TG_PROXY_IP, TG_PROXY_PORT)
|
||||
proxies = {"http": proxyStr, "https": proxyStr}
|
||||
response = requests.post(url=url, headers=headers, params=payload, proxies=proxies).json()
|
||||
if response['ok']:
|
||||
print('推送成功!')
|
||||
else:
|
||||
print('推送失败!')
|
||||
|
||||
def dingding_bot(title, content):
|
||||
timestamp = str(round(time.time() * 1000)) # 时间戳
|
||||
secret_enc = DD_BOT_SECRET.encode('utf-8')
|
||||
string_to_sign = '{}\n{}'.format(timestamp, DD_BOT_SECRET)
|
||||
string_to_sign_enc = string_to_sign.encode('utf-8')
|
||||
hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
|
||||
sign = urllib.parse.quote_plus(base64.b64encode(hmac_code)) # 签名
|
||||
print('开始使用 钉钉机器人 推送消息...', end='')
|
||||
url = f'https://oapi.dingtalk.com/robot/send?access_token={DD_BOT_ACCESS_TOKEN}×tamp={timestamp}&sign={sign}'
|
||||
headers = {'Content-Type': 'application/json;charset=utf-8'}
|
||||
data = {
|
||||
'msgtype': 'text',
|
||||
'text': {'content': f'{title}\n\n{content}'}
|
||||
}
|
||||
response = requests.post(url=url, data=json.dumps(data), headers=headers, timeout=15).json()
|
||||
if not response['errcode']:
|
||||
print('推送成功!')
|
||||
else:
|
||||
print('推送失败!')
|
||||
|
||||
def qywxapp_bot(title, content):
|
||||
print("\n")
|
||||
if not QYWX_APP:
|
||||
print("企业微信应用的QYWX_APP未设置!!\n取消推送")
|
||||
return
|
||||
print("企业微信应用启动")
|
||||
qywx_app_params = QYWX_APP.split(',')
|
||||
url='https://qyapi.weixin.qq.com/cgi-bin/gettoken'
|
||||
headers= {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
payload = {
|
||||
'corpid': qywx_app_params[0],
|
||||
'corpsecret': qywx_app_params[1],
|
||||
}
|
||||
response = requests.post(url=url, headers=headers, data=json.dumps(payload), timeout=15).json()
|
||||
accesstoken = response["access_token"]
|
||||
html = content.replace("\n", "<br/>")
|
||||
|
||||
options = None
|
||||
if not qywx_app_params[4]:
|
||||
options = {
|
||||
'msgtype': 'text',
|
||||
'text': {
|
||||
content: f'{title}\n\n${content}'
|
||||
}
|
||||
}
|
||||
elif qywx_app_params[4] == '0':
|
||||
options = {
|
||||
'msgtype': 'textcard',
|
||||
'textcard': {
|
||||
title: f'{title}',
|
||||
description: f'{content}',
|
||||
btntxt: '更多'
|
||||
}
|
||||
}
|
||||
elif qywx_app_params[4] == '1':
|
||||
options = {
|
||||
'msgtype': 'text',
|
||||
'text': {
|
||||
content: f'{title}\n\n${content}'
|
||||
}
|
||||
}
|
||||
else:
|
||||
options = {
|
||||
'msgtype': 'mpnews',
|
||||
'mpnews': {
|
||||
'articles': [
|
||||
{
|
||||
'title': f'{title}',
|
||||
'thumb_media_id': f'{qywx_app_params[4]}',
|
||||
'author': '智能助手',
|
||||
'content_source_url': '',
|
||||
'content': f'{html}',
|
||||
'digest': f'{content}'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
url=f"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={accesstoken}"
|
||||
data = {
|
||||
'touser': f'{change_user_id(content)}',
|
||||
'agentid': f'{qywx_app_params[3]}',
|
||||
'safe': '0'
|
||||
}
|
||||
data.update(options)
|
||||
headers = {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
response = requests.post(url=url, headers=headers, data=json.dumps(data)).json()
|
||||
|
||||
if response['errcode'] == 0:
|
||||
print('推送成功!')
|
||||
else:
|
||||
print('推送失败!')
|
||||
|
||||
def change_user_id(desp):
|
||||
qywx_app_params = QYWX_APP.split(',')
|
||||
if qywx_app_params[2]:
|
||||
userIdTmp = qywx_app_params[2].split("|")
|
||||
userId = ""
|
||||
for i in range(len(userIdTmp)):
|
||||
count1 = f"账号{i + 1}"
|
||||
count2 = f"签到号{i + 1}"
|
||||
if re.search(count1, desp) or re.search(count2, desp):
|
||||
userId = userIdTmp[i]
|
||||
if not userId:
|
||||
userId = qywx_app_params[2]
|
||||
return userId
|
||||
else:
|
||||
return "@all"
|
||||
|
||||
def send(title, content):
|
||||
"""
|
||||
使用 bark, telegram bot, dingding bot, serverJ 发送手机推送
|
||||
:param title:
|
||||
:param content:
|
||||
:return:
|
||||
"""
|
||||
for i in notify_mode:
|
||||
if i == 'bark':
|
||||
if BARK:
|
||||
bark(title=title, content=content)
|
||||
else:
|
||||
print('未启用 bark')
|
||||
continue
|
||||
if i == 'sc_key':
|
||||
if SCKEY:
|
||||
serverJ(title=title, content=content)
|
||||
else:
|
||||
print('未启用 Server酱')
|
||||
continue
|
||||
elif i == 'dingding_bot':
|
||||
if DD_BOT_ACCESS_TOKEN and DD_BOT_SECRET:
|
||||
dingding_bot(title=title, content=content)
|
||||
else:
|
||||
print('未启用 钉钉机器人')
|
||||
continue
|
||||
elif i == 'telegram_bot':
|
||||
if TG_BOT_TOKEN and TG_USER_ID:
|
||||
telegram_bot(title=title, content=content)
|
||||
else:
|
||||
print('未启用 telegram机器人')
|
||||
continue
|
||||
elif i == 'qywxapp_bot':
|
||||
if QYWX_APP:
|
||||
qywxapp_bot(title=title, content=content)
|
||||
else:
|
||||
print('未启用 企业微信应用推送')
|
||||
continue
|
||||
else:
|
||||
print('此类推送方式不存在')
|
||||
|
||||
def main():
|
||||
send('title', 'content')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
16
sample/package.json
Normal file
16
sample/package.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "dependence",
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"crypto-js": "^4.0.0",
|
||||
"download": "^8.0.0",
|
||||
"got": "^11.5.1",
|
||||
"http-server": "^0.12.3",
|
||||
"qrcode-terminal": "^0.12.0",
|
||||
"request": "^2.88.2",
|
||||
"tough-cookie": "^4.0.0",
|
||||
"tunnel": "0.0.6",
|
||||
"ws": "^7.4.3"
|
||||
}
|
||||
}
|
1
sample/requirements.txt
Normal file
1
sample/requirements.txt
Normal file
|
@ -0,0 +1 @@
|
|||
requests
|
97
shell/api.sh
97
shell/api.sh
|
@ -1,22 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
get_token() {
|
||||
token=$(cat $AuthConf | jq -r .token)
|
||||
}
|
||||
|
||||
get_json_value() {
|
||||
local json=$1
|
||||
local key=$2
|
||||
|
||||
if [[ -z "$3" ]]; then
|
||||
local num=1
|
||||
else
|
||||
local num=$3
|
||||
fi
|
||||
|
||||
local value=$(echo "${json}" | awk -F"[,:}]" '{for(i=1;i<=NF;i++){if($i~/'${key}'\042/){print $(i+1)}}}' | tr -d '"' | sed -n ${num}p)
|
||||
|
||||
echo ${value}
|
||||
token=$(cat $file_auth_user | jq -r .token)
|
||||
}
|
||||
|
||||
add_cron_api() {
|
||||
|
@ -31,7 +16,8 @@ add_cron_api() {
|
|||
local name=$3
|
||||
fi
|
||||
|
||||
local api=$(curl "http://localhost:5600/api/crons?t=$currentTimeStamp" \
|
||||
local api=$(
|
||||
curl -s "http://localhost:5600/api/crons?t=$currentTimeStamp" \
|
||||
-H "Accept: application/json" \
|
||||
-H "Authorization: Bearer $token" \
|
||||
-H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36" \
|
||||
|
@ -40,19 +26,58 @@ add_cron_api() {
|
|||
-H "Referer: http://localhost:5700/crontab" \
|
||||
-H "Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7" \
|
||||
--data-raw "{\"name\":\"$name\",\"command\":\"$command\",\"schedule\":\"$schedule\"}" \
|
||||
--compressed)
|
||||
--compressed
|
||||
)
|
||||
code=$(echo $api | jq -r .code)
|
||||
message=$(echo $api | jq -r .message)
|
||||
if [[ $code == 200 ]]; then
|
||||
echo -e "$name 添加成功"
|
||||
echo -e "$name -> 添加成功"
|
||||
else
|
||||
echo -e "$name 添加失败"
|
||||
echo -e "$name -> 添加失败(${message})"
|
||||
fi
|
||||
}
|
||||
|
||||
update_cron_api() {
|
||||
local currentTimeStamp=$(date +%s)
|
||||
if [ $# -eq 1 ]; then
|
||||
local schedule=$(echo "$1" | awk -F ":" '{print $1}')
|
||||
local command=$(echo "$1" | awk -F ":" '{print $2}')
|
||||
local name=$(echo "$1" | awk -F ":" '{print $3}')
|
||||
local id=$(echo "$1" | awk -F ":" '{print $4}')
|
||||
else
|
||||
local schedule=$1
|
||||
local command=$2
|
||||
local name=$3
|
||||
local id=$4
|
||||
fi
|
||||
|
||||
local api=$(
|
||||
curl -s "http://localhost:5600/api/crons?t=$currentTimeStamp" \
|
||||
-X 'PUT' \
|
||||
-H "Accept: application/json" \
|
||||
-H "Authorization: Bearer $token" \
|
||||
-H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36" \
|
||||
-H "Content-Type: application/json;charset=UTF-8" \
|
||||
-H "Origin: http://localhost:5700" \
|
||||
-H "Referer: http://localhost:5700/crontab" \
|
||||
-H "Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7" \
|
||||
--data-raw "{\"name\":\"$name\",\"command\":\"$command\",\"schedule\":\"$schedule\",\"_id\":\"$id\"}" \
|
||||
--compressed
|
||||
)
|
||||
code=$(echo $api | jq -r .code)
|
||||
message=$(echo $api | jq -r .message)
|
||||
if [[ $code == 200 ]]; then
|
||||
echo -e "$name -> 更新成功"
|
||||
else
|
||||
echo -e "$name -> 更新失败(${message})"
|
||||
fi
|
||||
}
|
||||
|
||||
del_cron_api() {
|
||||
local id=$1
|
||||
local ids=$1
|
||||
local currentTimeStamp=$(date +%s)
|
||||
local api=$(curl "http://localhost:5600/api/crons/$id?t=$currentTimeStamp" \
|
||||
local api=$(
|
||||
curl -s "http://localhost:5600/api/crons?t=$currentTimeStamp" \
|
||||
-X 'DELETE' \
|
||||
-H "Accept: application/json" \
|
||||
-H "Authorization: Bearer $token" \
|
||||
|
@ -60,11 +85,33 @@ del_cron_api() {
|
|||
-H "Content-Type: application/json;charset=UTF-8" \
|
||||
-H "Origin: http://localhost:5700" \
|
||||
-H "Referer: http://localhost:5700/crontab" \
|
||||
-H "Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7")
|
||||
-H "Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7" \
|
||||
--data-raw "[$ids]" \
|
||||
--compressed
|
||||
)
|
||||
code=$(echo $api | jq -r .code)
|
||||
message=$(echo $api | jq -r .message)
|
||||
if [[ $code == 200 ]]; then
|
||||
echo -e "$name 删除成功"
|
||||
echo -e "删除成功"
|
||||
else
|
||||
echo -e "$name 删除失败"
|
||||
echo -e "删除失败(${message})"
|
||||
fi
|
||||
}
|
||||
|
||||
get_user_info() {
|
||||
local currentTimeStamp=$(date +%s)
|
||||
local api=$(
|
||||
curl -s "http://localhost:5700/api/user?t=$currentTimeStamp" \
|
||||
-H 'Accept: */*' \
|
||||
-H "Authorization: Bearer $token" \
|
||||
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36' \
|
||||
-H 'Referer: http://localhost:5700/crontab' \
|
||||
-H 'Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7' \
|
||||
--compressed
|
||||
)
|
||||
code=$(echo $api | jq -r .code)
|
||||
if [[ $code != 200 ]]; then
|
||||
echo -e "请先登录!"
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
|
30
shell/bot.sh
Normal file
30
shell/bot.sh
Normal file
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
## 导入通用变量与函数
|
||||
dir_shell=/ql/shell
|
||||
. $dir_shell/share.sh
|
||||
repo_path="${dir_repo}/SuMaiKaDe_jddockerbot"
|
||||
|
||||
echo -e "1、安装bot依赖...\n"
|
||||
apk --no-cache add -f zlib-dev gcc jpeg-dev python3-dev musl-dev freetype-dev
|
||||
echo
|
||||
|
||||
echo -e "2、下载bot所需文件...\n"
|
||||
git clone -b master https://ghproxy.com/https://github.com/SuMaiKaDe/jddockerbot.git $repo_path
|
||||
cp -rf "$repo_path/jbot" $dir_root
|
||||
cp -f "$repo_path/config/bot.json" "$dir_root/config"
|
||||
echo
|
||||
|
||||
echo -e "3、安装python3依赖...\n"
|
||||
pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
cp -f "$repo_path/jbot/requirements.txt" "$dir_root"
|
||||
pip3 --default-timeout=100 install -r requirements.txt --no-cache-dir
|
||||
echo
|
||||
|
||||
echo -e "4、启动bot程序...\n"
|
||||
cd $dir_root
|
||||
ps -ef | grep "python3 -m jbot" | grep -v grep | awk '{print $1}' | xargs kill -9 2>/dev/null
|
||||
nohup python3 -m jbot &
|
||||
echo
|
||||
|
||||
exit 0
|
151
shell/code.sh
Executable file
151
shell/code.sh
Executable file
|
@ -0,0 +1,151 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
## 导入通用变量与函数
|
||||
dir_shell=/ql/shell
|
||||
. $dir_shell/share.sh
|
||||
|
||||
## 生成pt_pin清单
|
||||
gen_pt_pin_array() {
|
||||
local tmp1 tmp2 i pt_pin_temp
|
||||
for ((user_num = 1; user_num <= $user_sum; user_num++)); do
|
||||
tmp1=Cookie$user_num
|
||||
tmp2=${!tmp1}
|
||||
i=$(($user_num - 1))
|
||||
pt_pin_temp=$(echo $tmp2 | perl -pe "{s|.*pt_pin=([^; ]+)(?=;?).*|\1|; s|%|\\\x|g}")
|
||||
[[ $pt_pin_temp == *\\x* ]] && pt_pin[i]=$(printf $pt_pin_temp) || pt_pin[i]=$pt_pin_temp
|
||||
done
|
||||
}
|
||||
|
||||
## 导出互助码的通用程序,$1:去掉后缀的脚本名称,$2:config.sh中的后缀,$3:活动中文名称
|
||||
export_codes_sub() {
|
||||
local task_name=$1
|
||||
local config_name=$2
|
||||
local chinese_name=$3
|
||||
local config_name_my=My$config_name
|
||||
local config_name_for_other=ForOther$config_name
|
||||
local i j k m n pt_pin_in_log code tmp_grep tmp_my_code tmp_for_other user_num random_num_list
|
||||
if cd $dir_log/$task_name &>/dev/null && [[ $(ls) ]]; then
|
||||
## 寻找所有互助码以及对应的pt_pin
|
||||
i=0
|
||||
pt_pin_in_log=()
|
||||
code=()
|
||||
pt_pin_and_code=$(ls -r *.log | xargs awk -v var="的$chinese_name好友互助码" 'BEGIN{FS="[( )】]+"; OFS="&"} $3~var {print $2,$4}')
|
||||
for line in $pt_pin_and_code; do
|
||||
pt_pin_in_log[i]=$(echo $line | awk -F "&" '{print $1}')
|
||||
code[i]=$(echo $line | awk -F "&" '{print $2}')
|
||||
let i++
|
||||
done
|
||||
|
||||
## 输出My系列变量
|
||||
if [[ ${#code[*]} -gt 0 ]]; then
|
||||
for ((m = 0; m < ${#pt_pin[*]}; m++)); do
|
||||
tmp_my_code=""
|
||||
j=$((m + 1))
|
||||
for ((n = 0; n < ${#code[*]}; n++)); do
|
||||
if [[ ${pt_pin[m]} == ${pt_pin_in_log[n]} ]]; then
|
||||
tmp_my_code=${code[n]}
|
||||
break
|
||||
fi
|
||||
done
|
||||
echo "$config_name_my$j='$tmp_my_code'"
|
||||
done
|
||||
else
|
||||
echo "## 从日志中未找到任何互助码"
|
||||
fi
|
||||
|
||||
## 输出ForOther系列变量
|
||||
if [[ ${#code[*]} -gt 0 ]]; then
|
||||
echo
|
||||
case $HelpType in
|
||||
0) ## 全部一致
|
||||
tmp_for_other=""
|
||||
for ((m = 0; m < ${#pt_pin[*]}; m++)); do
|
||||
j=$((m + 1))
|
||||
tmp_for_other="$tmp_for_other@\${$config_name_my$j}"
|
||||
done
|
||||
echo "${config_name_for_other}1=\"$tmp_for_other\"" | perl -pe "s|($config_name_for_other\d+=\")@|\1|"
|
||||
for ((m = 1; m < ${#pt_pin[*]}; m++)); do
|
||||
j=$((m + 1))
|
||||
echo "$config_name_for_other$j=\"\${${config_name_for_other}1}\""
|
||||
done
|
||||
;;
|
||||
|
||||
1) ## 均等助力
|
||||
for ((m = 0; m < ${#pt_pin[*]}; m++)); do
|
||||
tmp_for_other=""
|
||||
j=$((m + 1))
|
||||
for ((n = $m; n < $(($user_sum + $m)); n++)); do
|
||||
[[ $m -eq $n ]] && continue
|
||||
if [[ $((n + 1)) -le $user_sum ]]; then
|
||||
k=$((n + 1))
|
||||
else
|
||||
k=$((n + 1 - $user_sum))
|
||||
fi
|
||||
tmp_for_other="$tmp_for_other@\${$config_name_my$k}"
|
||||
done
|
||||
echo "$config_name_for_other$j=\"$tmp_for_other\"" | perl -pe "s|($config_name_for_other\d+=\")@|\1|"
|
||||
done
|
||||
;;
|
||||
|
||||
2) ## 本套脚本内账号间随机顺序助力
|
||||
for ((m = 0; m < ${#pt_pin[*]}; m++)); do
|
||||
tmp_for_other=""
|
||||
random_num_list=$(seq $user_sum | sort -R)
|
||||
j=$((m + 1))
|
||||
for n in $random_num_list; do
|
||||
[[ $j -eq $n ]] && continue
|
||||
tmp_for_other="$tmp_for_other@\${$config_name_my$n}"
|
||||
done
|
||||
echo "$config_name_for_other$j=\"$tmp_for_other\"" | perl -pe "s|($config_name_for_other\d+=\")@|\1|"
|
||||
done
|
||||
;;
|
||||
|
||||
*) ## 按编号优先
|
||||
for ((m = 0; m < ${#pt_pin[*]}; m++)); do
|
||||
tmp_for_other=""
|
||||
j=$((m + 1))
|
||||
for ((n = 0; n < ${#pt_pin[*]}; n++)); do
|
||||
[[ $m -eq $n ]] && continue
|
||||
k=$((n + 1))
|
||||
tmp_for_other="$tmp_for_other@\${$config_name_my$k}"
|
||||
done
|
||||
echo "$config_name_for_other$j=\"$tmp_for_other\"" | perl -pe "s|($config_name_for_other\d+=\")@|\1|"
|
||||
done
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
else
|
||||
echo "## 未运行过 $task_name.js 脚本,未产生日志"
|
||||
fi
|
||||
}
|
||||
|
||||
## 汇总输出
|
||||
export_all_codes() {
|
||||
gen_pt_pin_array
|
||||
echo -e "\n# 从日志提取互助码,编号和配置文件中Cookie编号完全对应,如果为空就是所有日志中都没有。\n\n# 即使某个MyXxx变量未赋值,也可以将其变量名填在ForOtherXxx中,jtask脚本会自动过滤空值。\n"
|
||||
echo -n "# 你选择的互助码模板为:"
|
||||
case $HelpType in
|
||||
0)
|
||||
echo "所有账号助力码全部一致。"
|
||||
;;
|
||||
1)
|
||||
echo "所有账号机会均等助力。"
|
||||
;;
|
||||
2)
|
||||
echo "本套脚本内账号间随机顺序助力。"
|
||||
;;
|
||||
*)
|
||||
echo "按账号编号优先。"
|
||||
;;
|
||||
esac
|
||||
for ((i = 0; i < ${#name_js[*]}; i++)); do
|
||||
echo -e "\n## ${name_chinese[i]}:"
|
||||
export_codes_sub "${name_js[i]}" "${name_config[i]}" "${name_chinese[i]}"
|
||||
done
|
||||
}
|
||||
|
||||
## 执行并写入日志
|
||||
log_time=$(date "+%Y-%m-%d-%H-%M-%S")
|
||||
log_path="$dir_code/$log_time.log"
|
||||
make_dir "$dir_code"
|
||||
export_all_codes | perl -pe "{s|京东种豆|种豆|; s|crazyJoy任务|疯狂的JOY|}" | tee $log_path
|
|
@ -1,141 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
## 路径、环境判断
|
||||
ShellDir=${QL_DIR:-$(cd $(dirname $0); pwd)}
|
||||
LogDir=${ShellDir}/log
|
||||
ConfigDir=${ShellDir}/config
|
||||
FileConf=${ConfigDir}/config.sh
|
||||
CookieConf=${ConfigDir}/cookie.sh
|
||||
[[ ${ANDROID_RUNTIME_ROOT}${ANDROID_ROOT} ]] && Opt="P" || Opt="E"
|
||||
Tips="从日志中未找到任何互助码"
|
||||
|
||||
## 所有有互助码的活动,只需要把脚本名称去掉前缀 jd_ 后列在 Name1 中,将其中文名称列在 Name2 中,对应 config.sh 中互助码后缀列在 Name3 中即可。
|
||||
## Name1、Name2 和 Name3 中的三个名称必须一一对应。
|
||||
Name1=(fruit pet plantBean dreamFactory jdfactory crazy_joy jdzz jxnc bookshop cash sgmh cfd global)
|
||||
Name2=(东东农场 东东萌宠 京东种豆得豆 京喜工厂 东东工厂 crazyJoy任务 京东赚赚 京喜农场 口袋书店 签到领现金 闪购盲盒 京喜财富岛 环球挑战赛)
|
||||
Name3=(Fruit Pet Bean DreamFactory JdFactory Joy Jdzz Jxnc BookShop Cash Sgmh Cfd Global)
|
||||
|
||||
|
||||
## 导入 config.sh
|
||||
function Import_Conf {
|
||||
if [ -f ${FileConf} ]
|
||||
then
|
||||
. ${CookieConf}
|
||||
. ${FileConf}
|
||||
if [ ! -s ${CookieConf} ]; then
|
||||
echo -e "请先在Cookie管理中添加一条Cookie...\n"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo -e "配置文件 ${FileConf} 不存在,请先按教程配置好该文件...\n"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
## 用户数量 UserSum
|
||||
function Count_UserSum {
|
||||
UserSum=$(awk '{print NR}' ${CookieConf} | tail -n1)
|
||||
}
|
||||
|
||||
|
||||
## 导出互助码的通用程序
|
||||
function Cat_Scodes {
|
||||
if [ -d ${LogDir}/jd_$1 ] && [[ $(ls ${LogDir}/jd_$1) != "" ]]; then
|
||||
cd ${LogDir}/jd_$1
|
||||
|
||||
## 导出助力码变量(My)
|
||||
for log in $(ls -r); do
|
||||
case $# in
|
||||
2)
|
||||
codes=$(cat ${log} | grep -${Opt} "开始【京东账号|您的(好友)?助力码为" | uniq | perl -0777 -pe "{s|\*||g; s|开始||g; s|\n您的(好友)?助力码为(:)?:?|:|g; s|,.+||g}" | sed -r "s/【京东账号/My$2/;s/】.*?:/='/;s/】.*?/='/;s/$/'/;s/\(每次运行都变化,不影响\)//")
|
||||
;;
|
||||
3)
|
||||
codes=$(grep -${Opt} $3 ${log} | uniq | sed -r "s/【京东账号/My$2/;s/(.*?】/='/;s/$/'/")
|
||||
;;
|
||||
esac
|
||||
if [[ ${codes} ]]; then
|
||||
## 添加判断,若未找到该用户互助码,则设置为空值
|
||||
for ((user_num=1;user_num<=${UserSum};user_num++)); do
|
||||
echo -e "${codes}" | grep -${Opt}q "My$2${user_num}="
|
||||
if [ $? -eq 1 ]; then
|
||||
if [ $user_num == 1 ]; then
|
||||
codes=$(echo "${codes}" | sed -r "1i My${2}1=''")
|
||||
else
|
||||
codes=$(echo "${codes}" | sed -r "/My$2$(expr ${user_num} - 1)=/a\My$2${user_num}=''")
|
||||
fi
|
||||
fi
|
||||
done
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
## 导出为他人助力变量(ForOther)
|
||||
if [[ ${codes} ]]; then
|
||||
help_code=""
|
||||
for ((user_num=1;user_num<=${UserSum};user_num++)); do
|
||||
echo -e "${codes}" | grep -${Opt}q "My$2${user_num}=''"
|
||||
if [ $? -eq 1 ]; then
|
||||
help_code=${help_code}"\${My"$2${user_num}"}@"
|
||||
fi
|
||||
done
|
||||
## 生成互助规则模板
|
||||
for_other_codes=""
|
||||
case $HelpType in
|
||||
0) ### 统一优先级助力模板
|
||||
new_code=$(echo ${help_code} | sed "s/@$//")
|
||||
for ((user_num=1;user_num<=${UserSum};user_num++)); do
|
||||
if [ $user_num == 1 ]; then
|
||||
for_other_codes=${for_other_codes}"ForOther"$2${user_num}"=\""${new_code}"\"\n"
|
||||
else
|
||||
for_other_codes=${for_other_codes}"ForOther"$2${user_num}"=\"\${ForOther"${2}1"}\"\n"
|
||||
fi
|
||||
done
|
||||
;;
|
||||
1) ### 均匀助力模板
|
||||
for ((user_num=1;user_num<=${UserSum};user_num++)); do
|
||||
echo ${help_code} | grep "\${My"$2${user_num}"}@" > /dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
left_str=$(echo ${help_code} | sed "s/\${My$2${user_num}}@/ /g" | awk '{print $1}')
|
||||
right_str=$(echo ${help_code} | sed "s/\${My$2${user_num}}@/ /g" | awk '{print $2}')
|
||||
mark="\${My$2${user_num}}@"
|
||||
else
|
||||
left_str=$(echo ${help_code} | sed "s/${mark}/ /g" | awk '{print $1}')${mark}
|
||||
right_str=$(echo ${help_code} | sed "s/${mark}/ /g" | awk '{print $2}')
|
||||
fi
|
||||
new_code=$(echo ${right_str}${left_str} | sed "s/@$//")
|
||||
for_other_codes=${for_other_codes}"ForOther"$2${user_num}"=\""${new_code}"\"\n"
|
||||
done
|
||||
;;
|
||||
*) ### 普通优先级助力模板
|
||||
for ((user_num=1;user_num<=${UserSum};user_num++)); do
|
||||
new_code=$(echo ${help_code} | sed "s/\${My"$2${user_num}"}@//;s/@$//")
|
||||
for_other_codes=${for_other_codes}"ForOther"$2${user_num}"=\""${new_code}"\"\n"
|
||||
done
|
||||
;;
|
||||
esac
|
||||
echo -e "${codes}\n\n${for_other_codes}" | sed s/[[:space:]]//g
|
||||
else
|
||||
echo ${Tips}
|
||||
fi
|
||||
else
|
||||
echo "未运行过 jd_$1 脚本,未产生日志"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
## 汇总
|
||||
function Cat_All {
|
||||
echo -e "\n从最后一个日志提取互助码,受日志内容影响,仅供参考。"
|
||||
for ((i=0; i<${#Name1[*]}; i++)); do
|
||||
echo -e "\n${Name2[i]}:"
|
||||
[[ $(Cat_Scodes "${Name1[i]}" "${Name3[i]}" "的${Name2[i]}好友互助码") == ${Tips} ]] && Cat_Scodes "${Name1[i]}" "${Name3[i]}" || Cat_Scodes "${Name1[i]}" "${Name3[i]}" "的${Name2[i]}好友互助码"
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
## 执行并写入日志
|
||||
LogTime=$(date "+%Y-%m-%d-%H-%M-%S")
|
||||
LogFile="${LogDir}/export_sharecodes/${LogTime}.log"
|
||||
[ ! -d "${LogDir}/export_sharecodes" ] && mkdir -p ${LogDir}/export_sharecodes
|
||||
Import_Conf && Count_UserSum && Cat_All | perl -pe "{s|京东种豆|种豆|; s|crazyJoy任务|疯狂的JOY|}" | tee ${LogFile}
|
122
shell/git_diy.sh
122
shell/git_diy.sh
|
@ -1,122 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
#author:spark thanks to: https://github.com/sparkssssssss/scripts
|
||||
|
||||
ShellDir=${QL_DIR:-$(
|
||||
cd $(dirname $0)
|
||||
pwd
|
||||
)}
|
||||
[[ $QL_DIR ]] && ShellJs=js
|
||||
ConfigDir=$ShellDir/config
|
||||
ListCronCurrent=$ConfigDir/crontab.list
|
||||
AuthConf=$ConfigDir/auth.json
|
||||
|
||||
declare -A BlackListDict
|
||||
url=$1
|
||||
path=$2
|
||||
blackword=$3
|
||||
|
||||
if [[ $# -lt 2 ]] || [[ $# -gt 4 ]]; then
|
||||
echo 'Desc: 用户拉取指定用户的指定仓储'
|
||||
echo 'Usage: diy <repourl> <path> <blacklist>'
|
||||
|
||||
echo 'repourl 仓储地址'
|
||||
echo 'path 需要下载脚本的指定目录,多个目录 | 分割 path1 | path2'
|
||||
echo 'blacklist 需要排除的脚本名,多个名称 | 分割 blacklist1 | blacklist2'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
diyscriptsdir=/ql/diyscripts
|
||||
mkdir -p ${diyscriptsdir}
|
||||
|
||||
urlTmp=${url%*/}
|
||||
repoTmp=${urlTmp##*/}
|
||||
repo=${repoTmp%.*}
|
||||
tmp=${url%/*}
|
||||
authorTmp1=${tmp##*/}
|
||||
authorTmp2=${authorTmp1##*:}
|
||||
author=${authorTmp2##*.}
|
||||
|
||||
if [ ! -d "$diyscriptsdir/${author}_${repo}" ]; then
|
||||
echo -e "${author}本地仓库不存在,从远程拉取ing..."
|
||||
cd ${diyscriptsdir} && git clone $url ${author}_${repo}
|
||||
gitpullstatus=$?
|
||||
[ $gitpullstatus -eq 0 ] && echo -e "${author}本地仓库拉取完毕"
|
||||
[ $gitpullstatus -ne 0 ] && echo -e "${author}本地仓库拉取失败,请检查!" && exit 0
|
||||
else
|
||||
cd ${diyscriptsdir}/${author}_${repo}
|
||||
branch=$(git symbolic-ref --short -q HEAD)
|
||||
git fetch --all
|
||||
git reset --hard origin/$branch
|
||||
git pull
|
||||
gitpullstatus=$?
|
||||
fi
|
||||
|
||||
rand() {
|
||||
min=$1
|
||||
max=$(($2 - $min + 1))
|
||||
num=$(cat /proc/sys/kernel/random/uuid | cksum | awk -F ' ' '{print $1}')
|
||||
echo $(($num % $max + $min))
|
||||
}
|
||||
|
||||
addnewcron() {
|
||||
addname=""
|
||||
cd ${diyscriptsdir}/${author}_${repo}
|
||||
express=$(find . -name "*.js")
|
||||
if [ $path ]; then
|
||||
express=$(find . -name "*.js" | egrep $path)
|
||||
fi
|
||||
if [ $blackword ]; then
|
||||
express=$(find . -name "*.js" | egrep -v $blackword | egrep $path)
|
||||
fi
|
||||
for js in $express; do
|
||||
base=$(basename $js)
|
||||
croname=$(echo "${author}_$base" | awk -F\. '{print $1}')
|
||||
script_date=$(cat $js | grep ^[0-9] | awk '{print $1,$2,$3,$4,$5}' | egrep -v "[a-zA-Z]|:|\." | sort | uniq | head -n 1)
|
||||
[ -z "${script_date}" ] && script_date=$(cat $js | grep -Eo "([0-9]+|\*|[0-9]+[,-].*) ([0-9]+|\*|[0-9]+[,-].*) ([0-9]+|\*|[0-9]+[,-].*) ([0-9]+|\*|[0-9]+[,-].*) ([0-9]+|\*|[0-9][,-].*)" | sort | uniq | head -n 1)
|
||||
[ -z "${script_date}" ] && cron_min=$(rand 1 59) && cron_hour=$(rand 7 9) && script_date="${cron_min} ${cron_hour} * * *"
|
||||
local oldCron=$(grep -c -w "$croname" "$ListCronCurrent")
|
||||
if [[ oldCron -eq 0 ]]; then
|
||||
local name=$(cat "$js" | grep -E "new Env\(" | perl -pe "s|(^.+)new Env\(\'*\"*(.+?)'*\"*\).+|\2|")
|
||||
add_cron_api "$script_date" "js $croname" "$name"
|
||||
addname="${addname}\n${croname}"
|
||||
echo -e "添加了新的脚本${croname}."
|
||||
fi
|
||||
if [ ! -f "/ql/scripts/${author}_$base" ]; then
|
||||
\cp $js /ql/scripts/${author}_$base
|
||||
else
|
||||
change=$(diff $js /ql/scripts/${author}_$base)
|
||||
[ -n "${change}" ] && \cp $js /ql/scripts/${author}_$base && echo -e "${author}_$base 脚本更新了."
|
||||
fi
|
||||
done
|
||||
[ "$addname" != "" ] && notify "新增 ${author} 自定义脚本" "${addname}"
|
||||
|
||||
}
|
||||
|
||||
delcron() {
|
||||
delname=""
|
||||
cronfiles=$(grep "$author" /ql/config/crontab.list | grep -v "^#" | perl -pe "s|.*ID=(.*) js (${author}_.*)\.*|\1:\2|")
|
||||
for filename in $cronfiles; do
|
||||
local id=$(echo "$1" | awk -F ":" '{print $1}')
|
||||
local name=$(echo "$1" | awk -F ":" '{print $2}')
|
||||
hasFile=$(cd ${diyscriptsdir}/${author}_${repo} && find . -name "$filename.js" | wc -l)
|
||||
if [[ $hasFile != 0 ]]; then
|
||||
del_cron_api "$id"
|
||||
echo -e "删除失效脚本${name}."
|
||||
delname="${delname}\n${author}_${filename}"
|
||||
fi
|
||||
done
|
||||
[ "$delname" != "" ] && notify "删除 ${author} 失效脚本" "${delname}"
|
||||
}
|
||||
|
||||
. $ShellDir/shell/api.sh
|
||||
get_token
|
||||
|
||||
if [[ ${gitpullstatus} -eq 0 ]]; then
|
||||
addnewcron
|
||||
delcron
|
||||
else
|
||||
echo -e "$author 仓库更新失败了."
|
||||
notify "自定义仓库更新失败" "$author"
|
||||
fi
|
||||
|
||||
exit 0
|
|
@ -1,297 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
ShellDir=${QL_DIR:-$(
|
||||
cd $(dirname $0)
|
||||
pwd
|
||||
)}
|
||||
[[ $QL_DIR ]] && ShellJs=js
|
||||
LogDir=$ShellDir/log
|
||||
DbDir=$ShellDir/db
|
||||
ManualLogDir=$ShellDir/manual_log
|
||||
ScriptsDir=$ShellDir/scripts
|
||||
ConfigDir=$ShellDir/config
|
||||
FileConf=$ConfigDir/config.sh
|
||||
CookieConf=$ConfigDir/cookie.sh
|
||||
AuthConf=$ConfigDir/auth.json
|
||||
ExtraShell=$ConfigDir/extra.sh
|
||||
FileConfSample=$ShellDir/sample/config.sh.sample
|
||||
ListCronSample=$ShellDir/sample/crontab.list.sample
|
||||
ListCronCurrent=$ConfigDir/crontab.list
|
||||
ListCronRemote=$ScriptsDir/docker/crontab_list.sh
|
||||
ListCurrentTask=$LogDir/task.list
|
||||
ListRemoteTask=$LogDir/js.list
|
||||
ListJsAdd=$LogDir/js-add.list
|
||||
ListJsDrop=$LogDir/js-drop.list
|
||||
ContentVersion=$ShellDir/version
|
||||
ContentNewTask=$ShellDir/new_task
|
||||
ContentDropTask=$ShellDir/drop_task
|
||||
SendVersion=$ShellDir/send_version
|
||||
isTermux=$ANDROID_RUNTIME_ROOT$ANDROID_ROOT
|
||||
ShellURL=https://ghproxy.com/https://github.com/whyour/qinglong
|
||||
ScriptsURL=https://ghproxy.com/https://github.com/gossh520/jd_scripts
|
||||
|
||||
Import_Conf() {
|
||||
if [ ! -s $FileConf ]; then
|
||||
echo -e "复制一份 $FileConfSample 示例配置文件\n\n"
|
||||
cp -fv $FileConfSample $FileConf
|
||||
fi
|
||||
if [ ! -s $ListCronCurrent ]; then
|
||||
echo -e "复制一份 $ListCronSample 基础定时任务\n\n"
|
||||
cp -fv $ListCronSample $ListCronCurrent
|
||||
fi
|
||||
[ -f $CookieConf ] && . $CookieConf
|
||||
[ -f $FileConf ] && . $FileConf
|
||||
}
|
||||
|
||||
# 更新shell
|
||||
Git_Pull_Shell() {
|
||||
echo -e "更新shell...\n"
|
||||
cd $ShellDir
|
||||
git remote set-url origin $ShellURL
|
||||
git fetch --all
|
||||
ExitStatusShell=$?
|
||||
git reset --hard origin/master
|
||||
git pull
|
||||
}
|
||||
|
||||
Git_Pull_Shell_Next() {
|
||||
if [[ $ExitStatusShell -eq 0 ]]; then
|
||||
echo -e "更新shell成功...\n"
|
||||
[ ! -d $ShellDir/node_modules ] && Npm_Install panel
|
||||
[ -f $ShellDir/package.json ] && PanelDependNew=$(cat $ShellDir/package.json)
|
||||
[[ "$PanelDependOld" != "$PanelDependNew" ]] && cd $ShellDir && Npm_Install panel
|
||||
cp -f $FileConfSample $ConfigDir/config.sh.sample
|
||||
Notify_Version
|
||||
else
|
||||
echo -e "更新shell失败,请检查原因...\n"
|
||||
fi
|
||||
}
|
||||
|
||||
## npm install
|
||||
Npm_Install() {
|
||||
echo -e "检测到 $1 的依赖包有变化,运行 npm install...\n"
|
||||
Npm_InstallSub
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "\nnpm install 运行不成功,自动删除 $1/node_modules 后再次尝试一遍..."
|
||||
rm -rf node_modules
|
||||
fi
|
||||
echo
|
||||
|
||||
if [ ! -d node_modules ]; then
|
||||
echo -e "运行 npm install...\n"
|
||||
Npm_InstallSub
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "\nnpm install 运行不成功,自动删除 $1/node_modules...\n"
|
||||
echo -e "请进入 $1 目录后手动运行 npm install...\n"
|
||||
echo -e "3...\n"
|
||||
sleep 1
|
||||
echo -e "2...\n"
|
||||
sleep 1
|
||||
echo -e "1...\n"
|
||||
sleep 1
|
||||
rm -rf node_modules
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
## npm install 子程序,判断是否为安卓,判断是否安装有yarn
|
||||
function Npm_InstallSub() {
|
||||
if [ -n "$isTermux" ]; then
|
||||
npm install --production --no-save --no-bin-links || npm install --production --no-bin-links --no-save --registry=https://registry.npm.taobao.org
|
||||
elif ! type yarn >/dev/null 2>&1; then
|
||||
npm install --production --no-save || npm install --production --no-save --registry=https://registry.npm.taobao.org
|
||||
else
|
||||
echo -e "检测到本机安装了 yarn,使用 yarn 替代 npm...\n"
|
||||
yarn install --production --network-timeout 1000000000 || yarn install --production --registry=https://registry.npm.taobao.org --network-timeout 1000000000
|
||||
fi
|
||||
}
|
||||
|
||||
## 检测配置文件版本
|
||||
Notify_Version() {
|
||||
## 识别出两个文件的版本号
|
||||
VerConfSample=$(grep " Version: " $FileConfSample | perl -pe "s|.+v((\d+\.?){3})|\1|")
|
||||
[ -f $FileConf ] && VerConf=$(grep " Version: " $FileConf | perl -pe "s|.+v((\d+\.?){3})|\1|")
|
||||
|
||||
## 删除旧的发送记录文件
|
||||
[ -f "$SendVersion" ] && [[ $(cat $SendVersion) != $VerConfSample ]] && rm -f $SendVersion
|
||||
|
||||
## 识别出更新日期和更新内容
|
||||
UpdateDate=$(grep " Date: " $FileConfSample | awk -F ": " '{print $2}')
|
||||
UpdateContent=$(grep " Update Content: " $FileConfSample | awk -F ": " '{print $2}')
|
||||
|
||||
## 如果是今天,并且版本号不一致,则发送通知
|
||||
if [ -f $FileConf ] && [[ "$VerConf" != "$VerConfSample" ]] && [[ $UpdateDate == $(date "+%Y-%m-%d") ]]; then
|
||||
if [ ! -f $SendVersion ]; then
|
||||
notify "检测到配置文件config.sh.sample有更新" "更新日期: $UpdateDate\n当前版本: $VerConf\n新的版本: $VerConfSample\n更新内容: $UpdateContent\n更新说明: 如需使用新功能请对照config.sh.sample,将相关新参数手动增加到你自己的config.sh中,否则请无视本消息。本消息只在该新版本配置文件更新当天发送一次。"
|
||||
fi
|
||||
else
|
||||
[ -f $ContentVersion ] && rm -f $ContentVersion
|
||||
[ -f $SendVersion ] && rm -f $SendVersion
|
||||
fi
|
||||
}
|
||||
|
||||
## 每天次数随机,更新时间随机,更新秒数随机,至少6次,至多12次,大部分为8-10次,符合正态分布。
|
||||
Random_Pull_Cron() {
|
||||
if [[ $(date "+%-H") -le 2 ]]; then
|
||||
RanMin=$(($RANDOM % 60))
|
||||
RanSleep=$(($RANDOM % 56))
|
||||
RanHourArray[0]=$(($RANDOM % 3))
|
||||
for ((i = 1; i < 14; i++)); do
|
||||
j=$(($i - 1))
|
||||
tmp=$(($RANDOM % 3 + ${RanHourArray[j]} + 2))
|
||||
[[ $tmp -lt 24 ]] && RanHourArray[i]=$tmp || break
|
||||
done
|
||||
|
||||
RanHour=${RanHourArray[0]}
|
||||
for ((i = 1; i < ${#RanHourArray[*]}; i++)); do
|
||||
RanHour="$RanHour,${RanHourArray[i]}"
|
||||
done
|
||||
|
||||
perl -i -pe "s|.+(git_pull? .+git_pull\.log.*)|$RanMin $RanHour \* \* \* sleep $RanSleep && \1|" $ListCronCurrent
|
||||
crontab $ListCronCurrent
|
||||
fi
|
||||
}
|
||||
|
||||
## 克隆scripts
|
||||
Git_Clone_Scripts() {
|
||||
git clone -b master $ScriptsURL $ScriptsDir
|
||||
ExitStatusScripts=$?
|
||||
}
|
||||
|
||||
## 更新scripts
|
||||
Git_Pull_Scripts() {
|
||||
if [ -d $ScriptsDir/.git ]; then
|
||||
echo -e "更新scripts...\n"
|
||||
cd $ScriptsDir
|
||||
git remote set-url origin $ScriptsURL
|
||||
git fetch --all
|
||||
ExitStatusScripts=$?
|
||||
git reset --hard origin/master
|
||||
git pull
|
||||
else
|
||||
Git_Clone_Scripts
|
||||
fi
|
||||
}
|
||||
|
||||
Git_Pull_Scripts_Next() {
|
||||
if [[ $ExitStatusScripts -eq 0 ]]; then
|
||||
echo -e "更新scripts成功...\n"
|
||||
[ ! -d $ScriptsDir/node_modules ] && Npm_Install scripts
|
||||
[ -f $ScriptsDir/package.json ] && ScriptsDependNew=$(cat $ScriptsDir/package.json)
|
||||
[[ "$ScriptsDependOld" != "$ScriptsDependNew" ]] && cd $ScriptsDir && Npm_Install scripts
|
||||
Diff_Cron
|
||||
if [ -s $ListJsDrop ]; then
|
||||
Output_ListJs $ListJsDrop "失效"
|
||||
Del_Cron
|
||||
fi
|
||||
if [ -s $ListJsAdd ]; then
|
||||
Output_ListJs $ListJsAdd "新"
|
||||
Add_Cron
|
||||
fi
|
||||
else
|
||||
echo -e "更新scripts失败,请检查原因...\n"
|
||||
fi
|
||||
}
|
||||
|
||||
Diff_Cron() {
|
||||
cat $ListCronRemote | grep -E "node.+j[drx]_\w+\.js" | perl -pe "s|.+(j[drx]_\w+)\.js.+|\1|" | sort -u >$ListRemoteTask
|
||||
cat $ListCronCurrent | grep -E "$ShellJs j[drx]_\w+" | perl -pe "s|.*ID=(.*) $ShellJs (j[drx]_\w+)\.*|\2|" | sort -u >$ListCurrentTask
|
||||
if [ -s $ListCurrentTask ]; then
|
||||
grep -vwf $ListCurrentTask $ListRemoteTask >$ListJsAdd
|
||||
else
|
||||
cp -f $ListRemoteTask $ListJsAdd
|
||||
fi
|
||||
if [ -s $ListRemoteTask ]; then
|
||||
grep -vwf $ListRemoteTask $ListCurrentTask >$ListJsDrop
|
||||
else
|
||||
cp -f $ListCurrentTask $ListJsDrop
|
||||
fi
|
||||
}
|
||||
|
||||
Del_Cron() {
|
||||
if [ $AutoDelCron == true ] && [ -s $ListJsDrop ]; then
|
||||
echo -e "开始尝试自动删除定时任务如下:\n"
|
||||
cat $ListJsDrop
|
||||
echo
|
||||
JsDrop=$(cat $ListJsDrop)
|
||||
for Cron in $JsDrop; do
|
||||
local id=$(cat $ListCronCurrent | grep -E "js $Cron$" | perl -pe "s|.*ID=(.*) js $Cron$|\1|")
|
||||
del_cron_api "$id"
|
||||
done
|
||||
crontab $ListCronCurrent
|
||||
echo -e "成功删除失效的脚本与定时任务\n"
|
||||
notify "删除 lxk0301 失效脚本" "$JsDrop"
|
||||
fi
|
||||
}
|
||||
|
||||
Add_Cron() {
|
||||
if [ $AutoAddCron == true ] && [ -s $ListJsAdd ]; then
|
||||
echo -e "开始尝试自动添加定时任务\n"
|
||||
JsAdd=$(cat $ListJsAdd)
|
||||
for Cron in $JsAdd; do
|
||||
if [[ $Cron == jd_bean_sign ]]; then
|
||||
local name=$(cat "$ScriptsDir/$Cron.js" | grep -E "new Env\(" | perl -pe "s|(^.+)new Env\(\'*\"*(.+?)'*\"*\).+|\2|")
|
||||
add_cron_api "4 0,9 * * *" "$ShellJs $Cron" "$name"
|
||||
else
|
||||
local name=$(cat "$ScriptsDir/$Cron.js" | grep -E "new Env\(" | perl -pe "s|(^.+)new Env\(\'*\"*(.+?)'*\"*\).+|\2|")
|
||||
local param=$(cat $ListCronRemote | grep -E "\/$Cron\." | perl -pe "s|(^.+) node */scripts/(j[drx]_\w+)\.js.+|\1\:$ShellJs \2|")
|
||||
add_cron_api "$param:$name"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
crontab $ListCronCurrent
|
||||
echo -e "成功添加新的定时任务...\n"
|
||||
notify "新增lxk0301脚本" "$JsAdd"
|
||||
else
|
||||
echo -e "添加新的定时任务出错,请手动添加...\n"
|
||||
notify "尝试自动添加lxk0301以下新的定时任务出错,请手动添加:" "$JsAdd"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
## 输出定时任务变化
|
||||
Output_ListJs() {
|
||||
local list=$1
|
||||
local type=$2
|
||||
if [ -s $list ]; then
|
||||
echo -e "检测到有$type的定时任务:\n"
|
||||
cat $list
|
||||
echo
|
||||
fi
|
||||
}
|
||||
|
||||
#################################################################################################################################
|
||||
echo -e "\n--------------------------------------------------------------\n"
|
||||
echo -n "系统时间:"
|
||||
echo $(date "+%Y-%m-%d %H:%M:%S")
|
||||
if [ "${TZ}" = "UTC" ]; then
|
||||
echo -n "北京时间:"
|
||||
echo $(date -d "8 hour" "+%Y-%m-%d %H:%M:%S")
|
||||
fi
|
||||
echo -e "\nJS脚本目录:$ScriptsDir\n"
|
||||
echo -e "--------------------------------------------------------------\n"
|
||||
|
||||
. $ShellDir/shell/api.sh
|
||||
get_token
|
||||
|
||||
Import_Conf
|
||||
|
||||
# 更新shell
|
||||
[ -f $ShellDir/package.json ] && PanelDependOld=$(cat $ShellDir/package.json)
|
||||
Git_Pull_Shell
|
||||
Git_Pull_Shell_Next
|
||||
|
||||
## 更新scripts
|
||||
[ -f $ScriptsDir/package.json ] && ScriptsDependOld=$(cat $ScriptsDir/package.json)
|
||||
Git_Pull_Scripts
|
||||
Git_Pull_Scripts_Next
|
||||
|
||||
## 调用用户自定义的extra.sh
|
||||
if [[ $EnableExtraShell == true ]]; then
|
||||
if [ -f $ExtraShell ]; then
|
||||
. $ExtraShell
|
||||
else
|
||||
echo -e "$ExtraShell 文件不存在,跳过执行DIY脚本...\n"
|
||||
fi
|
||||
fi
|
283
shell/js.sh
283
shell/js.sh
|
@ -1,283 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
## 路径
|
||||
ShellDir=${QL_DIR:-$(cd $(dirname $0); pwd)}
|
||||
[[ ${QL_DIR} ]] && ShellJS=js
|
||||
ScriptsDir=${ShellDir}/scripts
|
||||
ConfigDir=${ShellDir}/config
|
||||
FileConf=${ConfigDir}/config.sh
|
||||
CookieConf=${ConfigDir}/cookie.sh
|
||||
FileConfSample=${ShellDir}/sample/config.sh.sample
|
||||
LogDir=${ShellDir}/log
|
||||
ListScripts=($(cd ${ScriptsDir}; ls *.js | grep -E "j[drx]_"))
|
||||
ListCron=${ConfigDir}/crontab.list
|
||||
ListCronLxk=${ScriptsDir}/docker/crontab_list.sh
|
||||
ListJs=${LogDir}/js.list
|
||||
|
||||
## 导入config.sh
|
||||
function Import_Conf {
|
||||
if [ -f ${FileConf} ]
|
||||
then
|
||||
. ${CookieConf}
|
||||
. ${FileConf}
|
||||
if [[ ! -s ${CookieConf} ]]; then
|
||||
echo -e "请先在Cookie管理中添加一条Cookie...\n"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo -e "配置文件 ${FileConf} 不存在,请先按教程配置好该文件...\n"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
## 更新crontab
|
||||
function Detect_Cron {
|
||||
if [[ $(cat ${ListCron}) != $(crontab -l) ]]; then
|
||||
crontab ${ListCron}
|
||||
fi
|
||||
}
|
||||
|
||||
## 用户数量UserSum
|
||||
function Count_UserSum {
|
||||
UserSum=0
|
||||
for line in `cat $CookieConf`
|
||||
do
|
||||
((UserSum++))
|
||||
eval Cookie${UserSum}="\"${line}\""
|
||||
done
|
||||
}
|
||||
|
||||
## 组合Cookie和互助码子程序
|
||||
function Combin_Sub {
|
||||
CombinAll=""
|
||||
if [[ ${AutoHelpOther} == true ]] && [[ $1 == ForOther* ]]; then
|
||||
|
||||
ForOtherAll=""
|
||||
MyName=$(echo $1 | perl -pe "s|ForOther|My|")
|
||||
|
||||
for ((m=1; m<=${UserSum}; m++)); do
|
||||
TmpA=${MyName}$m
|
||||
TmpB=${!TmpA}
|
||||
ForOtherAll="${ForOtherAll}@${TmpB}"
|
||||
done
|
||||
|
||||
for ((n=1; n<=${UserSum}; n++)); do
|
||||
for num in ${TempBlockCookie}; do
|
||||
[[ $n -eq $num ]] && continue 2
|
||||
done
|
||||
CombinAll="${CombinAll}&${ForOtherAll}"
|
||||
done
|
||||
|
||||
else
|
||||
for ((i=1; i<=${UserSum}; i++)); do
|
||||
for num in ${TempBlockCookie}; do
|
||||
[[ $i -eq $num ]] && continue 2
|
||||
done
|
||||
Tmp1=$1$i
|
||||
Tmp2=${!Tmp1}
|
||||
CombinAll="${CombinAll}&${Tmp2}"
|
||||
done
|
||||
fi
|
||||
|
||||
echo ${CombinAll} | perl -pe "{s|^&||; s|^@+||; s|&@|&|g; s|@+&|&|g; s|@+|@|g; s|@+$||}"
|
||||
}
|
||||
|
||||
## 组合Cookie、Token与互助码
|
||||
function Combin_All {
|
||||
export JD_COOKIE=$(Combin_Sub Cookie)
|
||||
export FRUITSHARECODES=$(Combin_Sub ForOtherFruit)
|
||||
export PETSHARECODES=$(Combin_Sub ForOtherPet)
|
||||
export PLANT_BEAN_SHARECODES=$(Combin_Sub ForOtherBean)
|
||||
export DREAM_FACTORY_SHARE_CODES=$(Combin_Sub ForOtherDreamFactory)
|
||||
export DDFACTORY_SHARECODES=$(Combin_Sub ForOtherJdFactory)
|
||||
export JDZZ_SHARECODES=$(Combin_Sub ForOtherJdzz)
|
||||
export JDJOY_SHARECODES=$(Combin_Sub ForOtherJoy)
|
||||
export JXNC_SHARECODES=$(Combin_Sub ForOtherJxnc)
|
||||
export JXNCTOKENS=$(Combin_Sub TokenJxnc)
|
||||
export BOOKSHOP_SHARECODES=$(Combin_Sub ForOtherBookShop)
|
||||
export JD_CASH_SHARECODES=$(Combin_Sub ForOtherCash)
|
||||
export JDSGMH_SHARECODES=$(Combin_Sub ForOtherSgmh)
|
||||
export JDCFD_SHARECODES=$(Combin_Sub ForOtherCfd)
|
||||
export JDGLOBAL_SHARECODES=$(Combin_Sub ForOtherGlobal)
|
||||
}
|
||||
|
||||
## 转换JD_BEAN_SIGN_STOP_NOTIFY或JD_BEAN_SIGN_NOTIFY_SIMPLE
|
||||
function Trans_JD_BEAN_SIGN_NOTIFY {
|
||||
case ${NotifyBeanSign} in
|
||||
0)
|
||||
export JD_BEAN_SIGN_STOP_NOTIFY="true"
|
||||
;;
|
||||
1)
|
||||
export JD_BEAN_SIGN_NOTIFY_SIMPLE="true"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
## 转换UN_SUBSCRIBES
|
||||
function Trans_UN_SUBSCRIBES {
|
||||
export UN_SUBSCRIBES="${goodPageSize}\n${shopPageSize}\n${jdUnsubscribeStopGoods}\n${jdUnsubscribeStopShop}"
|
||||
}
|
||||
|
||||
## 申明全部变量
|
||||
function Set_Env {
|
||||
Count_UserSum
|
||||
Combin_All
|
||||
Trans_JD_BEAN_SIGN_NOTIFY
|
||||
Trans_UN_SUBSCRIBES
|
||||
}
|
||||
|
||||
## 随机延迟
|
||||
function Random_Delay {
|
||||
if [[ -n ${RandomDelay} ]] && [[ ${RandomDelay} -gt 0 ]]; then
|
||||
CurMin=$(date "+%-M")
|
||||
if [[ ${CurMin} -gt 2 && ${CurMin} -lt 30 ]] || [[ ${CurMin} -gt 31 && ${CurMin} -lt 59 ]]; then
|
||||
CurDelay=$((${RANDOM} % ${RandomDelay} + 1))
|
||||
echo -e "\n命令未添加 \"now\",随机延迟 ${CurDelay} 秒后再执行任务,如需立即终止,请按 CTRL+C...\n"
|
||||
sleep ${CurDelay}
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
## 使用说明
|
||||
function Help {
|
||||
echo -e "本脚本的用法为:"
|
||||
echo -e "1. ${ShellJS} xxx # 如果设置了随机延迟并且当时时间不在0-2、30-31、59分内,将随机延迟一定秒数"
|
||||
echo -e "2. ${ShellJS} xxx now # 无论是否设置了随机延迟,均立即运行"
|
||||
echo -e "3. ${ShellJS} runall # 运行所有非挂机脚本,非常耗时"
|
||||
echo -e "4. ${ShellJS} hangup # 重启挂机程序"
|
||||
echo -e "5. ${ShellJS} resetpwd # 重置控制面板用户名和密码"
|
||||
echo -e "\n针对用法1、用法2中的\"xxx\",可以不输入后缀\".js\",另外,如果前缀是\"jd_\"的话前缀也可以省略。"
|
||||
echo -e "当前有以下脚本可以运行(仅列出以jd_、jr_、jx_开头的脚本):"
|
||||
cd ${ScriptsDir}
|
||||
for ((i=0; i<${#ListScripts[*]}; i++)); do
|
||||
Name=$(grep "new Env" ${ListScripts[i]} | awk -F "'|\"" '{print $2}')
|
||||
echo -e "$(($i + 1)).${Name}:${ListScripts[i]}"
|
||||
done
|
||||
}
|
||||
|
||||
## nohup
|
||||
function Run_Nohup {
|
||||
if [[ $(ps -ef | grep "${js}" | grep -v "grep") != "" ]]; then
|
||||
ps -ef | grep "${js}" | grep -v "grep" | awk '{print $2}' | xargs kill -9
|
||||
fi
|
||||
[ ! -d ${LogDir}/${js} ] && mkdir -p ${LogDir}/${js}
|
||||
LogTime=$(date "+%Y-%m-%d-%H-%M-%S")
|
||||
LogFile="${LogDir}/${js}/${LogTime}.log"
|
||||
nohup node ${js}.js > ${LogFile} &
|
||||
}
|
||||
|
||||
## 运行挂机脚本
|
||||
function Run_HangUp {
|
||||
HangUpJs="jd_crazy_joy_coin"
|
||||
cd ${ScriptsDir}
|
||||
for js in ${HangUpJs}; do
|
||||
Import_Conf ${js} && Set_Env
|
||||
if type pm2 >/dev/null 2>&1; then
|
||||
pm2 stop ${js}.js 2>/dev/null
|
||||
pm2 flush
|
||||
pm2 start -a ${js}.js --watch "${ScriptsDir}/${js}.js" --name="${js}"
|
||||
else
|
||||
Run_Nohup >/dev/null 2>&1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
## 重置密码
|
||||
function Reset_Pwd {
|
||||
cp -f ${ShellDir}/sample/auth.json ${ConfigDir}/auth.json
|
||||
echo -e "控制面板重置成功,用户名:admin,密码:adminadmin\n"
|
||||
}
|
||||
|
||||
## 一次性运行所有脚本
|
||||
function Run_All {
|
||||
if [ ! -f ${ListJs} ]; then
|
||||
cat ${ListCronLxk} | grep -E "j[drx]_\w+\.js" | perl -pe "s|.+(j[drx]_\w+)\.js.+|\1|" | sort -u > ${ListJs}
|
||||
fi
|
||||
echo -e "\n==================== 开始运行所有非挂机脚本 ====================\n"
|
||||
echo -e "请注意:本过程将非常非常耗时,一个账号可能长达几小时,账号越多耗时越长,如果是手动运行,退出终端也将终止运行。\n"
|
||||
echo -e "倒计时5秒...\n"
|
||||
for ((sec=5; sec>0; sec--)); do
|
||||
echo -e "$sec...\n"
|
||||
sleep 1
|
||||
done
|
||||
for file in $(cat ${ListJs}); do
|
||||
echo -e "==================== 运行 $file.js 脚本 ====================\n"
|
||||
${ShellJS} $file now
|
||||
done
|
||||
}
|
||||
|
||||
## 正常运行单个脚本
|
||||
function Run_Normal {
|
||||
Import_Conf $1 && Detect_Cron && Set_Env
|
||||
|
||||
FileNameTmp1=$(echo $1 | perl -pe "s|\.js||")
|
||||
FileNameTmp2=$(echo $1 | perl -pe "{s|jd_||; s|\.js||; s|^|jd_|}")
|
||||
SeekDir="${ScriptsDir} ${ScriptsDir}/backUp ${ConfigDir}"
|
||||
FileName=""
|
||||
WhichDir=""
|
||||
|
||||
for dir in ${SeekDir}
|
||||
do
|
||||
if [ -f ${dir}/${FileNameTmp1}.js ]; then
|
||||
FileName=${FileNameTmp1}
|
||||
WhichDir=${dir}
|
||||
break
|
||||
elif [ -f ${dir}/${FileNameTmp2}.js ]; then
|
||||
FileName=${FileNameTmp2}
|
||||
WhichDir=${dir}
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "${FileName}" ] && [ -n "${WhichDir}" ]
|
||||
then
|
||||
[ $# -eq 1 ] && Random_Delay
|
||||
LogTime=$(date "+%Y-%m-%d-%H-%M-%S")
|
||||
LogFile="${LogDir}/${FileName}/${LogTime}.log"
|
||||
[ ! -d ${LogDir}/${FileName} ] && mkdir -p ${LogDir}/${FileName}
|
||||
cd ${WhichDir}
|
||||
node ${FileName}.js 2>&1 | tee ${LogFile}
|
||||
else
|
||||
echo -e "\n在${ScriptsDir}、${ScriptsDir}/backUp、${ConfigDir}三个目录下均未检测到 $1 脚本的存在,请确认...\n"
|
||||
Help
|
||||
fi
|
||||
}
|
||||
|
||||
## 命令检测
|
||||
case $# in
|
||||
0)
|
||||
echo
|
||||
Help
|
||||
;;
|
||||
1)
|
||||
case $1 in
|
||||
hangup)
|
||||
Run_HangUp
|
||||
;;
|
||||
resetpwd)
|
||||
Reset_Pwd
|
||||
;;
|
||||
runall)
|
||||
Run_All
|
||||
;;
|
||||
*)
|
||||
Run_Normal $1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
2)
|
||||
case $2 in
|
||||
now)
|
||||
Run_Normal $1 $2
|
||||
;;
|
||||
*)
|
||||
echo -e "\n命令输入错误...\n"
|
||||
Help
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo -e "\n命令过多...\n"
|
||||
Help
|
||||
;;
|
||||
esac
|
|
@ -1,4 +1,4 @@
|
|||
const notify = require('/ql/scripts/sendNotify');
|
||||
const notify = require('/ql/scripts/sendNotify.js');
|
||||
const title = process.argv[2];
|
||||
const content = process.argv[3];
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#!/bin/bash
|
||||
#author:spark thanks to: https://github.com/sparkssssssss/scripts
|
||||
|
||||
. /ql/config/cookie.sh
|
||||
. /ql/config/config.sh
|
||||
title=$(echo $1|sed 's/-/_/g')
|
||||
msg=$(echo -e $2)
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
ShellDir=${QL_DIR:-$(cd $(dirname $0); pwd)}
|
||||
|
||||
echo -e "更新shell...\n"
|
||||
cd ${ShellDir}
|
||||
git fetch --all
|
||||
git pull
|
||||
echo -e "更新shell完成...\n"
|
||||
|
||||
echo -e "重新build...\n"
|
||||
yarn install --network-timeout 1000000000 || yarn install --registry=https://registry.npm.taobao.org --network-timeout 1000000000
|
||||
yarn build
|
||||
yarn build-back
|
||||
yarn cache clean
|
||||
echo -e "重新build完成...\n"
|
||||
|
||||
echo -e "重启服务...\n"
|
||||
|
||||
PIDS=`ps -ef|grep "app.js"|grep -v grep`
|
||||
if [ "$PIDS" != "" ]; then
|
||||
pm2 restart panel
|
||||
else
|
||||
pm2 start ${QL_DIR}/build/app.js -n panel
|
||||
fi
|
||||
|
||||
nginx -s reload
|
||||
|
||||
echo -e "重启服务完成...\n"
|
|
@ -1,58 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
## 判断环境
|
||||
ShellDir=${QL_DIR:-$(cd $(dirname $0); pwd)}
|
||||
LogDir=${ShellDir}/log
|
||||
|
||||
## 导入配置文件
|
||||
. ${ShellDir}/config/cookie.sh
|
||||
. ${ShellDir}/config/config.sh
|
||||
|
||||
## 删除运行js脚本的旧日志
|
||||
function Rm_JsLog {
|
||||
LogFileList=$(ls -l ${LogDir}/*/*.log | awk '{print $9}')
|
||||
for log in ${LogFileList}
|
||||
do
|
||||
LogDate=$(echo ${log} | awk -F "/" '{print $NF}' | cut -c1-10) #文件名比文件属性获得的日期要可靠
|
||||
if [[ $(uname -s) == Darwin ]]
|
||||
then
|
||||
DiffTime=$(($(date +%s) - $(date -j -f "%Y-%m-%d" "${LogDate}" +%s)))
|
||||
else
|
||||
DiffTime=$(($(date +%s) - $(date +%s -d "${LogDate}")))
|
||||
fi
|
||||
[ ${DiffTime} -gt $((${RmLogDaysAgo} * 86400)) ] && rm -vf ${log}
|
||||
done
|
||||
}
|
||||
|
||||
## 删除git_pull.sh的运行日志
|
||||
function Rm_GitPullLog {
|
||||
if [[ $(uname -s) == Darwin ]]
|
||||
then
|
||||
DateDelLog=$(date -v-${RmLogDaysAgo}d "+%Y-%m-%d")
|
||||
else
|
||||
Stmp=$(($(date "+%s") - 86400 * ${RmLogDaysAgo}))
|
||||
DateDelLog=$(date -d "@${Stmp}" "+%Y-%m-%d")
|
||||
fi
|
||||
LineEndGitPull=$[$(cat ${LogDir}/git_pull.log | grep -n "${DateDelLog} " | head -1 | awk -F ":" '{print $1}') - 3]
|
||||
[ ${LineEndGitPull} -gt 0 ] && perl -i -ne "{print unless 1 .. ${LineEndGitPull} }" ${LogDir}/git_pull.log
|
||||
}
|
||||
|
||||
## 删除空文件夹
|
||||
function Rm_EmptyDir {
|
||||
cd ${LogDir}
|
||||
for dir in $(ls)
|
||||
do
|
||||
if [ -d ${dir} ] && [[ $(ls ${dir}) == "" ]]; then
|
||||
rm -rf ${dir}
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
## 运行
|
||||
if [ -n "${RmLogDaysAgo}" ]; then
|
||||
echo -e "查找旧日志文件中...\n"
|
||||
Rm_JsLog
|
||||
Rm_GitPullLog
|
||||
Rm_EmptyDir
|
||||
echo -e "删除旧日志执行完毕\n"
|
||||
fi
|
40
shell/rmlog.sh
Executable file
40
shell/rmlog.sh
Executable file
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
## 导入通用变量与函数
|
||||
dir_shell=/ql/shell
|
||||
. $dir_shell/share.sh
|
||||
|
||||
days=$1
|
||||
|
||||
## 删除运行js脚本的旧日志
|
||||
remove_js_log() {
|
||||
local log_full_path_list=$(ls -l $dir_log/*/*.log | awk '{print $9}')
|
||||
local diff_time
|
||||
for log in $log_full_path_list; do
|
||||
local log_date=$(echo $log | awk -F "/" '{print $NF}' | cut -c1-10) #文件名比文件属性获得的日期要可靠
|
||||
if [[ $is_macos -eq 1 ]]; then
|
||||
diff_time=$(($(date +%s) - $(date -j -f "%Y-%m-%d" "$log_date" +%s)))
|
||||
else
|
||||
diff_time=$(($(date +%s) - $(date +%s -d "$log_date")))
|
||||
fi
|
||||
[[ $diff_time -gt $((${days} * 86400)) ]] && rm -vf $log
|
||||
done
|
||||
}
|
||||
|
||||
## 删除空文件夹
|
||||
remove_empty_dir() {
|
||||
cd $dir_log
|
||||
for dir in $(ls); do
|
||||
if [ -d $dir ] && [[ -z $(ls $dir) ]]; then
|
||||
rm -rf $dir
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
## 运行
|
||||
if [[ ${days} ]]; then
|
||||
echo -e "查找旧日志文件中...\n"
|
||||
remove_js_log
|
||||
remove_empty_dir
|
||||
echo -e "删除旧日志执行完毕\n"
|
||||
fi
|
260
shell/share.sh
Executable file
260
shell/share.sh
Executable file
|
@ -0,0 +1,260 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
## 目录
|
||||
dir_root=/ql
|
||||
dir_shell=$dir_root/shell
|
||||
dir_sample=$dir_root/sample
|
||||
dir_config=$dir_root/config
|
||||
dir_scripts=$dir_root/scripts
|
||||
dir_repo=$dir_root/repo
|
||||
dir_raw=$dir_root/raw
|
||||
dir_log=$dir_root/log
|
||||
dir_db=$dir_root/db
|
||||
dir_manual_log=$dir_root/manual_log
|
||||
dir_list_tmp=$dir_log/.tmp
|
||||
dir_code=$dir_log/code
|
||||
dir_update_log=$dir_log/update
|
||||
|
||||
## 文件
|
||||
file_config_sample=$dir_sample/config.sample.sh
|
||||
file_cookie=$dir_config/cookie.sh
|
||||
file_sharecode=$dir_config/sharecode.sh
|
||||
file_config_user=$dir_config/config.sh
|
||||
file_auth_sample=$dir_sample/auth.sample.json
|
||||
file_auth_user=$dir_config/auth.json
|
||||
file_extra_shell=$dir_config/extra.sh
|
||||
file_notify_js_sample=$dir_sample/notify.js
|
||||
file_notify_py_sample=$dir_sample/notify.py
|
||||
file_notify_py=$dir_scripts/notify.py
|
||||
file_notify_js=$dir_scripts/sendNotify.js
|
||||
|
||||
## 清单文件
|
||||
list_crontab_user=$dir_config/crontab.list
|
||||
list_crontab_sample=$dir_sample/crontab.sample.list
|
||||
list_own_scripts=$dir_list_tmp/own_scripts.list
|
||||
list_own_user=$dir_list_tmp/own_user.list
|
||||
list_own_add=$dir_list_tmp/own_add.list
|
||||
list_own_drop=$dir_list_tmp/own_drop.list
|
||||
|
||||
## 软连接及其原始文件对应关系
|
||||
link_name=(
|
||||
task
|
||||
ql
|
||||
notify
|
||||
)
|
||||
original_name=(
|
||||
task.sh
|
||||
update.sh
|
||||
notify.sh
|
||||
)
|
||||
|
||||
## 导入配置文件
|
||||
import_config() {
|
||||
[ -f $file_config_user ] && . $file_config_user
|
||||
user_sum=0
|
||||
for line in $(cat $file_cookie); do
|
||||
let user_sum+=1
|
||||
eval Cookie${user_sum}="\"$line\""
|
||||
done
|
||||
|
||||
command_timeout_time=${CommandTimeoutTime:-"1h"}
|
||||
}
|
||||
|
||||
## 创建目录,$1:目录的绝对路径
|
||||
make_dir() {
|
||||
local dir=$1
|
||||
if [[ ! -d $dir ]]; then
|
||||
mkdir -p $dir
|
||||
fi
|
||||
}
|
||||
|
||||
## 检测termux
|
||||
detect_termux() {
|
||||
if [[ ${ANDROID_RUNTIME_ROOT}${ANDROID_ROOT} ]] || [[ $PATH == *com.termux* ]]; then
|
||||
is_termux=1
|
||||
else
|
||||
is_termux=0
|
||||
fi
|
||||
}
|
||||
|
||||
## 检测macos
|
||||
detect_macos() {
|
||||
[[ $(uname -s) == Darwin ]] && is_macos=1 || is_macos=0
|
||||
}
|
||||
|
||||
## 生成随机数,$1:用来求余的数字
|
||||
gen_random_num() {
|
||||
local divi=$1
|
||||
echo $((${RANDOM} % $divi))
|
||||
}
|
||||
|
||||
## 创建软连接的子函数,$1:软连接文件路径,$2:要连接的对象
|
||||
link_shell_sub() {
|
||||
local link_path="$1"
|
||||
local original_path="$2"
|
||||
if [ ! -L $link_path ] || [[ $(readlink -f $link_path) != $original_path ]]; then
|
||||
rm -f $link_path 2>/dev/null
|
||||
ln -sf $original_path $link_path
|
||||
fi
|
||||
}
|
||||
|
||||
## 创建软连接
|
||||
link_shell() {
|
||||
if [[ $is_termux -eq 1 ]]; then
|
||||
local path="/data/data/com.termux/files/usr/bin/"
|
||||
elif [[ $PATH == */usr/local/bin* ]] && [ -d /usr/local/bin ]; then
|
||||
local path="/usr/local/bin/"
|
||||
else
|
||||
local path=""
|
||||
echo -e "脚本功能受限,请自行添加命令的软连接...\n"
|
||||
fi
|
||||
if [[ $path ]]; then
|
||||
for ((i = 0; i < ${#link_name[*]}; i++)); do
|
||||
link_shell_sub "$path${link_name[i]}" "$dir_shell/${original_name[i]}"
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
## 定义各命令
|
||||
define_cmd() {
|
||||
local cmd_prefix cmd_suffix
|
||||
if type task >/dev/null 2>&1; then
|
||||
cmd_suffix=""
|
||||
if [ -x "$dir_shell/task.sh" ]; then
|
||||
cmd_prefix=""
|
||||
else
|
||||
cmd_prefix="bash "
|
||||
fi
|
||||
else
|
||||
cmd_suffix=".sh"
|
||||
if [ -x "$dir_shell/task.sh" ]; then
|
||||
cmd_prefix="$dir_shell/"
|
||||
else
|
||||
cmd_prefix="bash $dir_shell/"
|
||||
fi
|
||||
fi
|
||||
for ((i = 0; i < ${#link_name[*]}; i++)); do
|
||||
export cmd_${link_name[i]}="${cmd_prefix}${link_name[i]}${cmd_suffix}"
|
||||
done
|
||||
}
|
||||
|
||||
## 修复配置文件
|
||||
fix_config() {
|
||||
make_dir $dir_config
|
||||
make_dir $dir_log
|
||||
make_dir $dir_db
|
||||
make_dir $dir_manual_log
|
||||
make_dir $dir_scripts
|
||||
make_dir $dir_list_tmp
|
||||
make_dir $dir_repo
|
||||
make_dir $dir_raw
|
||||
make_dir $dir_update_log
|
||||
|
||||
if [ ! -s $file_config_user ]; then
|
||||
echo -e "复制一份 $file_config_sample 为 $file_config_user,随后请按注释编辑你的配置文件:$file_config_user\n"
|
||||
cp -fv $file_config_sample $file_config_user
|
||||
echo
|
||||
fi
|
||||
|
||||
if [ ! -f $file_cookie ]; then
|
||||
echo -e "检测到config配置目录下不存在cookie.sh,创建一个空文件用于初始化...\n"
|
||||
touch $file_cookie
|
||||
echo
|
||||
fi
|
||||
|
||||
if [ ! -s $file_auth_user ]; then
|
||||
echo -e "复制一份 $file_auth_sample 为 $file_auth_user\n"
|
||||
cp -fv $file_auth_sample $file_auth_user
|
||||
echo
|
||||
fi
|
||||
|
||||
if [ ! -s $file_notify_py ]; then
|
||||
echo -e "复制一份 $file_notify_py_sample 为 $file_notify_py\n"
|
||||
cp -fv $file_notify_py_sample $file_notify_py
|
||||
echo
|
||||
fi
|
||||
|
||||
if [ ! -s $file_notify_js ]; then
|
||||
echo -e "复制一份 $file_notify_js_sample 为 $file_notify_js\n"
|
||||
cp -fv $file_notify_js_sample $file_notify_js
|
||||
echo
|
||||
fi
|
||||
|
||||
if [ -s /etc/nginx/conf.d/default.conf ]; then
|
||||
echo -e "检测到默认nginx配置文件,删除...\n"
|
||||
rm -f /etc/nginx/conf.d/default.conf
|
||||
echo
|
||||
fi
|
||||
}
|
||||
|
||||
## npm install 子程序,判断是否为安卓,判断是否安装有yarn
|
||||
npm_install_sub() {
|
||||
if [ $is_termux -eq 1 ]; then
|
||||
npm install --production --no-save --no-bin-links --registry=https://registry.npm.taobao.org || npm install --production --no-bin-links --no-save
|
||||
elif ! type yarn >/dev/null 2>&1; then
|
||||
npm install --production --no-save --registry=https://registry.npm.taobao.org || npm install --production --no-save
|
||||
else
|
||||
echo -e "检测到本机安装了 yarn,使用 yarn 替代 npm...\n"
|
||||
yarn install --production --network-timeout 1000000000 --registry=https://registry.npm.taobao.org || yarn install --production --network-timeout 1000000000
|
||||
fi
|
||||
}
|
||||
|
||||
## npm install,$1:package.json文件所在路径
|
||||
npm_install_1() {
|
||||
local dir_current=$(pwd)
|
||||
local dir_work=$1
|
||||
|
||||
cd $dir_work
|
||||
echo -e "运行 npm install...\n"
|
||||
npm_install_sub
|
||||
[[ $? -ne 0 ]] && echo -e "\nnpm install 运行不成功,请进入 $dir_work 目录后手动运行 npm install...\n"
|
||||
cd $dir_current
|
||||
}
|
||||
|
||||
npm_install_2() {
|
||||
local dir_current=$(pwd)
|
||||
local dir_work=$1
|
||||
|
||||
cd $dir_work
|
||||
echo -e "检测到 $dir_work 的依赖包有变化,运行 npm install...\n"
|
||||
npm_install_sub
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo -e "\n安装 $dir_work 的依赖包运行不成功,再次尝试一遍...\n"
|
||||
npm_install_1 $dir_work
|
||||
fi
|
||||
cd $dir_current
|
||||
}
|
||||
|
||||
## 比对两个文件,$1比$2新时,将$1复制为$2
|
||||
diff_and_copy() {
|
||||
local copy_source=$1
|
||||
local copy_to=$2
|
||||
if [ ! -s $copy_to ] || [[ $(diff $copy_source $copy_to) ]]; then
|
||||
cp -f $copy_source $copy_to
|
||||
fi
|
||||
}
|
||||
|
||||
## 更新依赖
|
||||
update_depend() {
|
||||
local dir_current=$(pwd)
|
||||
|
||||
if [ ! -s $dir_scripts/package.json ] || [[ $(diff $dir_sample/package.json $dir_scripts/package.json) ]]; then
|
||||
cp -f $dir_sample/package.json $dir_scripts/package.json
|
||||
npm_install_2 $dir_scripts
|
||||
fi
|
||||
|
||||
if [ ! -s $dir_scripts/requirements.txt ] || [[ $(diff $dir_sample/requirements.txt $dir_scripts/requirements.txt) ]]; then
|
||||
cp -f $dir_sample/requirements.txt $dir_scripts/requirements.txt
|
||||
cd $dir_scripts
|
||||
pip3 install -r $dir_scripts/requirements.txt
|
||||
fi
|
||||
|
||||
cd $dir_current
|
||||
}
|
||||
|
||||
## 导入配置文件,检测平台,创建软连接,识别命令,修复配置文件
|
||||
detect_termux
|
||||
detect_macos
|
||||
define_cmd
|
||||
fix_config
|
||||
import_config
|
179
shell/task.sh
Executable file
179
shell/task.sh
Executable file
|
@ -0,0 +1,179 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
## 导入通用变量与函数
|
||||
dir_shell=/ql/shell
|
||||
. $dir_shell/share.sh
|
||||
|
||||
## 组合Cookie和互助码子程序,$1:要组合的内容
|
||||
combine_sub() {
|
||||
local what_combine=$1
|
||||
local combined_all=""
|
||||
local tmp1 tmp2
|
||||
for ((i = 1; i <= $user_sum; i++)); do
|
||||
local tmp1=$what_combine$i
|
||||
local tmp2=${!tmp1}
|
||||
combined_all="$combined_all&$tmp2"
|
||||
done
|
||||
echo $combined_all | perl -pe "{s|^&||; s|^@+||; s|&@|&|g; s|@+&|&|g; s|@+|@|g; s|@+$||}"
|
||||
}
|
||||
|
||||
## 正常依次运行时,组合所有账号的Cookie与互助码
|
||||
combine_all() {
|
||||
for ((i = 0; i < ${#env_name[*]}; i++)); do
|
||||
export ${env_name[i]}=$(combine_sub ${var_name[i]})
|
||||
done
|
||||
}
|
||||
|
||||
## 并发运行时,直接申明每个账号的Cookie与互助码,$1:用户Cookie编号
|
||||
combine_one() {
|
||||
local user_num=$1
|
||||
for ((i = 0; i < ${#env_name[*]}; i++)); do
|
||||
local tmp=${var_name[i]}$user_num
|
||||
export ${env_name[i]}=${!tmp}
|
||||
done
|
||||
}
|
||||
|
||||
## 选择python3还是node
|
||||
define_program() {
|
||||
local p1=$1
|
||||
if [[ $p1 == *.js ]]; then
|
||||
which_program="node"
|
||||
elif [[ $p1 == *.py ]]; then
|
||||
which_program="python3"
|
||||
else
|
||||
which_program=""
|
||||
fi
|
||||
}
|
||||
|
||||
random_delay() {
|
||||
local random_delay_max=$RandomDelay
|
||||
if [[ $random_delay_max ]] && [[ $random_delay_max -gt 0 ]]; then
|
||||
local current_min=$(date "+%-M")
|
||||
if [[ $current_min -gt 2 && $current_min -lt 30 ]] || [[ $current_min -gt 31 && $current_min -lt 59 ]]; then
|
||||
delay_second=$(($(gen_random_num $random_delay_max) + 1))
|
||||
echo -e "\n命令未添加 \"now\",随机延迟 $delay_second 秒后再执行任务,如需立即终止,请按 CTRL+C...\n"
|
||||
sleep $delay_second
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
## scripts目录下所有可运行脚本数组
|
||||
gen_array_scripts() {
|
||||
local dir_current=$(pwd)
|
||||
local i="-1"
|
||||
cd $dir_scripts
|
||||
for file in $(ls); do
|
||||
if [ -f $file ] && [[ $file == *.js && $file != sendNotify.js ]]; then
|
||||
let i++
|
||||
array_scripts[i]=$(echo "$file" | perl -pe "s|$dir_scripts/||g")
|
||||
array_scripts_name[i]=$(grep "new Env" $file | awk -F "'|\"" '{print $2}' | head -1)
|
||||
[[ -z ${array_scripts_name[i]} ]] && array_scripts_name[i]="<未识别出活动名称>"
|
||||
fi
|
||||
done
|
||||
cd $dir_current
|
||||
}
|
||||
|
||||
## 使用说明
|
||||
usage() {
|
||||
define_cmd
|
||||
gen_array_scripts
|
||||
echo -e "task命令运行本程序自动添加进crontab的脚本,需要输入脚本的绝对路径或去掉 “$dir_scripts/” 目录后的相对路径(定时任务中请写作相对路径),用法为:"
|
||||
echo -e "1.$cmd_task <file_name> # 依次执行,如果设置了随机延迟并且当时时间不在0-2、30-31、59分内,将随机延迟一定秒数"
|
||||
echo -e "2.$cmd_task <file_name> now # 依次执行,无论是否设置了随机延迟,均立即运行,前台会输出日志,同时记录在日志文件中"
|
||||
echo -e "3.$cmd_task <file_name> conc # 并发执行,无论是否设置了随机延迟,均立即运行,前台不产生日志,直接记录在日志文件中"
|
||||
if [[ ${#array_scripts[*]} -gt 0 ]]; then
|
||||
echo -e "\n当前有以下脚本可以运行:"
|
||||
for ((i = 0; i < ${#array_scripts[*]}; i++)); do
|
||||
echo -e "$(($i + 1)). ${array_scripts_name[i]}:${array_scripts[i]}"
|
||||
done
|
||||
else
|
||||
echo -e "\n暂无脚本可以执行"
|
||||
fi
|
||||
}
|
||||
|
||||
## run nohup,$1:文件名,不含路径,带后缀
|
||||
run_nohup() {
|
||||
local file_name=$1
|
||||
nohup node $file_name &>$log_path &
|
||||
}
|
||||
|
||||
## 正常运行单个脚本,$1:传入参数
|
||||
run_normal() {
|
||||
local p1=$1
|
||||
cd $dir_scripts
|
||||
define_program "$p1"
|
||||
if [[ $p1 == *.js ]]; then
|
||||
if [[ $AutoHelpOther == true ]] && [[ $(ls $dir_code) ]]; then
|
||||
local latest_log=$(ls -r $dir_code | head -1)
|
||||
. $dir_code/$latest_log
|
||||
fi
|
||||
if [[ $# -eq 1 ]]; then
|
||||
random_delay
|
||||
fi
|
||||
fi
|
||||
combine_all
|
||||
log_time=$(date "+%Y-%m-%d-%H-%M-%S")
|
||||
log_dir="$dir_log/${p1%%.*}"
|
||||
log_path="$log_dir/$log_time.log"
|
||||
make_dir "$log_dir"
|
||||
timeout $command_timeout_time $which_program $p1 2>&1 | tee $log_path
|
||||
}
|
||||
|
||||
## 并发执行,因为是并发,所以日志只能直接记录在日志文件中(日志文件以Cookie编号结尾),前台执行并发跑时不会输出日志
|
||||
## 并发执行时,设定的 RandomDelay 不会生效,即所有任务立即执行
|
||||
run_concurrent() {
|
||||
local p1=$1
|
||||
cd $dir_scripts
|
||||
define_program "$p1"
|
||||
log_dir="$dir_log/${p1%%.*}"
|
||||
make_dir $log_dir
|
||||
log_time=$(date "+%Y-%m-%d-%H-%M-%S.%N")
|
||||
echo -e "\n各账号间已经在后台开始并发执行,前台不输入日志,日志直接写入文件中。\n"
|
||||
for ((user_num = 1; user_num <= $user_sum; user_num++)); do
|
||||
combine_one $user_num
|
||||
log_path="$log_dir/${log_time}_${user_num}.log"
|
||||
timeout $command_timeout_time $which_program $p1 &>$log_path &
|
||||
done
|
||||
}
|
||||
|
||||
## 运行其他命令
|
||||
run_else() {
|
||||
local log_time=$(date "+%Y-%m-%d-%H-%M-%S")
|
||||
local log_dir="$dir_log/$1"
|
||||
local log_path="$log_dir/$log_time.log"
|
||||
make_dir "$log_dir"
|
||||
timeout $command_timeout_time "$@" 2>&1 | tee $log_path
|
||||
}
|
||||
|
||||
## 命令检测
|
||||
main() {
|
||||
case $# in
|
||||
0)
|
||||
echo
|
||||
usage
|
||||
;;
|
||||
1)
|
||||
run_normal $1
|
||||
;;
|
||||
2)
|
||||
case $2 in
|
||||
now)
|
||||
run_normal $1 $2
|
||||
;;
|
||||
conc)
|
||||
run_concurrent $1 $2
|
||||
;;
|
||||
*)
|
||||
run_else "$@"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
run_else "$@"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
exit 0
|
400
shell/update.sh
Executable file
400
shell/update.sh
Executable file
|
@ -0,0 +1,400 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# 导入通用变量与函数
|
||||
dir_shell=/ql/shell
|
||||
. $dir_shell/share.sh
|
||||
. $dir_shell/api.sh
|
||||
|
||||
send_mark=$dir_shell/send_mark
|
||||
|
||||
get_token
|
||||
|
||||
## 重置仓库remote url,docker专用,$1:要重置的目录,$2:要重置为的网址
|
||||
reset_romote_url() {
|
||||
local dir_current=$(pwd)
|
||||
local dir_work=$1
|
||||
local url=$2
|
||||
|
||||
if [ -d "$dir_work/.git" ]; then
|
||||
cd $dir_work
|
||||
git remote set-url origin $url >/dev/null
|
||||
git reset --hard >/dev/null
|
||||
cd $dir_current
|
||||
fi
|
||||
}
|
||||
|
||||
## 克隆脚本,$1:仓库地址,$2:仓库保存路径,$3:分支(可省略)
|
||||
git_clone_scripts() {
|
||||
local url=$1
|
||||
local dir=$2
|
||||
local branch=$3
|
||||
[[ $branch ]] && local cmd="-b $branch "
|
||||
echo -e "开始克隆仓库 $url 到 $dir\n"
|
||||
git clone $cmd $url $dir
|
||||
exit_status=$?
|
||||
}
|
||||
|
||||
## 更新脚本,$1:仓库保存路径
|
||||
git_pull_scripts() {
|
||||
local dir_current=$(pwd)
|
||||
local dir_work=$1
|
||||
cd $dir_work
|
||||
echo -e "开始更新仓库:$dir_work\n"
|
||||
git fetch --all
|
||||
exit_status=$?
|
||||
git reset --hard
|
||||
git pull
|
||||
cd $dir_current
|
||||
}
|
||||
|
||||
## 检测cron的差异,$1:脚本清单文件路径,$2:cron任务清单文件路径,$3:增加任务清单文件路径,$4:删除任务清单文件路径
|
||||
diff_cron() {
|
||||
local list_scripts="$1"
|
||||
local list_task="$2"
|
||||
local list_add="$3"
|
||||
local list_drop="$4"
|
||||
if [ -s $list_task ]; then
|
||||
grep -vwf $list_task $list_scripts >$list_add
|
||||
elif [ ! -s $list_task ] && [ -s $list_scripts ]; then
|
||||
cp -f $list_scripts $list_add
|
||||
fi
|
||||
if [ -s $list_scripts ]; then
|
||||
grep -vwf $list_scripts $list_task >$list_drop
|
||||
else
|
||||
cp -f $list_task $list_drop
|
||||
fi
|
||||
}
|
||||
|
||||
## 检测配置文件版本
|
||||
detect_config_version() {
|
||||
## 识别出两个文件的版本号
|
||||
ver_config_sample=$(grep " Version: " $file_config_sample | perl -pe "s|.+v((\d+\.?){3})|\1|")
|
||||
[ -f $file_config_user ] && ver_config_user=$(grep " Version: " $file_config_user | perl -pe "s|.+v((\d+\.?){3})|\1|")
|
||||
|
||||
## 删除旧的发送记录文件
|
||||
[ -f $send_mark ] && [[ $(cat $send_mark) != $ver_config_sample ]] && rm -f $send_mark
|
||||
|
||||
## 识别出更新日期和更新内容
|
||||
update_date=$(grep " Date: " $file_config_sample | awk -F ": " '{print $2}')
|
||||
update_content=$(grep " Update Content: " $file_config_sample | awk -F ": " '{print $2}')
|
||||
|
||||
## 如果是今天,并且版本号不一致,则发送通知
|
||||
if [ -f $file_config_user ] && [[ $ver_config_user != $ver_config_sample ]] && [[ $update_date == $(date "+%Y-%m-%d") ]]; then
|
||||
if [ ! -f $send_mark ]; then
|
||||
local notify_title="配置文件更新通知"
|
||||
local notify_content="更新日期: $update_date\n用户版本: $ver_config_user\n新的版本: $ver_config_sample\n更新内容: $update_content\n更新说明: 如需使用新功能请对照config.sample.sh,将相关新参数手动增加到你自己的config.sh中,否则请无视本消息。本消息只在该新版本配置文件更新当天发送一次。\n"
|
||||
echo -e $notify_content
|
||||
notify "$notify_title" "$notify_content"
|
||||
[[ $? -eq 0 ]] && echo $ver_config_sample >$send_mark
|
||||
fi
|
||||
else
|
||||
[ -f $send_mark ] && rm -f $send_mark
|
||||
fi
|
||||
}
|
||||
|
||||
## 输出是否有新的或失效的定时任务,$1:新的或失效的任务清单文件路径,$2:新/失效
|
||||
output_list_add_drop() {
|
||||
local list=$1
|
||||
local type=$2
|
||||
if [ -s $list ]; then
|
||||
echo -e "检测到有$type的定时任务:\n"
|
||||
cat $list
|
||||
echo
|
||||
fi
|
||||
}
|
||||
|
||||
## 自动删除失效的脚本与定时任务,需要:1.AutoDelCron 设置为 true;2.正常更新js脚本,没有报错;3.存在失效任务
|
||||
## $1:失效任务清单文件路径
|
||||
del_cron() {
|
||||
local list_drop=$1
|
||||
local author=$2
|
||||
local detail=""
|
||||
local ids=""
|
||||
echo -e "开始尝试自动删除失效的定时任务...\n"
|
||||
for cron in $(cat $list_drop); do
|
||||
local id=$(cat $list_crontab_user | grep -E "$cmd_task $cron$" | perl -pe "s|.*ID=(.*) $cmd_task $cron$|\1|" | xargs | sed 's/ /","/g')
|
||||
if [[ $ids ]]; then
|
||||
ids="$ids,\"$id\""
|
||||
else
|
||||
ids="\"$id\""
|
||||
fi
|
||||
cron_file="$dir_scripts/${cron}"
|
||||
if [[ -f $cron_file ]]; then
|
||||
cron_name=$(grep "new Env" $cron_file | awk -F "'|\"" '{print $2}' | head -1)
|
||||
fi
|
||||
[[ -z $cron_name ]] && cron_name="$cron"
|
||||
detail="${detail}\n${cron_name}"
|
||||
rm -f $cron_file
|
||||
done
|
||||
result=$(del_cron_api "$ids")
|
||||
detail="${result}\n\n${detail}"
|
||||
notify "删除失效任务通知" "$detail"
|
||||
}
|
||||
|
||||
## 自动增加定时任务,需要:1.AutoAddCron 设置为 true;2.正常更新js脚本,没有报错;3.存在新任务;4.crontab.list存在并且不为空
|
||||
## $1:新任务清单文件路径
|
||||
add_cron() {
|
||||
local list_add=$1
|
||||
local author=$2
|
||||
echo -e "开始尝试自动添加定时任务...\n"
|
||||
local detail=""
|
||||
cd $dir_scripts
|
||||
for file in $(cat $list_add); do
|
||||
local file_name=${file/${author}\_/}
|
||||
if [ -f $file ]; then
|
||||
cron_line=$(
|
||||
perl -ne "{
|
||||
print if /.*([\d\*]*[\*-\/,\d]*[\d\*] ){4,5}[\d\*]*[\*-\/,\d]*[\d\*]( |,|\").*$file_name/
|
||||
}" $file |
|
||||
perl -pe "{
|
||||
s|[^\d\*]*(([\d\*]*[\*-\/,\d]*[\d\*] ){4,5}[\d\*]*[\*-\/,\d]*[\d\*])( \|,\|\").*/?$file_name.*|\1|g;
|
||||
s| | |g
|
||||
}" | sort -u | head -1
|
||||
)
|
||||
cron_name=$(grep "new Env" $file | awk -F "'|\"" '{print $2}' | head -1)
|
||||
[[ -z $cron_name ]] && cron_name="$file_name"
|
||||
[[ -z $cron_line ]] && cron_line="0 6 * * *"
|
||||
result=$(add_cron_api "$cron_line:$cmd_task $file:$cron_name")
|
||||
echo -e "$result"
|
||||
detail="${detail}\n${result}"
|
||||
fi
|
||||
done
|
||||
notify "新增任务通知" "$detail"
|
||||
}
|
||||
|
||||
## 更新仓库
|
||||
update_repo() {
|
||||
echo -e "--------------------------------------------------------------\n"
|
||||
local url="$1"
|
||||
local path="$2"
|
||||
local blackword="$3"
|
||||
local dependence="$4"
|
||||
local urlTmp="${url%*/}"
|
||||
local repoTmp="${urlTmp##*/}"
|
||||
local repo="${repoTmp%.*}"
|
||||
local tmp="${url%/*}"
|
||||
local authorTmp1="${tmp##*/}"
|
||||
local authorTmp2="${authorTmp1##*:}"
|
||||
local author="${authorTmp2##*.}"
|
||||
|
||||
local repo_path="${dir_repo}/${author}_${repo}"
|
||||
if [ -d ${repo_path}/.git ]; then
|
||||
reset_romote_url ${repo_path} ${url}
|
||||
git_pull_scripts ${repo_path}
|
||||
else
|
||||
git_clone_scripts ${url} ${repo_path}
|
||||
fi
|
||||
if [[ $exit_status -eq 0 ]]; then
|
||||
echo -e "\n更新${repo_path}成功...\n"
|
||||
else
|
||||
echo -e "\n更新${repo_path}失败,请检查原因...\n"
|
||||
fi
|
||||
|
||||
diff_scripts $repo_path $author $path $blackword $dependence
|
||||
}
|
||||
|
||||
## 更新所有 raw 文件
|
||||
update_raw() {
|
||||
echo -e "--------------------------------------------------------------\n"
|
||||
local raw_url="$1"
|
||||
raw_file_name=$(echo ${raw_url} | awk -F "/" '{print $NF}')
|
||||
echo -e "开始下载:${raw_url} \n\n保存路径:$dir_raw/${raw_file_name}\n"
|
||||
wget -q --no-check-certificate -O "$dir_raw/${raw_file_name}.new" ${raw_url}
|
||||
if [[ $? -eq 0 ]]; then
|
||||
mv "$dir_raw/${raw_file_name}.new" "$dir_raw/${raw_file_name}"
|
||||
echo -e "下载 ${raw_file_name} 成功...\n"
|
||||
cd $dir_raw
|
||||
local filename="raw_${raw_file_name}"
|
||||
local cron_id=$(cat $list_crontab_user | grep -E "$cmd_task $filename$" | perl -pe "s|.*ID=(.*) $cmd_task $filename$|\1|")
|
||||
cp -f $raw_file_name $dir_scripts/${filename}
|
||||
cron_line=$(
|
||||
perl -ne "{
|
||||
print if /.*([\d\*]*[\*-\/,\d]*[\d\*] ){4,5}[\d\*]*[\*-\/,\d]*[\d\*]( |,|\").*$raw_file_name/
|
||||
}" $raw_file_name |
|
||||
perl -pe "{
|
||||
s|[^\d\*]*(([\d\*]*[\*-\/,\d]*[\d\*] ){4,5}[\d\*]*[\*-\/,\d]*[\d\*])( \|,\|\").*/?$raw_file_name.*|\1|g;
|
||||
s| | |g
|
||||
}" | sort -u | head -1
|
||||
)
|
||||
cron_name=$(grep "new Env" $raw_file_name | awk -F "'|\"" '{print $2}' | head -1)
|
||||
[[ -z $cron_name ]] && cron_name="$raw_file_name"
|
||||
[[ -z $cron_line ]] && cron_line="0 6 * * *"
|
||||
if [[ -z $cron_id ]]; then
|
||||
result=$(add_cron_api "$cron_line:$cmd_task $filename:$cron_name")
|
||||
echo -e "$result"
|
||||
notify "新增任务通知" "\n$result"
|
||||
# update_cron_api "$cron_line:$cmd_task $filename:$cron_name:$cron_id"
|
||||
fi
|
||||
else
|
||||
echo -e "下载 ${raw_file_name} 失败,保留之前正常下载的版本...\n"
|
||||
[ -f "$dir_raw/${raw_file_name}.new" ] && rm -f "$dir_raw/${raw_file_name}.new"
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
## 调用用户自定义的extra.sh
|
||||
run_extra_shell() {
|
||||
if [[ ${EnableExtraShell} == true ]]; then
|
||||
if [ -f $file_extra_shell ]; then
|
||||
echo -e "--------------------------------------------------------------\n"
|
||||
. $file_extra_shell
|
||||
else
|
||||
echo -e "$file_extra_shell文件不存在,跳过执行...\n"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
## 脚本用法
|
||||
usage() {
|
||||
echo -e "本脚本用法:"
|
||||
echo -e "1. $cmd_update update # 更新青龙,并且运行extra.sh"
|
||||
echo -e "2. $cmd_update restart # 重新启动青龙并编译,不会运行extra.sh"
|
||||
echo -e "3. $cmd_update raw <fileurl> # 更新单个脚本文件"
|
||||
echo -e "4. $cmd_update repo <repourl> <path> <blacklist> <dependence> # 更新单个仓库的脚本"
|
||||
echo -e "5. $cmd_update rmlog <days> # 删除旧日志"
|
||||
echo -e "6. $cmd_update code # 获取互助码"
|
||||
echo -e "6. $cmd_update bot # 启动tg-bot"
|
||||
}
|
||||
|
||||
## 更新qinglong
|
||||
update_qinglong() {
|
||||
echo -e "--------------------------------------------------------------\n"
|
||||
git_pull_scripts $dir_root
|
||||
if [[ $exit_status -eq 0 ]]; then
|
||||
echo -e "\n更新$dir_root成功...\n"
|
||||
cp -f $file_config_sample $dir_config/config.sample.sh
|
||||
detect_config_version
|
||||
update_depend
|
||||
else
|
||||
echo -e "\n更新$dir_root失败,请检查原因...\n"
|
||||
fi
|
||||
}
|
||||
|
||||
## 对比脚本
|
||||
diff_scripts() {
|
||||
gen_list_repo $1 $2 $3 $4 $5
|
||||
diff_cron $list_own_scripts $list_own_user $list_own_add $list_own_drop
|
||||
|
||||
if [ -s $list_own_drop ]; then
|
||||
output_list_add_drop $list_own_drop "失效"
|
||||
if [[ ${AutoDelCron} == true ]]; then
|
||||
del_cron $list_own_drop $2
|
||||
fi
|
||||
fi
|
||||
if [ -s $list_own_add ]; then
|
||||
output_list_add_drop $list_own_add "新"
|
||||
if [[ ${AutoAddCron} == true ]]; then
|
||||
add_cron $list_own_add $2
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
## 生成脚本的路径清单文件
|
||||
gen_list_repo() {
|
||||
local dir_current=$(pwd)
|
||||
local repo_path="$1"
|
||||
local author="$2"
|
||||
local path="$3"
|
||||
local blackword="$4"
|
||||
local dependence="$5"
|
||||
rm -f $dir_list_tmp/own*.list >/dev/null 2>&1
|
||||
|
||||
cd ${repo_path}
|
||||
files=$(find . -name "*.js" | sed 's/^..//')
|
||||
if [[ $path ]]; then
|
||||
files=$(find . -name "*.js" | sed 's/^..//' | egrep $path)
|
||||
fi
|
||||
if [[ $blackword ]]; then
|
||||
files=$(find . -name "*.js" | sed 's/^..//' | egrep -v $blackword | egrep $path)
|
||||
fi
|
||||
if [[ $dependence ]]; then
|
||||
find . -name "*.js" | sed 's/^..//' | egrep $dependence | xargs -i cp {} $dir_scripts
|
||||
fi
|
||||
for file in ${files}; do
|
||||
filename=$(basename $file)
|
||||
cp -f $file $dir_scripts/${author}_${filename}
|
||||
echo ${author}_${filename} >>$list_own_scripts
|
||||
done
|
||||
grep -E "$cmd_task $author" $list_crontab_user | perl -pe "s|.*ID=(.*) $cmd_task ($author_.*)\.*|\2|" | awk -F " " '{print $1}' | sort -u >$list_own_user
|
||||
cd $dir_current
|
||||
}
|
||||
|
||||
## 重新编译qinglong
|
||||
restart_qinglong() {
|
||||
update_qinglong
|
||||
if [[ $exit_status -eq 0 ]]; then
|
||||
echo -e "重新编译青龙...\n"
|
||||
yarn install --network-timeout 1000000000 || yarn install --registry=https://registry.npm.taobao.org --network-timeout 1000000000
|
||||
yarn build
|
||||
yarn build-back
|
||||
yarn cache clean
|
||||
echo -e "重新编译青龙完成...\n"
|
||||
|
||||
echo -e "重启青龙面板...\n"
|
||||
pm2 reload panel 2>/dev/null || pm2 start $dir_root/build/app.js -n panel
|
||||
nginx -s reload 2>/dev/null || nginx -c /etc/nginx/nginx.conf
|
||||
echo -e "重启面板完成...\n"
|
||||
|
||||
echo -e "重启定时任务...\n"
|
||||
pm2 reload schedule 2>/dev/null || pm2 start $dir_root/build/schedule.js -n schedule
|
||||
echo -e "重启定时完成...\n"
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
local p1=$1
|
||||
local p2=$2
|
||||
local p3=$3
|
||||
local p4=$4
|
||||
local p5=$5
|
||||
log_time=$(date "+%Y-%m-%d-%H-%M-%S")
|
||||
log_path="$dir_log/update/${log_time}_$p1.log"
|
||||
case $p1 in
|
||||
update)
|
||||
update_qinglong | tee $log_path
|
||||
run_extra_shell | tee -a $log_path
|
||||
;;
|
||||
restart)
|
||||
restart_qinglong | tee $log_path
|
||||
;;
|
||||
repo)
|
||||
get_user_info
|
||||
local name=$(echo "${p2##*/}" | awk -F "." '{print $1}')
|
||||
log_path="$dir_log/update/${log_time}_$name.log"
|
||||
if [[ -n $p2 ]]; then
|
||||
update_repo "$p2" "$p3" "$p4" "$p5" | tee $log_path
|
||||
else
|
||||
echo -e "命令输入错误...\n"
|
||||
usage
|
||||
fi
|
||||
;;
|
||||
raw)
|
||||
get_user_info
|
||||
local name=$(echo "${p2##*/}" | awk -F "." '{print $1}')
|
||||
log_path="$dir_log/update/${log_time}_$name.log"
|
||||
if [[ -n $p2 ]]; then
|
||||
update_raw "$p2" | tee $log_path
|
||||
else
|
||||
echo -e "命令输入错误...\n"
|
||||
usage
|
||||
fi
|
||||
;;
|
||||
rmlog)
|
||||
. $dir_shell/rmlog.sh "$p2" | tee $log_path
|
||||
;;
|
||||
code)
|
||||
. $dir_shell/code.sh
|
||||
;;
|
||||
bot)
|
||||
. $dir_shell/bot.sh
|
||||
;;
|
||||
*)
|
||||
echo -e "命令输入错误...\n"
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
exit 0
|
|
@ -23,7 +23,7 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
.cookie-wrapper {
|
||||
.session-wrapper {
|
||||
th {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
|
|
@ -105,17 +105,17 @@ const Config = () => {
|
|||
return <span style={{ cursor: 'text' }}>{index + 1} </span>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '用户名',
|
||||
dataIndex: 'pin',
|
||||
key: 'pin',
|
||||
align: 'center' as const,
|
||||
render: (text: string, record: any) => {
|
||||
const match = record.value.match(/pt_pin=([^; ]+)(?=;?)/);
|
||||
const val = (match && match[1]) || '未匹配用户名';
|
||||
return <span style={{ cursor: 'text' }}>{decodeUrl(val)}</span>;
|
||||
},
|
||||
},
|
||||
// {
|
||||
// title: '用户名',
|
||||
// dataIndex: 'pin',
|
||||
// key: 'pin',
|
||||
// align: 'center' as const,
|
||||
// render: (text: string, record: any) => {
|
||||
// const match = record.value.match(/pt_pin=([^; ]+)(?=;?)/);
|
||||
// const val = (match && match[1]) || '未匹配用户名';
|
||||
// return <span style={{ cursor: 'text' }}>{decodeUrl(val)}</span>;
|
||||
// },
|
||||
// },
|
||||
{
|
||||
title: '昵称',
|
||||
dataIndex: 'nickname',
|
||||
|
@ -231,11 +231,11 @@ const Config = () => {
|
|||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (value && loading) {
|
||||
asyncUpdateStatus();
|
||||
}
|
||||
}, [value]);
|
||||
// useEffect(() => {
|
||||
// if (value && loading) {
|
||||
// asyncUpdateStatus();
|
||||
// }
|
||||
// }, [value]);
|
||||
|
||||
const asyncUpdateStatus = async () => {
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
|
@ -362,7 +362,7 @@ const Config = () => {
|
|||
});
|
||||
};
|
||||
|
||||
const handleCancel = (cookies: any[]) => {
|
||||
const handleCancel = (cookies?: any[]) => {
|
||||
setIsModalVisible(false);
|
||||
if (cookies && cookies.length > 0) {
|
||||
handleCookies(cookies);
|
||||
|
@ -370,10 +370,10 @@ const Config = () => {
|
|||
};
|
||||
|
||||
const handleCookies = (cookies: any[]) => {
|
||||
const result = [...value];
|
||||
for (let i = 0; i < cookies.length; i++) {
|
||||
const cookie = cookies[i];
|
||||
const index = value.findIndex((x) => x._id === cookie._id);
|
||||
const result = [...value];
|
||||
if (index === -1) {
|
||||
result.push(cookie);
|
||||
} else {
|
||||
|
@ -381,9 +381,8 @@ const Config = () => {
|
|||
...cookie,
|
||||
});
|
||||
}
|
||||
setValue(result);
|
||||
refreshStatus(cookie, index);
|
||||
}
|
||||
setValue(result);
|
||||
};
|
||||
|
||||
const components = {
|
||||
|
@ -432,9 +431,8 @@ const Config = () => {
|
|||
|
||||
return (
|
||||
<PageContainer
|
||||
className="cookie-wrapper"
|
||||
title="Cookie管理"
|
||||
loading={loading}
|
||||
className="session-wrapper"
|
||||
title="Session管理"
|
||||
extra={[
|
||||
<Button key="2" type="primary" onClick={() => addCookie()}>
|
||||
添加Cookie
|
||||
|
@ -463,9 +461,9 @@ const Config = () => {
|
|||
dataSource={value}
|
||||
rowKey="value"
|
||||
size="middle"
|
||||
bordered
|
||||
scroll={{ x: 768 }}
|
||||
components={components}
|
||||
loading={loading}
|
||||
onRow={(record, index) => {
|
||||
return {
|
||||
index,
|
||||
|
|
|
@ -10,7 +10,7 @@ const CookieModal = ({
|
|||
}: {
|
||||
cookie?: any;
|
||||
visible: boolean;
|
||||
handleCancel: (needUpdate?: boolean) => void;
|
||||
handleCancel: (cks?: any[]) => void;
|
||||
}) => {
|
||||
const [form] = Form.useForm();
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
@ -46,7 +46,7 @@ const CookieModal = ({
|
|||
});
|
||||
}
|
||||
setLoading(false);
|
||||
handleCancel(data);
|
||||
handleCancel(cookie ? [data] : data);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -92,7 +92,7 @@ const CookieModal = ({
|
|||
<Input.TextArea
|
||||
rows={4}
|
||||
autoSize={true}
|
||||
placeholder="请输入cookie,多个cookie换行输入"
|
||||
placeholder="请输入cookie,可直接换行输入多个cookie"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
|
|
@ -23,6 +23,7 @@ import {
|
|||
EditOutlined,
|
||||
StopOutlined,
|
||||
DeleteOutlined,
|
||||
PauseCircleOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import config from '@/utils/config';
|
||||
import { PageContainer } from '@ant-design/pro-layout';
|
||||
|
@ -39,6 +40,20 @@ enum CrontabStatus {
|
|||
'disabled',
|
||||
}
|
||||
|
||||
enum OperationName {
|
||||
'启用',
|
||||
'禁用',
|
||||
'运行',
|
||||
'停止',
|
||||
}
|
||||
|
||||
enum OperationPath {
|
||||
'enable',
|
||||
'disable',
|
||||
'run',
|
||||
'stop',
|
||||
}
|
||||
|
||||
const Crontab = () => {
|
||||
const columns = [
|
||||
{
|
||||
|
@ -108,6 +123,7 @@ const Crontab = () => {
|
|||
align: 'center' as const,
|
||||
render: (text: string, record: any, index: number) => (
|
||||
<Space size="middle">
|
||||
{record.status !== CrontabStatus.running && (
|
||||
<Tooltip title="运行">
|
||||
<a
|
||||
onClick={() => {
|
||||
|
@ -117,6 +133,18 @@ const Crontab = () => {
|
|||
<PlayCircleOutlined />
|
||||
</a>
|
||||
</Tooltip>
|
||||
)}
|
||||
{record.status === CrontabStatus.running && (
|
||||
<Tooltip title="停止">
|
||||
<a
|
||||
onClick={() => {
|
||||
stopCron(record, index);
|
||||
}}
|
||||
>
|
||||
<PauseCircleOutlined />
|
||||
</a>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip title="日志">
|
||||
<a
|
||||
onClick={() => {
|
||||
|
@ -142,6 +170,7 @@ const Crontab = () => {
|
|||
const [searchText, setSearchText] = useState('');
|
||||
const [isLogModalVisible, setIsLogModalVisible] = useState(false);
|
||||
const [logCron, setLogCron] = useState<any>();
|
||||
const [selectedRowIds, setSelectedRowIds] = useState<string[]>([]);
|
||||
|
||||
const getCrons = () => {
|
||||
setLoading(true);
|
||||
|
@ -177,7 +206,7 @@ const Crontab = () => {
|
|||
),
|
||||
onOk() {
|
||||
request
|
||||
.delete(`${config.apiPrefix}crons/${record._id}`)
|
||||
.delete(`${config.apiPrefix}crons`, { data: [record._id] })
|
||||
.then((data: any) => {
|
||||
if (data.code === 200) {
|
||||
notification.success({
|
||||
|
@ -213,7 +242,7 @@ const Crontab = () => {
|
|||
),
|
||||
onOk() {
|
||||
request
|
||||
.get(`${config.apiPrefix}crons/${record._id}/run`)
|
||||
.put(`${config.apiPrefix}crons/run`, { data: [record._id] })
|
||||
.then((data: any) => {
|
||||
if (data.code === 200) {
|
||||
const result = [...value];
|
||||
|
@ -235,6 +264,42 @@ const Crontab = () => {
|
|||
});
|
||||
};
|
||||
|
||||
const stopCron = (record: any, index: number) => {
|
||||
Modal.confirm({
|
||||
title: '确认停止',
|
||||
content: (
|
||||
<>
|
||||
确认停止定时任务{' '}
|
||||
<Text style={{ wordBreak: 'break-all' }} type="warning">
|
||||
{record.name}
|
||||
</Text>{' '}
|
||||
吗
|
||||
</>
|
||||
),
|
||||
onOk() {
|
||||
request
|
||||
.put(`${config.apiPrefix}crons/stop`, { data: [record._id] })
|
||||
.then((data: any) => {
|
||||
if (data.code === 200) {
|
||||
const result = [...value];
|
||||
result.splice(index, 1, {
|
||||
...record,
|
||||
status: CrontabStatus.idle,
|
||||
});
|
||||
setValue(result);
|
||||
} else {
|
||||
notification.error({
|
||||
message: data,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
onCancel() {
|
||||
console.log('Cancel');
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const enabledOrDisabledCron = (record: any, index: number) => {
|
||||
Modal.confirm({
|
||||
title: `确认${
|
||||
|
@ -252,21 +317,16 @@ const Crontab = () => {
|
|||
),
|
||||
onOk() {
|
||||
request
|
||||
.get(
|
||||
`${config.apiPrefix}crons/${record._id}/${
|
||||
.put(
|
||||
`${config.apiPrefix}crons/${
|
||||
record.status === CrontabStatus.disabled ? 'enable' : 'disable'
|
||||
}`,
|
||||
{
|
||||
data: { _id: record._id },
|
||||
data: [record._id],
|
||||
},
|
||||
)
|
||||
.then((data: any) => {
|
||||
if (data.code === 200) {
|
||||
notification.success({
|
||||
message: `${
|
||||
record.status === CrontabStatus.disabled ? '启用' : '禁用'
|
||||
}成功`,
|
||||
});
|
||||
const newStatus =
|
||||
record.status === CrontabStatus.disabled
|
||||
? CrontabStatus.idle
|
||||
|
@ -296,14 +356,12 @@ const Crontab = () => {
|
|||
}> = ({ record, index }) => (
|
||||
<Dropdown
|
||||
arrow
|
||||
trigger={['click', 'hover']}
|
||||
trigger={['click']}
|
||||
overlay={
|
||||
<Menu onClick={({ key }) => action(key, record, index)}>
|
||||
<Menu.Item key="edit" icon={<EditOutlined />}>
|
||||
编辑
|
||||
</Menu.Item>
|
||||
{record.isSystem !== 1 && (
|
||||
<>
|
||||
<Menu.Item
|
||||
key="enableordisable"
|
||||
icon={
|
||||
|
@ -316,10 +374,10 @@ const Crontab = () => {
|
|||
>
|
||||
{record.status === CrontabStatus.disabled ? '启用' : '禁用'}
|
||||
</Menu.Item>
|
||||
{record.isSystem !== 1 && (
|
||||
<Menu.Item key="delete" icon={<DeleteOutlined />}>
|
||||
删除
|
||||
</Menu.Item>
|
||||
</>
|
||||
)}
|
||||
</Menu>
|
||||
}
|
||||
|
@ -385,8 +443,78 @@ const Crontab = () => {
|
|||
.finally(() => setLoading(false));
|
||||
};
|
||||
|
||||
const onSelectChange = (selectedIds: any[]) => {
|
||||
setSelectedRowIds(selectedIds);
|
||||
};
|
||||
|
||||
const rowSelection = {
|
||||
selectedRowIds,
|
||||
onChange: onSelectChange,
|
||||
selections: [
|
||||
Table.SELECTION_ALL,
|
||||
Table.SELECTION_INVERT,
|
||||
Table.SELECTION_NONE,
|
||||
],
|
||||
};
|
||||
|
||||
const delCrons = () => {
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
content: <>确认删除选中的定时任务吗</>,
|
||||
onOk() {
|
||||
request
|
||||
.delete(`${config.apiPrefix}crons`, { data: selectedRowIds })
|
||||
.then((data: any) => {
|
||||
if (data.code === 200) {
|
||||
notification.success({
|
||||
message: '批量删除成功',
|
||||
});
|
||||
setSelectedRowIds([]);
|
||||
getCrons();
|
||||
} else {
|
||||
notification.error({
|
||||
message: data,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
onCancel() {
|
||||
console.log('Cancel');
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const operateCrons = (operationStatus: number) => {
|
||||
Modal.confirm({
|
||||
title: `确认${OperationName[operationStatus]}`,
|
||||
content: <>确认{OperationName[operationStatus]}选中的定时任务吗</>,
|
||||
onOk() {
|
||||
request
|
||||
.put(`${config.apiPrefix}crons/${OperationPath[operationStatus]}`, {
|
||||
data: selectedRowIds,
|
||||
})
|
||||
.then((data: any) => {
|
||||
if (data.code === 200) {
|
||||
notification.success({
|
||||
message: `批量${OperationName[operationStatus]}成功`,
|
||||
});
|
||||
getCrons();
|
||||
} else {
|
||||
notification.error({
|
||||
message: data,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
onCancel() {
|
||||
console.log('Cancel');
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (logCron) {
|
||||
localStorage.setItem('logCron', logCron._id);
|
||||
setIsLogModalVisible(true);
|
||||
}
|
||||
}, [logCron]);
|
||||
|
@ -411,7 +539,6 @@ const Crontab = () => {
|
|||
<PageContainer
|
||||
className="code-mirror-wrapper"
|
||||
title="定时任务"
|
||||
loading={loading}
|
||||
extra={[
|
||||
<Search
|
||||
placeholder="请输入名称或者关键词"
|
||||
|
@ -436,7 +563,45 @@ const Crontab = () => {
|
|||
marginLeft,
|
||||
},
|
||||
}}
|
||||
style={{
|
||||
height: '100vh',
|
||||
}}
|
||||
>
|
||||
{selectedRowIds.length > 0 && (
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<Button type="primary" style={{ marginBottom: 5 }} onClick={delCrons}>
|
||||
批量删除
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => operateCrons(0)}
|
||||
style={{ marginLeft: 8, marginBottom: 5 }}
|
||||
>
|
||||
批量启用
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => operateCrons(1)}
|
||||
style={{ marginLeft: 8, marginRight: 8 }}
|
||||
>
|
||||
批量禁用
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
style={{ marginRight: 8 }}
|
||||
onClick={() => operateCrons(2)}
|
||||
>
|
||||
批量运行
|
||||
</Button>
|
||||
<Button type="primary" onClick={() => operateCrons(3)}>
|
||||
批量停止
|
||||
</Button>
|
||||
<span style={{ marginLeft: 8 }}>
|
||||
已选择
|
||||
<a>{selectedRowIds?.length}</a>项
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<Table
|
||||
columns={columns}
|
||||
pagination={{
|
||||
|
@ -447,8 +612,9 @@ const Crontab = () => {
|
|||
dataSource={value}
|
||||
rowKey="_id"
|
||||
size="middle"
|
||||
bordered
|
||||
scroll={{ x: 768 }}
|
||||
loading={loading}
|
||||
rowSelection={rowSelection}
|
||||
/>
|
||||
<CronLogModal
|
||||
visible={isLogModalVisible}
|
||||
|
|
|
@ -28,6 +28,7 @@ const CronLogModal = ({
|
|||
request
|
||||
.get(`${config.apiPrefix}crons/${cron._id}/log`)
|
||||
.then((data: any) => {
|
||||
if (localStorage.getItem('logCron') === cron._id) {
|
||||
const log = data.data as string;
|
||||
setValue(log || '暂无日志');
|
||||
if (log && !log.includes('执行结束')) {
|
||||
|
@ -35,6 +36,7 @@ const CronLogModal = ({
|
|||
getCronLog();
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
if (isFirst) {
|
||||
|
|
|
@ -68,19 +68,19 @@ const CronModal = ({
|
|||
>
|
||||
<Form form={form} layout="vertical" name="form_in_modal" preserve={false}>
|
||||
<Form.Item name="name" label="名称">
|
||||
<Input />
|
||||
<Input placeholder="请输入任务名称" />
|
||||
</Form.Item>
|
||||
<Form.Item name="command" label="任务" rules={[{ required: true }]}>
|
||||
<Input />
|
||||
<Form.Item name="command" label="命令" rules={[{ required: true }]}>
|
||||
<Input placeholder="请输入要执行的命令" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="schedule"
|
||||
label="时间"
|
||||
label="定时规则"
|
||||
rules={[
|
||||
{ required: true },
|
||||
{
|
||||
validator: (rule, value) => {
|
||||
if (cronParse.parseString(value).expressions.length > 0) {
|
||||
if (cronParse.parseExpression(value).hasNext()) {
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
return Promise.reject('Cron表达式格式有误');
|
||||
|
@ -89,7 +89,7 @@ const CronModal = ({
|
|||
},
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
<Input placeholder="秒(可选) 分 时 天 月 周" />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
|
|
@ -87,7 +87,7 @@ const Crontab = () => {
|
|||
newValue={sample}
|
||||
splitView={true}
|
||||
leftTitle="config.sh"
|
||||
rightTitle="config.sh.sample"
|
||||
rightTitle="config.sample.sh"
|
||||
disableWordDiff={true}
|
||||
/>
|
||||
{/* <CodeDiff
|
||||
|
|
Loading…
Reference in New Issue
Block a user