diff --git a/docker/Dockerfile b/docker/Dockerfile index 6dc6ebc4..dc886a41 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -31,7 +31,6 @@ RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && cd ${QL_DIR} \ && cp -f .env.example .env \ && ln -sf ${QL_DIR}/shell/task.sh /usr/local/bin/task \ - && ln -sf ${QL_DIR}/shell/task.sh /usr/local/bin/mytask \ && ln -sf ${QL_DIR}/shell/update.sh /usr/local/bin/update \ && ln -sf ${QL_DIR}/shell/rmlog.sh /usr/local/bin/rmlog \ && ln -sf ${QL_DIR}/shell/notify.sh /usr/local/bin/notify \ diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh index 72bc1d28..34532604 100644 --- a/docker/docker-entrypoint.sh +++ b/docker/docker-entrypoint.sh @@ -11,15 +11,6 @@ echo -e "======================2. 检测配置文件========================\n" [ ! -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.sample.list ${QL_DIR}/config/crontab.list - perl -i -pe "{s|CMD_UPDATE|update|g; s|CMD_REBUILD|rebuild|g; s|CMD_RMLOG|rmlog|g; s|CMD_TASK|task|g; s|CMD_MYTASK|mytask|g}" ${QL_DIR}/config/crontab.list -fi -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 diff --git a/gossh520_jd_scripts b/gossh520_jd_scripts new file mode 160000 index 00000000..85da52dc --- /dev/null +++ b/gossh520_jd_scripts @@ -0,0 +1 @@ +Subproject commit 85da52dc3fb5ede1c7cd70a2d3af62e37c18e341 diff --git a/sample/config.sample.sh b/sample/config.sample.sh index 28aaa332..f78d1ef2 100644 --- a/sample/config.sample.sh +++ b/sample/config.sample.sh @@ -37,7 +37,7 @@ AutoAddCron="true" RmLogDaysAgo="7" -## 在运行 task 或 mytask 命令时,随机延迟启动任务的最大延迟时间 +## 在运行 task 命令时,随机延迟启动任务的最大延迟时间 ## 如果任务不是必须准点运行的任务,那么给它增加一个随机延迟,由你定义最大延迟时间,单位为秒,如 RandomDelay="300" ,表示任务将在 1-300 秒内随机延迟一个秒数,然后再运行 ## 在crontab.list中,在每小时第0-2分、第30-31分、第59分这几个时间内启动的任务,均算作必须准点运行的任务,在启动这些任务时,即使你定义了RandomDelay,也将准点运行,不启用随机延迟 ## 在crontab.list中,除掉每小时上述时间启动的任务外,其他任务在你定义了 RandomDelay 的情况下,一律启用随机延迟,但如果你给某些任务添加了 "now" 或者 "conc",那么这些任务也将无视随机延迟直接启动 diff --git a/sample/crontab.sample.list b/sample/crontab.sample.list deleted file mode 100644 index c24ccfde..00000000 --- a/sample/crontab.sample.list +++ /dev/null @@ -1,11 +0,0 @@ -# 更新所有脚本 -55 2,13 * * * CMD_UPDATE all - -# 重构面板 -# 30 7 */7 * * CMD_REBUILD >> ${QL_DIR}/log/rebuild.log 2>&1 - -# 删除 RmLogDaysAgo 指定天数以前的旧日志,不记录日志 -57 13 * * * CMD_RMLOG >/dev/null 2>&1 - -# 其他定时任务,由本程序自动添加的任务使用 CMD_TASK 命令,由你自行添加的任务请使用 CMD_MYTASK 命令 -# 如果由本程序自动添加的任务你不想运行,注释即可,不要删除,请在最后保留一个空行 diff --git a/sample/jdCookie.js b/sample/jdCookie.js deleted file mode 100644 index c828d0a2..00000000 --- a/sample/jdCookie.js +++ /dev/null @@ -1,34 +0,0 @@ -/* -此文件为Node.js专用。其他用户请忽略 - */ -//此处填写京东账号cookie。 -let CookieJDs = [ - '',//账号一ck,例:pt_key=XXX;pt_pin=XXX; - '',//账号二ck,例:pt_key=XXX;pt_pin=XXX;如有更多,依次类推 -] -// 判断环境变量里面是否有京东ck -if (process.env.JD_COOKIE) { - if (process.env.JD_COOKIE.indexOf('&') > -1) { - CookieJDs = process.env.JD_COOKIE.split('&'); - } else if (process.env.JD_COOKIE.indexOf('\n') > -1) { - CookieJDs = process.env.JD_COOKIE.split('\n'); - } else { - CookieJDs = [process.env.JD_COOKIE]; - } -} -if (JSON.stringify(process.env).indexOf('GITHUB')>-1) { - console.log(`请勿使用github action运行此脚本,无论你是从你自己的私库还是其他哪里拉取的源代码,都会导致我被封号\n`); - !(async () => { - await require('./sendNotify').sendNotify('提醒', `请勿使用github action、滥用github资源会封我仓库以及账号`) - await process.exit(0); - })() -} -CookieJDs = [...new Set(CookieJDs.filter(item => !!item))] -console.log(`\n====================共${CookieJDs.length}个京东账号Cookie=========\n`); -console.log(`==================脚本执行- 北京时间(UTC+8):${new Date(new Date().getTime() + new Date().getTimezoneOffset()*60*1000 + 8*60*60*1000).toLocaleString()}=====================\n`) -if (process.env.JD_DEBUG && process.env.JD_DEBUG === 'false') console.log = () => {}; -for (let i = 0; i < CookieJDs.length; i++) { - if (!CookieJDs[i].match(/pt_pin=(.+?);/) || !CookieJDs[i].match(/pt_key=(.+?);/)) console.log(`\n提示:京东cookie 【${CookieJDs[i]}】填写不规范,可能会影响部分脚本正常使用。正确格式为: pt_key=xxx;pt_pin=xxx;(分号;不可少)\n`); - const index = (i + 1 === 1) ? '' : (i + 1); - exports['CookieJD' + index] = CookieJDs[i].trim(); -} diff --git a/sample/package.json b/sample/package.json deleted file mode 100644 index c3ee19ea..00000000 --- a/sample/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "lxk0301", - "version": "1.0.0", - "description": "{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}", - "main": "AlipayManor.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "repository": { - "type": "git", - "url": "https://github.com/lxk0301/jd_scripts.git" - }, - "keywords": [ - "" - ], - "author": "LXK9301", - "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" - } -} diff --git a/sample/sendNotify.js b/sample/sendNotify.js deleted file mode 100644 index 185ccd12..00000000 --- a/sample/sendNotify.js +++ /dev/null @@ -1,711 +0,0 @@ -/* - * @Author: lxk0301 https://gitee.com/lxk0301 - * @Date: 2020-08-19 16:12:40 - * @Last Modified by: lxk0301 - * @Last Modified time: 2021-4-3 16:00:54 - */ -/** - * sendNotify 推送通知功能 - * @param text 通知头 - * @param desp 通知体 - * @param params 某些推送通知方式点击弹窗可跳转, 例:{ url: 'https://abc.com' } - * @param author 作者仓库等信息 例:`本脚本免费使用 By:https://gitee.com/lxk0301/jd_docker` - * @returns {Promise} - */ -const querystring = require("querystring"); -const $ = new Env(); -const timeout = 15000;//超时时间(单位毫秒) -// =======================================微信server酱通知设置区域=========================================== -//此处填你申请的SCKEY. -//(环境变量名 PUSH_KEY) -let SCKEY = ''; - -// =======================================Bark App通知设置区域=========================================== -//此处填你BarkAPP的信息(IP/设备码,例如:https://api.day.app/XXXXXXXX) -let BARK_PUSH = ''; -//BARK app推送铃声,铃声列表去APP查看复制填写 -let BARK_SOUND = ''; - - -// =======================================telegram机器人通知设置区域=========================================== -//此处填你telegram bot 的Token,telegram机器人通知推送必填项.例如:1077xxx4424:AAFjv0FcqxxxxxxgEMGfi22B4yh15R5uw -//(环境变量名 TG_BOT_TOKEN) -let TG_BOT_TOKEN = ''; -//此处填你接收通知消息的telegram用户的id,telegram机器人通知推送必填项.例如:129xxx206 -//(环境变量名 TG_USER_ID) -let TG_USER_ID = ''; -//tg推送HTTP代理设置(不懂可忽略,telegram机器人通知推送功能中非必填) -let TG_PROXY_HOST = '';//例如:127.0.0.1(环境变量名:TG_PROXY_HOST) -let TG_PROXY_PORT = '';//例如:1080(环境变量名:TG_PROXY_PORT) -let TG_PROXY_AUTH = '';//tg代理配置认证参数 -//Telegram api自建的反向代理地址(不懂可忽略,telegram机器人通知推送功能中非必填),默认tg官方api(环境变量名:TG_API_HOST) -let TG_API_HOST = 'api.telegram.org' -// =======================================钉钉机器人通知设置区域=========================================== -//此处填你钉钉 bot 的webhook,例如:5a544165465465645d0f31dca676e7bd07415asdasd -//(环境变量名 DD_BOT_TOKEN) -let DD_BOT_TOKEN = ''; -//密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符串 -let DD_BOT_SECRET = ''; - -// =======================================企业微信机器人通知设置区域=========================================== -//此处填你企业微信机器人的 webhook(详见文档 https://work.weixin.qq.com/api/doc/90000/90136/91770),例如:693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa -//(环境变量名 QYWX_KEY) -let QYWX_KEY = ''; - -// =======================================企业微信应用消息通知设置区域=========================================== -/* -此处填你企业微信应用消息的值(详见文档 https://work.weixin.qq.com/api/doc/90000/90135/90236) -环境变量名 QYWX_AM依次填入 corpid,corpsecret,touser(注:多个成员ID使用|隔开),agentid,消息类型(选填,不填默认文本消息类型) -注意用,号隔开(英文输入法的逗号),例如:wwcff56746d9adwers,B-791548lnzXBE6_BWfxdf3kSTMJr9vFEPKAbh6WERQ,mingcheng,1000001,2COXgjH2UIfERF2zxrtUOKgQ9XklUqMdGSWLBoW_lSDAdafat -可选推送消息类型(推荐使用图文消息(mpnews)): -- 文本卡片消息: 0 (数字零) -- 文本消息: 1 (数字一) -- 图文消息(mpnews): 素材库图片id, 可查看此教程(http://note.youdao.com/s/HMiudGkb)或者(https://note.youdao.com/ynoteshare1/index.html?id=1a0c8aff284ad28cbd011b29b3ad0191&type=note) -*/ -let QYWX_AM = ''; - -// =======================================iGot聚合推送通知设置区域=========================================== -//此处填您iGot的信息(推送key,例如:https://push.hellyw.com/XXXXXXXX) -let IGOT_PUSH_KEY = ''; - -// =======================================push+设置区域======================================= -//官方文档:http://www.pushplus.plus/ -//PUSH_PLUS_TOKEN:微信扫码登录后一对一推送或一对多推送下面的token(您的Token),不提供PUSH_PLUS_USER则默认为一对一推送 -//PUSH_PLUS_USER: 一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送) -let PUSH_PLUS_TOKEN = ''; -let PUSH_PLUS_USER = ''; - -//==========================云端环境变量的判断与接收========================= -if (process.env.PUSH_KEY) { - SCKEY = process.env.PUSH_KEY; -} - -if (process.env.QQ_SKEY) { - QQ_SKEY = process.env.QQ_SKEY; -} - -if (process.env.QQ_MODE) { - QQ_MODE = process.env.QQ_MODE; -} - - -if (process.env.BARK_PUSH) { - if(process.env.BARK_PUSH.indexOf('https') > -1 || process.env.BARK_PUSH.indexOf('http') > -1) { - //兼容BARK自建用户 - BARK_PUSH = process.env.BARK_PUSH - } else { - BARK_PUSH = `https://api.day.app/${process.env.BARK_PUSH}` - } - if (process.env.BARK_SOUND) { - BARK_SOUND = process.env.BARK_SOUND - } -} else { - if(BARK_PUSH && BARK_PUSH.indexOf('https') === -1 && BARK_PUSH.indexOf('http') === -1) { - //兼容BARK本地用户只填写设备码的情况 - BARK_PUSH = `https://api.day.app/${BARK_PUSH}` - } -} -if (process.env.TG_BOT_TOKEN) { - TG_BOT_TOKEN = process.env.TG_BOT_TOKEN; -} -if (process.env.TG_USER_ID) { - TG_USER_ID = process.env.TG_USER_ID; -} -if (process.env.TG_PROXY_AUTH) TG_PROXY_AUTH = process.env.TG_PROXY_AUTH; -if (process.env.TG_PROXY_HOST) TG_PROXY_HOST = process.env.TG_PROXY_HOST; -if (process.env.TG_PROXY_PORT) TG_PROXY_PORT = process.env.TG_PROXY_PORT; -if (process.env.TG_API_HOST) TG_API_HOST = process.env.TG_API_HOST; - -if (process.env.DD_BOT_TOKEN) { - DD_BOT_TOKEN = process.env.DD_BOT_TOKEN; - if (process.env.DD_BOT_SECRET) { - DD_BOT_SECRET = process.env.DD_BOT_SECRET; - } -} - -if (process.env.QYWX_KEY) { - QYWX_KEY = process.env.QYWX_KEY; -} - -if (process.env.QYWX_AM) { - QYWX_AM = process.env.QYWX_AM; -} - -if (process.env.IGOT_PUSH_KEY) { - IGOT_PUSH_KEY = process.env.IGOT_PUSH_KEY -} - -if (process.env.PUSH_PLUS_TOKEN) { - PUSH_PLUS_TOKEN = process.env.PUSH_PLUS_TOKEN; -} -if (process.env.PUSH_PLUS_USER) { - PUSH_PLUS_USER = process.env.PUSH_PLUS_USER; -} -//==========================云端环境变量的判断与接收========================= - -/** - * sendNotify 推送通知功能 - * @param text 通知头 - * @param desp 通知体 - * @param params 某些推送通知方式点击弹窗可跳转, 例:{ url: 'https://abc.com' } - * @param author 作者仓库等信息 例:`本脚本免费使用 By:https://gitee.com/lxk0301/jd_docker` - * @returns {Promise} - */ -async function sendNotify(text, desp, params = {}, author = '\n\n本脚本免费使用 By:https://gitee.com/lxk0301/jd_docker') { - //提供6种通知 - desp += author;//增加作者信息,防止被贩卖等 - await Promise.all([ - serverNotify(text, desp),//微信server酱 - pushPlusNotify(text, desp)//pushplus(推送加) - ]) - //由于上述两种微信通知需点击进去才能查看到详情,故text(标题内容)携带了账号序号以及昵称信息,方便不点击也可知道是哪个京东哪个活动 - text = text.match(/.*?(?=\s?-)/g) ? text.match(/.*?(?=\s?-)/g)[0] : text; - await Promise.all([ - BarkNotify(text, desp, params),//iOS Bark APP - tgBotNotify(text, desp),//telegram 机器人 - ddBotNotify(text, desp),//钉钉机器人 - qywxBotNotify(text, desp), //企业微信机器人 - qywxamNotify(text, desp), //企业微信应用消息推送 - iGotNotify(text, desp, params),//iGot - //CoolPush(text, desp)//QQ酷推 - ]) -} - -function serverNotify(text, desp, time = 2100) { - return new Promise(resolve => { - if (SCKEY) { - //微信server酱推送通知一个\n不会换行,需要两个\n才能换行,故做此替换 - desp = desp.replace(/[\n\r]/g, '\n\n'); - const options = { - url: SCKEY.includes('SCT') ? `https://sctapi.ftqq.com/${SCKEY}.send` : `https://sc.ftqq.com/${SCKEY}.send`, - body: `text=${text}&desp=${desp}`, - headers: { - 'Content-Type': 'application/x-www-form-urlencoded' - }, - timeout - } - setTimeout(() => { - $.post(options, (err, resp, data) => { - try { - if (err) { - console.log('发送通知调用API失败!!\n') - console.log(err); - } else { - data = JSON.parse(data); - //server酱和Server酱·Turbo版的返回json格式不太一样 - if (data.errno === 0 || data.data.errno === 0 ) { - console.log('server酱发送通知消息成功🎉\n') - } else if (data.errno === 1024) { - // 一分钟内发送相同的内容会触发 - console.log(`server酱发送通知消息异常: ${data.errmsg}\n`) - } else { - console.log(`server酱发送通知消息异常\n${JSON.stringify(data)}`) - } - } - } catch (e) { - $.logErr(e, resp); - } finally { - resolve(data); - } - }) - }, time) - } else { - console.log('\n\n您未提供server酱的SCKEY,取消微信推送消息通知🚫\n'); - resolve() - } - }) -} - -function CoolPush(text, desp) { - return new Promise(resolve => { - if (QQ_SKEY) { - let options = { - url: `https://push.xuthus.cc/${QQ_MODE}/${QQ_SKEY}`, - headers: { - 'Content-Type': 'application/json' - } - } - - // 已知敏感词 - text = text.replace(/京豆/g, "豆豆"); - desp = desp.replace(/京豆/g, ""); - desp = desp.replace(/🐶/g, ""); - desp = desp.replace(/红包/g, "H包"); - - switch (QQ_MODE) { - case "email": - options.json = { - "t": text, - "c": desp, - }; - break; - default: - options.body = `${text}\n\n${desp}`; - } - - let pushMode = function(t) { - switch (t){ - case "send": - return "个人"; - case "group": - return "QQ群"; - case "wx": - return "微信"; - case "ww": - return "企业微信"; - case "email": - return "邮件"; - default: - return "未知方式" - } - } - - $.post(options, (err, resp, data) => { - try { - if (err) { - console.log(`发送${pushMode(QQ_MODE)}通知调用API失败!!\n`) - console.log(err); - } else { - data = JSON.parse(data); - if (data.code === 200) { - console.log(`酷推发送${pushMode(QQ_MODE)}通知消息成功🎉\n`) - } else if (data.code === 400) { - console.log(`QQ酷推(Cool Push)发送${pushMode(QQ_MODE)}推送失败:${data.msg}\n`) - } else if (data.code === 503) { - console.log(`QQ酷推出错,${data.message}:${data.data}\n`) - }else{ - console.log(`酷推推送异常: ${JSON.stringify(data)}`); - } - } - } catch (e) { - $.logErr(e, resp); - } finally { - resolve(data); - } - }) - } else { - console.log('您未提供酷推的SKEY,取消QQ推送消息通知🚫\n'); - resolve() - } - }) -} - -function BarkNotify(text, desp, params={}) { - return new Promise(resolve => { - if (BARK_PUSH) { - const options = { - url: `${BARK_PUSH}/${encodeURIComponent(text)}/${encodeURIComponent(desp)}?sound=${BARK_SOUND}&${querystring.stringify(params)}`, - headers: { - 'Content-Type': 'application/x-www-form-urlencoded' - }, - timeout - } - $.get(options, (err, resp, data) => { - try { - if (err) { - console.log('Bark APP发送通知调用API失败!!\n') - console.log(err); - } else { - data = JSON.parse(data); - if (data.code === 200) { - console.log('Bark APP发送通知消息成功🎉\n') - } else { - console.log(`${data.message}\n`); - } - } - } catch (e) { - $.logErr(e, resp); - } finally { - resolve(); - } - }) - } else { - console.log('您未提供Bark的APP推送BARK_PUSH,取消Bark推送消息通知🚫\n'); - resolve() - } - }) -} - -function tgBotNotify(text, desp) { - return new Promise(resolve => { - if (TG_BOT_TOKEN && TG_USER_ID) { - const options = { - url: `https://${TG_API_HOST}/bot${TG_BOT_TOKEN}/sendMessage`, - body: `chat_id=${TG_USER_ID}&text=${text}\n\n${desp}&disable_web_page_preview=true`, - headers: { - 'Content-Type': 'application/x-www-form-urlencoded' - }, - timeout - } - if (TG_PROXY_HOST && TG_PROXY_PORT) { - const tunnel = require("tunnel"); - const agent = { - https: tunnel.httpsOverHttp({ - proxy: { - host: TG_PROXY_HOST, - port: TG_PROXY_PORT * 1, - proxyAuth: TG_PROXY_AUTH - } - }) - } - Object.assign(options, { agent }) - } - $.post(options, (err, resp, data) => { - try { - if (err) { - console.log('telegram发送通知消息失败!!\n') - console.log(err); - } else { - data = JSON.parse(data); - if (data.ok) { - console.log('Telegram发送通知消息成功🎉。\n') - } else if (data.error_code === 400) { - console.log('请主动给bot发送一条消息并检查接收用户ID是否正确。\n') - } else if (data.error_code === 401){ - console.log('Telegram bot token 填写错误。\n') - } - } - } catch (e) { - $.logErr(e, resp); - } finally { - resolve(data); - } - }) - } else { - console.log('您未提供telegram机器人推送所需的TG_BOT_TOKEN和TG_USER_ID,取消telegram推送消息通知🚫\n'); - resolve() - } - }) -} -function ddBotNotify(text, desp) { - return new Promise(resolve => { - const options = { - url: `https://oapi.dingtalk.com/robot/send?access_token=${DD_BOT_TOKEN}`, - json: { - "msgtype": "text", - "text": { - "content": ` ${text}\n\n${desp}` - } - }, - headers: { - 'Content-Type': 'application/json' - }, - timeout - } - if (DD_BOT_TOKEN && DD_BOT_SECRET) { - const crypto = require('crypto'); - const dateNow = Date.now(); - const hmac = crypto.createHmac('sha256', DD_BOT_SECRET); - hmac.update(`${dateNow}\n${DD_BOT_SECRET}`); - const result = encodeURIComponent(hmac.digest('base64')); - options.url = `${options.url}×tamp=${dateNow}&sign=${result}`; - $.post(options, (err, resp, data) => { - try { - if (err) { - console.log('钉钉发送通知消息失败!!\n') - console.log(err); - } else { - data = JSON.parse(data); - if (data.errcode === 0) { - console.log('钉钉发送通知消息成功🎉。\n') - } else { - console.log(`${data.errmsg}\n`) - } - } - } catch (e) { - $.logErr(e, resp); - } finally { - resolve(data); - } - }) - } else if (DD_BOT_TOKEN) { - $.post(options, (err, resp, data) => { - try { - if (err) { - console.log('钉钉发送通知消息失败!!\n') - console.log(err); - } else { - data = JSON.parse(data); - if (data.errcode === 0) { - console.log('钉钉发送通知消息完成。\n') - } else { - console.log(`${data.errmsg}\n`) - } - } - } catch (e) { - $.logErr(e, resp); - } finally { - resolve(data); - } - }) - } else { - console.log('您未提供钉钉机器人推送所需的DD_BOT_TOKEN或者DD_BOT_SECRET,取消钉钉推送消息通知🚫\n'); - resolve() - } - }) -} - -function qywxBotNotify(text, desp) { - return new Promise(resolve => { - const options = { - url: `https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${QYWX_KEY}`, - json: { - msgtype: 'text', - text: { - content: ` ${text}\n\n${desp}`, - }, - }, - headers: { - 'Content-Type': 'application/json', - }, - timeout - }; - if (QYWX_KEY) { - $.post(options, (err, resp, data) => { - try { - if (err) { - console.log('企业微信发送通知消息失败!!\n'); - console.log(err); - } else { - data = JSON.parse(data); - if (data.errcode === 0) { - console.log('企业微信发送通知消息成功🎉。\n'); - } else { - console.log(`${data.errmsg}\n`); - } - } - } catch (e) { - $.logErr(e, resp); - } finally { - resolve(data); - } - }); - } else { - console.log('您未提供企业微信机器人推送所需的QYWX_KEY,取消企业微信推送消息通知🚫\n'); - resolve(); - } - }); -} - -function ChangeUserId(desp) { - const QYWX_AM_AY = QYWX_AM.split(','); - if (QYWX_AM_AY[2]) { - const userIdTmp = QYWX_AM_AY[2].split("|"); - let userId = ""; - for (let i = 0; i < userIdTmp.length; i++) { - const count = "账号" + (i + 1); - const count2 = "签到号 " + (i + 1); - if (desp.match(count2)) { - userId = userIdTmp[i]; - } - } - if (!userId) userId = QYWX_AM_AY[2]; - return userId; - } else { - return "@all"; - } -} - -function qywxamNotify(text, desp) { - return new Promise(resolve => { - if (QYWX_AM) { - const QYWX_AM_AY = QYWX_AM.split(','); - const options_accesstoken = { - url: `https://qyapi.weixin.qq.com/cgi-bin/gettoken`, - json: { - corpid: `${QYWX_AM_AY[0]}`, - corpsecret: `${QYWX_AM_AY[1]}`, - }, - headers: { - 'Content-Type': 'application/json', - }, - timeout - }; - $.post(options_accesstoken, (err, resp, data) => { - html = desp.replace(/\n/g, "
") - var json = JSON.parse(data); - accesstoken = json.access_token; - let options; - - switch (QYWX_AM_AY[4]) { - case '0': - options = { - msgtype: 'textcard', - textcard: { - title: `${text}`, - description: `${desp}`, - url: 'https://github.com/lxk0301/jd_scripts', - btntxt: '更多' - } - } - break; - - case '1': - options = { - msgtype: 'text', - text: { - content: `${text}\n\n${desp}` - } - } - break; - - default: - options = { - msgtype: 'mpnews', - mpnews: { - articles: [ - { - title: `${text}`, - thumb_media_id: `${QYWX_AM_AY[4]}`, - author: `智能助手`, - content_source_url: ``, - content: `${html}`, - digest: `${desp}` - } - ] - } - } - }; - if (!QYWX_AM_AY[4]) { - //如不提供第四个参数,则默认进行文本消息类型推送 - options = { - msgtype: 'text', - text: { - content: `${text}\n\n${desp}` - } - } - } - options = { - url: `https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=${accesstoken}`, - json: { - touser: `${ChangeUserId(desp)}`, - agentid: `${QYWX_AM_AY[3]}`, - safe: '0', - ...options - }, - headers: { - 'Content-Type': 'application/json', - }, - } - - $.post(options, (err, resp, data) => { - try { - if (err) { - console.log('成员ID:' + ChangeUserId(desp) + '企业微信应用消息发送通知消息失败!!\n'); - console.log(err); - } else { - data = JSON.parse(data); - if (data.errcode === 0) { - console.log('成员ID:' + ChangeUserId(desp) + '企业微信应用消息发送通知消息成功🎉。\n'); - } else { - console.log(`${data.errmsg}\n`); - } - } - } catch (e) { - $.logErr(e, resp); - } finally { - resolve(data); - } - }); - }); - } else { - console.log('您未提供企业微信应用消息推送所需的QYWX_AM,取消企业微信应用消息推送消息通知🚫\n'); - resolve(); - } - }); -} - -function iGotNotify(text, desp, params={}){ - return new Promise(resolve => { - if (IGOT_PUSH_KEY) { - // 校验传入的IGOT_PUSH_KEY是否有效 - const IGOT_PUSH_KEY_REGX = new RegExp("^[a-zA-Z0-9]{24}$") - if(!IGOT_PUSH_KEY_REGX.test(IGOT_PUSH_KEY)) { - console.log('您所提供的IGOT_PUSH_KEY无效\n') - resolve() - return - } - const options = { - url: `https://push.hellyw.com/${IGOT_PUSH_KEY.toLowerCase()}`, - body: `title=${text}&content=${desp}&${querystring.stringify(params)}`, - headers: { - 'Content-Type': 'application/x-www-form-urlencoded' - }, - timeout - } - $.post(options, (err, resp, data) => { - try { - if (err) { - console.log('发送通知调用API失败!!\n') - console.log(err); - } else { - if(typeof data === 'string') data = JSON.parse(data); - if (data.ret === 0) { - console.log('iGot发送通知消息成功🎉\n') - } else { - console.log(`iGot发送通知消息失败:${data.errMsg}\n`) - } - } - } catch (e) { - $.logErr(e, resp); - } finally { - resolve(data); - } - }) - } else { - console.log('您未提供iGot的推送IGOT_PUSH_KEY,取消iGot推送消息通知🚫\n'); - resolve() - } - }) -} - -function pushPlusNotify(text, desp) { - return new Promise(resolve => { - if (PUSH_PLUS_TOKEN) { - desp = desp.replace(/[\n\r]/g, '
'); // 默认为html, 不支持plaintext - const body = { - token: `${PUSH_PLUS_TOKEN}`, - title: `${text}`, - content:`${desp}`, - topic: `${PUSH_PLUS_USER}` - }; - const options = { - url: `http://www.pushplus.plus/send`, - body: JSON.stringify(body), - headers: { - 'Content-Type': ' application/json' - }, - timeout - } - $.post(options, (err, resp, data) => { - try { - if (err) { - console.log(`push+发送${PUSH_PLUS_USER ? '一对多' : '一对一'}通知消息失败!!\n`) - console.log(err); - } else { - data = JSON.parse(data); - if (data.code === 200) { - console.log(`push+发送${PUSH_PLUS_USER ? '一对多' : '一对一'}通知消息完成。\n`) - } else { - console.log(`push+发送${PUSH_PLUS_USER ? '一对多' : '一对一'}通知消息失败:${data.msg}\n`) - } - } - } catch (e) { - $.logErr(e, resp); - } finally { - resolve(data); - } - }) - } else { - console.log('您未提供push+推送所需的PUSH_PLUS_TOKEN,取消push+推送消息通知🚫\n'); - resolve() - } - }) -} - -module.exports = { - sendNotify, - BARK_PUSH -} -// prettier-ignore -function Env(t,s){return new class{constructor(t,s){this.name=t,this.data=null,this.dataFile="box.dat",this.logs=[],this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,s),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}getScript(t){return new Promise(s=>{$.get({url:t},(t,e,i)=>s(i))})}runScript(t,s){return new Promise(e=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let o=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");o=o?1*o:20,o=s&&s.timeout?s.timeout:o;const[h,a]=i.split("@"),r={url:`http://${a}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:o},headers:{"X-Key":h,Accept:"*/*"}};$.post(r,(t,s,i)=>e(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),s=this.path.resolve(process.cwd(),this.dataFile),e=this.fs.existsSync(t),i=!e&&this.fs.existsSync(s);if(!e&&!i)return{};{const i=e?t:s;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),s=this.path.resolve(process.cwd(),this.dataFile),e=this.fs.existsSync(t),i=!e&&this.fs.existsSync(s),o=JSON.stringify(this.data);e?this.fs.writeFileSync(t,o):i?this.fs.writeFileSync(s,o):this.fs.writeFileSync(t,o)}}lodash_get(t,s,e){const i=s.replace(/\[(\d+)\]/g,".$1").split(".");let o=t;for(const t of i)if(o=Object(o)[t],void 0===o)return e;return o}lodash_set(t,s,e){return Object(t)!==t?t:(Array.isArray(s)||(s=s.toString().match(/[^.[\]]+/g)||[]),s.slice(0,-1).reduce((t,e,i)=>Object(t[e])===t[e]?t[e]:t[e]=Math.abs(s[i+1])>>0==+s[i+1]?[]:{},t)[s[s.length-1]]=e,t)}getdata(t){let s=this.getval(t);if(/^@/.test(t)){const[,e,i]=/^@(.*?)\.(.*?)$/.exec(t),o=e?this.getval(e):"";if(o)try{const t=JSON.parse(o);s=t?this.lodash_get(t,i,""):s}catch(t){s=""}}return s}setdata(t,s){let e=!1;if(/^@/.test(s)){const[,i,o]=/^@(.*?)\.(.*?)$/.exec(s),h=this.getval(i),a=i?"null"===h?null:h||"{}":"{}";try{const s=JSON.parse(a);this.lodash_set(s,o,t),e=this.setval(JSON.stringify(s),i)}catch(s){const h={};this.lodash_set(h,o,t),e=this.setval(JSON.stringify(h),i)}}else e=$.setval(t,s);return e}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,s){return this.isSurge()||this.isLoon()?$persistentStore.write(t,s):this.isQuanX()?$prefs.setValueForKey(t,s):this.isNode()?(this.data=this.loaddata(),this.data[s]=t,this.writedata(),!0):this.data&&this.data[s]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,s=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?$httpClient.get(t,(t,e,i)=>{!t&&e&&(e.body=i,e.statusCode=e.status),s(t,e,i)}):this.isQuanX()?$task.fetch(t).then(t=>{const{statusCode:e,statusCode:i,headers:o,body:h}=t;s(null,{status:e,statusCode:i,headers:o,body:h},h)},t=>s(t)):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,s)=>{try{const e=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();this.ckjar.setCookieSync(e,null),s.cookieJar=this.ckjar}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:e,statusCode:i,headers:o,body:h}=t;s(null,{status:e,statusCode:i,headers:o,body:h},h)},t=>s(t)))}post(t,s=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),delete t.headers["Content-Length"],this.isSurge()||this.isLoon())$httpClient.post(t,(t,e,i)=>{!t&&e&&(e.body=i,e.statusCode=e.status),s(t,e,i)});else if(this.isQuanX())t.method="POST",$task.fetch(t).then(t=>{const{statusCode:e,statusCode:i,headers:o,body:h}=t;s(null,{status:e,statusCode:i,headers:o,body:h},h)},t=>s(t));else if(this.isNode()){this.initGotEnv(t);const{url:e,...i}=t;this.got.post(e,i).then(t=>{const{statusCode:e,statusCode:i,headers:o,body:h}=t;s(null,{status:e,statusCode:i,headers:o,body:h},h)},t=>s(t))}}time(t){let s={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in s)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?s[e]:("00"+s[e]).substr((""+s[e]).length)));return t}msg(s=t,e="",i="",o){const h=t=>!t||!this.isLoon()&&this.isSurge()?t:"string"==typeof t?this.isLoon()?t:this.isQuanX()?{"open-url":t}:void 0:"object"==typeof t&&(t["open-url"]||t["media-url"])?this.isLoon()?t["open-url"]:this.isQuanX()?t:void 0:void 0;$.isMute||(this.isSurge()||this.isLoon()?$notification.post(s,e,i,h(o)):this.isQuanX()&&$notify(s,e,i,h(o))),this.logs.push("","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="),this.logs.push(s),e&&this.logs.push(e),i&&this.logs.push(i)}log(...t){t.length>0?this.logs=[...this.logs,...t]:console.log(this.logs.join(this.logSeparator))}logErr(t,s){const e=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();e?$.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):$.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(s=>setTimeout(s,t))}done(t={}){const s=(new Date).getTime(),e=(s-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${e} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,s)} diff --git a/shell/api.sh b/shell/api.sh old mode 100644 new mode 100755 diff --git a/shell/mytask.sh b/shell/mytask.sh deleted file mode 120000 index 315a66d0..00000000 --- a/shell/mytask.sh +++ /dev/null @@ -1 +0,0 @@ -task.sh \ No newline at end of file diff --git a/shell/notify.js b/shell/notify.js index 0ade7e9b..b70fe673 100644 --- a/shell/notify.js +++ b/shell/notify.js @@ -1,4 +1,4 @@ -const notify = require('../scripts/sendNotify.js'); +const notify = require('/ql/scripts/sendNotify.js'); const title = process.argv[2]; const content = process.argv[3]; diff --git a/shell/rebuild.sh b/shell/rebuild.sh deleted file mode 100644 index ecec1823..00000000 --- a/shell/rebuild.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash - -dir_shell=$(dirname $(readlink -f "$0")) -dir_root=$(cd $dir_shell; cd ..; pwd) - -echo -e "更新qinglong...\n" -cd $dir_root -git fetch --all -git pull -echo -e "更新更新qinglong完成...\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" -pm2 restart panel 2>/dev/null || pm2 start $dir_root/build/app.js -n panel -nginx -s reload - -echo -e "重启服务完成...\n" \ No newline at end of file diff --git a/shell/rmlog.sh b/shell/rmlog.sh index 6d65c1ce..5ba7d00b 100755 --- a/shell/rmlog.sh +++ b/shell/rmlog.sh @@ -2,7 +2,7 @@ ## 判断环境 dir_shell=$(dirname $(readlink -f "$0")) -dir_root=$(cd $dir_shell; cd ..; pwd) +dir_root=$(cd $dir_shell; pwd) ## 导入通用变量与函数 . $dir_shell/share.sh diff --git a/shell/share.sh b/shell/share.sh old mode 100644 new mode 100755 index 0a3c7748..e33912d2 --- a/shell/share.sh +++ b/shell/share.sh @@ -2,6 +2,7 @@ dir_sample=$dir_root/sample dir_config=$dir_root/config dir_scripts=$dir_root/scripts +dir_repo=$dir_root/repo dir_raw=$dir_scripts/raw dir_log=$dir_root/log dir_list_tmp=$dir_log/.tmp @@ -34,13 +35,11 @@ var_name=( ## 软连接及其原始文件对应关系 link_name=( task - mytask rmlog update rebuild ) original_name=( - task.sh task.sh rmlog.sh update.sh @@ -69,15 +68,6 @@ import_config_and_check () { fi } -## 发送通知,依赖于import_config_and_check或import_config_no_check,$1:标题,$2:内容 -notify () { - local title=$(echo $1 | perl -pe 's|-|_|g') - local msg="$(echo -e $2)" - if [ -d $dir_scripts_node_modules ]; then - node $dir_shell/notify.js "$title" "$msg" - fi -} - ## 创建目录,$1:目录的绝对路径 make_dir () { local dir=$1 @@ -154,52 +144,6 @@ define_cmd () { done } -## 统计 own 仓库数量 -count_own_repo_sum () { - own_repo_sum=0 - for ((i=1; i<=1000; i++)); do - local tmp1=RepoUrl$i - local tmp2=${!tmp1} - [[ $tmp2 ]] && own_repo_sum=$i || break - done -} - -## 形成 own 仓库的文件夹名清单,依赖于import_config_and_check或import_config_no_check -## array_own_repo_path:repo存放的绝对路径组成的数组;array_own_scripts_path:所有要使用的脚本所在的绝对路径组成的数组 -gen_own_dir_and_path () { - local scripts_path_num="-1" - local repo_num tmp1 tmp2 tmp3 tmp4 tmp5 dir - - if [[ $own_repo_sum -ge 1 ]]; then - for ((i=1; i<=$own_repo_sum; i++)); do - repo_num=$((i - 1)) - tmp1=RepoUrl$i - array_own_repo_url[$repo_num]=${!tmp1} - tmp2=RepoBranch$i - array_own_repo_branch[$repo_num]=${!tmp2} - array_own_repo_dir[$repo_num]=$(echo ${array_own_repo_url[$repo_num]} | perl -pe "s|\.git||" | awk -F "/|:" '{print $((NF - 1)) "_" $NF}') - array_own_repo_path[$repo_num]=$dir_scripts/${array_own_repo_dir[$repo_num]} - tmp3=RepoPath$i - if [[ ${!tmp3} ]]; then - for dir in ${!tmp3}; do - let scripts_path_num++ - tmp4="${array_own_repo_dir[repo_num]}/$dir" - tmp5=$(echo $tmp4 | perl -pe "{s|//|/|g; s|/$||}") # 去掉多余的/ - array_own_scripts_path[$scripts_path_num]="$dir_scripts/$tmp5" - done - else - let scripts_path_num++ - array_own_scripts_path[$scripts_path_num]="${array_own_repo_path[$repo_num]}" - fi - done - fi - - if [[ ${#RawUrl[*]} -ge 1 ]]; then - let scripts_path_num++ - array_own_scripts_path[$scripts_path_num]=$dir_raw # 只有own脚本所在绝对路径附加了raw文件夹,其他数组均不附加 - fi -} - ## 修复配置文件 fix_config () { make_dir $dir_config @@ -208,16 +152,9 @@ fix_config () { cp -fv $file_config_sample $file_config_user echo fi - if [ ! -s $list_crontab_user ]; then - echo -e "复制一份 $list_crontab_sample 为 $list_crontab_user,这是你自己的 crontab.list\n" - cp -fv $list_crontab_sample $list_crontab_user - echo - fi perl -i -pe "{ s|CMD_UPDATE|$cmd_update|g; - s|CMD_REBUILD|$cmd_rebuild|g; s|CMD_RMLOG|$cmd_rmlog|g; - s|CMD_TASK|$cmd_task|g; - s|CMD_MYTASK|$cmd_mytask|g + s|CMD_TASK|$cmd_task|g }" $list_crontab_user } diff --git a/shell/task.sh b/shell/task.sh old mode 100644 new mode 100755 index dcd40082..1c69fac4 --- a/shell/task.sh +++ b/shell/task.sh @@ -2,18 +2,11 @@ ## 路径 dir_shell=$(dirname $(readlink -f "$0")) -dir_root=$(cd $dir_shell; cd ..; pwd) +dir_root=$(cd $dir_shell; pwd) ## 导入通用变量与函数 . $dir_shell/share.sh -## 更新crontab -update_crontab () { - if [[ $(cat $list_crontab_user) != $(crontab -l) ]]; then - crontab $list_crontab_user - fi -} - ## 组合Cookie和互助码子程序,$1:要组合的内容 combine_sub () { local what_combine=$1 @@ -68,20 +61,16 @@ random_delay () { ## scripts目录下所有可运行脚本数组 gen_array_scripts () { import_config_no_check - count_own_repo_sum - gen_own_dir_and_path local dir_current=$(pwd) local i="-1" - for ((scripts_path_num=0; scripts_path_num<${#array_own_scripts_path[*]}; scripts_path_num++)); do - cd ${array_own_scripts_path[$scripts_path_num]} - for file in $(ls); do - if [ -f $file ] && [[ $(grep "new Env" $file) ]] && [[ $file == *.js && $file != sendNotify.js && $file != JD_extra_cookie.js ]]; then - let i++ - array_scripts[i]=$(echo "${array_own_scripts_path[$scripts_path_num]}/$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_scripts + for file in $(ls); do + if [ -f $file ] && [[ $file == *.js && $file != sendNotify.js && $file != JD_extra_cookie.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 } @@ -113,7 +102,6 @@ run_normal () { cd $dir_scripts if [ -f $p1 ]; then import_config_and_check "$p1" - update_crontab define_program "$p1" combine_all [[ $# -eq 1 ]] && random_delay @@ -122,7 +110,6 @@ run_normal () { make_dir "$dir_log/$p1" $which_program $p1 2>&1 | tee $log_path else - update_crontab echo -e "\n $p1 脚本不存在,请确认...\n" usage fi @@ -135,7 +122,6 @@ run_concurrent () { cd $dir_scripts if [ -f $p1 ]; then import_config_and_check "$p1" - update_crontab define_program make_dir $dir_log/$p1 log_time=$(date "+%Y-%m-%d-%H-%M-%S.%N") @@ -149,7 +135,6 @@ run_concurrent () { $which_program $p1 &>$log_path & done else - update_crontab echo -e "\n $p1 脚本不存在,请确认...\n" usage fi diff --git a/shell/update.sh b/shell/update.sh old mode 100644 new mode 100755 index 2b5350e7..9f95b50d --- a/shell/update.sh +++ b/shell/update.sh @@ -1,13 +1,24 @@ #!/usr/bin/env bash ## 文件路径、脚本网址 -dir_shell=$(dirname $(readlink -f "$0")) -dir_root=$(cd $dir_shell; cd ..; pwd) +# dir_shell=$(dirname $(readlink -f "$0")) +# dir_root=$( +# cd $dir_shell +# cd .. +# pwd +# ) +dir_shell=$(pwd) +dir_root=$( + cd $dir_shell + pwd +) send_mark=$dir_shell/send_mark -## 导入通用变量与函数 -. $dir_shell/share.sh -. $dir_shell/api.sh +# 导入通用变量与函数 +# . $dir_shell/share.sh +# . $dir_shell/api.sh +. ./shell/share.sh +. ./shell/api.sh ## 导入配置文件,检测平台,创建软连接,识别命令,修复配置文件 detect_termux @@ -19,7 +30,7 @@ import_config_no_check "update" get_token ## 重置仓库remote url,docker专用,$1:要重置的目录,$2:要重置为的网址 -reset_romote_url () { +reset_romote_url() { local dir_current=$(pwd) local dir_work=$1 local url=$2 @@ -33,7 +44,7 @@ reset_romote_url () { } ## 克隆脚本,$1:仓库地址,$2:仓库保存路径,$3:分支(可省略) -git_clone_scripts () { +git_clone_scripts() { local url=$1 local dir=$2 local branch=$3 @@ -44,7 +55,7 @@ git_clone_scripts () { } ## 更新脚本,$1:仓库保存路径 -git_pull_scripts () { +git_pull_scripts() { local dir_current=$(pwd) local dir_work=$1 cd $dir_work @@ -56,51 +67,27 @@ git_pull_scripts () { cd $dir_current } -## 生成脚本的路径清单文件 -gen_list_own () { - local dir_current=$(pwd) - rm -f $dir_list_tmp/own*.list >/dev/null 2>&1 - for ((i=0; i<${#array_own_scripts_path[*]}; i++)); do - cd ${array_own_scripts_path[i]} - if [[ $(ls *.js 2>/dev/null) ]]; then - for file in $(ls *.js); do - if [ -f $file ]; then - perl -ne "{ - print if /.*([\d\*]*[\*-\/,\d]*[\d\*] ){4}[\d\*]*[\*-\/,\d]*[\d\*]( |,|\").*\/?$file/ - }" $file | \ - perl -pe "{ - s|.*(([\d\*]*[\*-\/,\d]*[\d\*] ){4}[\d\*]*[\*-\/,\d]*[\d\*])( \|,\|\").*/?$file.*|${array_own_scripts_path[i]}/$file|g; - s|$dir_scripts/|| - }" | head -1 >> $list_own_scripts - fi - done - fi - done - grep -E "$cmd_task " $list_crontab_user | perl -pe "s|.* $cmd_task ([^\s]+)( .+\|$)|\1|" | sort -u > $list_own_user - cd $dir_current -} - ## 检测cron的差异,$1:脚本清单文件路径,$2:cron任务清单文件路径,$3:增加任务清单文件路径,$4:删除任务清单文件路径 -diff_cron () { +diff_cron() { make_dir $dir_list_tmp 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 + 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 + grep -vwf $list_scripts $list_task >$list_drop else cp -f $list_task $list_drop fi } ## 更新docker-entrypoint,docker专用 -update_docker_entrypoint () { +update_docker_entrypoint() { if [[ $QL_DIR ]] && [[ $(diff $dir_root/docker/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh) ]]; then cp -f $dir_root/docker/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh chmod 777 /usr/local/bin/docker-entrypoint.sh @@ -108,7 +95,7 @@ update_docker_entrypoint () { } ## 检测配置文件版本 -detect_config_version () { +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|") @@ -127,7 +114,7 @@ detect_config_version () { 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 + [[ $? -eq 0 ]] && echo $ver_config_sample >$send_mark fi else [ -f $send_mark ] && rm -f $send_mark @@ -135,7 +122,7 @@ detect_config_version () { } ## npm install 子程序,判断是否为安卓,判断是否安装有yarn -npm_install_sub () { +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 @@ -147,7 +134,7 @@ npm_install_sub () { } ## npm install,$1:package.json文件所在路径 -npm_install_1 () { +npm_install_1() { local dir_current=$(pwd) local dir_work=$1 @@ -158,7 +145,7 @@ npm_install_1 () { cd $dir_current } -npm_install_2 () { +npm_install_2() { local dir_current=$(pwd) local dir_work=$1 @@ -171,7 +158,7 @@ npm_install_2 () { } ## 比对两个文件,$1比$2新时,将$1复制为$2 -diff_and_copy () { +diff_and_copy() { local copy_source=$1 local copy_to=$2 if [ ! -s $copy_to ] || [[ $(diff $copy_source $copy_to) ]]; then @@ -180,20 +167,17 @@ diff_and_copy () { } ## 更新依赖 -update_depend () { +update_depend() { 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 [ ! -d $dir_scripts/node_modules ] && npm_install_2 $dir_scripts - - diff_and_copy "$dir_sample/sendNotify.js" "$dir_scripts/sendNotify.js" - diff_and_copy "$dir_sample/jdCookie.js" "$dir_scripts/jdCookie.js" } ## 输出是否有新的或失效的定时任务,$1:新的或失效的任务清单文件路径,$2:新/失效 -output_list_add_drop () { +output_list_add_drop() { local list=$1 local type=$2 if [ -s $list ]; then @@ -205,14 +189,14 @@ output_list_add_drop () { ## 自动删除失效的脚本与定时任务,需要:1.AutoDelCron/AutoDelCron 设置为 true;2.正常更新js脚本,没有报错;3.存在失效任务;4.crontab.list存在并且不为空 ## $1:失效任务清单文件路径 -del_cron () { +del_cron() { local list_drop=$1 local detail detail2 if [ -s $list_drop ] && [ -s $list_crontab_user ]; then - detail=$(cat $list_drop) + detail=$(cat $list_drop) echo -e "开始尝试自动删除失效的定时任务...\n" for cron in $detail; do - local id=$(cat $list_crontab_user | grep -E "$cmd_task $cron" | perl -pe "s|.*ID=(.*) $cmd_task $cron|\1|") + local id=$(cat $list_crontab_user | grep -E "$cmd_task $cron$" | perl -pe "s|.*ID=(.*) $cmd_task $cron$|\1|") del_cron_api "$id" done detail2=$(echo $detail | perl -pe "s| |\\\n|g") @@ -223,74 +207,75 @@ del_cron () { ## 自动增加定时任务,需要:1.AutoAddCron 设置为 true;2.正常更新js脚本,没有报错;3.存在新任务;4.crontab.list存在并且不为空 ## $1:新任务清单文件路径 -add_cron () { +add_cron() { local list_add=$1 - if [ -s $list_crontab_user ]; then - echo -e "开始尝试自动添加定时任务...\n" - local detail=$(cat $list_add) - cd $dir_scripts - for file_relative_path in $detail; do - local file_name=$(echo $file_relative_path | awk -F "/" '{print $NF}') - if [ -f $file_relative_path ]; then - cron_line=$( - perl -ne "{ + echo -e "开始尝试自动添加定时任务...\n" + local detail=$(cat $list_add) + cd $dir_scripts + for file_relative_path in $detail; do + local file_name=$(echo $file_relative_path | awk -F "/" '{print $NF}') + if [ -f $file_relative_path ]; then + cron_line=$( + perl -ne "{ print if /.*([\d\*]*[\*-\/,\d]*[\d\*] ){4}[\d\*]*[\*-\/,\d]*[\d\*]( |,|\").*$file_name/ - }" $file_relative_path | \ + }" $file_relative_path | perl -pe "{ s|[^\d\*]*(([\d\*]*[\*-\/,\d]*[\d\*] ){4}[\d\*]*[\*-\/,\d]*[\d\*])( \|,\|\").*/?$file_name.*|\1:$cmd_task $file_relative_path|g; s| | |g }" | sort -u | head -1 - ) - cron_name=$(grep "new Env" $file_relative_path | awk -F "'|\"" '{print $2}' | head -1) - [[ -z $cron_name ]] && cron_name="$file_name" - add_cron_api "$cron_line:$cron_name" - fi - done - exit_status=$? - local detail2=$(echo $detail | perl -pe "s| |\\\n|g") - if [[ $exit_status -eq 0 ]]; then - crontab $list_crontab_user - echo -e "成功添加新的定时任务...\n" - notify "新增任务通知" "成功添加新的定时任务:\n$detail2" - else - echo -e "添加新的定时任务出错,请手动添加...\n" - notify "新任务添加失败通知" "尝试自动添加以下新的定时任务出错,请手动添加:\n$detail2" + ) + cron_name=$(grep "new Env" $file_relative_path | awk -F "'|\"" '{print $2}' | head -1) + [[ -z $cron_name ]] && cron_name="$file_name" + add_cron_api "$cron_line:$cron_name" fi + done + exit_status=$? + local detail2=$(echo $detail | perl -pe "s| |\\\n|g") + if [[ $exit_status -eq 0 ]]; then + echo -e "成功添加新的定时任务...\n" + notify "新增任务通知" "成功添加新的定时任务:\n$detail2" + else + echo -e "添加新的定时任务出错,请手动添加...\n" + notify "新任务添加失败通知" "尝试自动添加以下新的定时任务出错,请手动添加:\n$detail2" fi } -## 更新所有仓库 -update_own_repo () { - [[ ${#array_own_repo_url[*]} -gt 0 ]] && echo -e "--------------------------------------------------------------\n" - for ((i=0; i<${#array_own_repo_url[*]}; i++)); do - if [ -d ${array_own_repo_path[i]}/.git ]; then - reset_romote_url ${array_own_repo_path[i]} ${array_own_repo_url[i]} - git_pull_scripts ${array_own_repo_path[i]} - else - git_clone_scripts ${array_own_repo_url[i]} ${array_own_repo_path[i]} ${array_own_repo_branch[i]} - fi - if [[ $exit_status -eq 0 ]]; then - echo -e "\n更新${array_own_repo_path[i]}成功...\n" - diff_and_copy "$dir_sample/sendNotify.js" "${array_own_repo_path[i]}/sendNotify.js" - diff_and_copy "$dir_sample/jdCookie.js" "${array_own_repo_path[i]}/jdCookie.js" - else - echo -e "\n更新${array_own_repo_path[i]}失败,请检查原因...\n" - fi - done - for ((i=0; i<${#array_own_scripts_path[*]}; i++)); do - diff_and_copy "$dir_sample/sendNotify.js" "${array_own_scripts_path[i]}/sendNotify.js" - diff_and_copy "$dir_sample/jdCookie.js" "${array_own_scripts_path[i]}/jdCookie.js" - done +## 更新仓库 +update_repo() { + echo -e "--------------------------------------------------------------\n" + local url="$1" + local path="$2" + local blackword="$3" + local urlTmp="${url%*/}" + local repoTmp="${urlTmp##*/}" + local repo="${repoTmp%.*}" + local tmp="${url%/*}" + local authorTmp1="${tmp##*/}" + local authorTmp2="${authorTmp1##*:}" + local author="${authorTmp2##*.}" + + local repo_path="${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 } ## 更新所有 raw 文件 -update_own_raw () { +update_raw() { if [[ ${#RawUrl[*]} -gt 0 ]]; then echo -e "--------------------------------------------------------------\n" make_dir $dir_raw - diff_and_copy "$dir_sample/sendNotify.js" "$dir_raw/sendNotify.js" - diff_and_copy "$dir_sample/jdCookie.js" "$dir_raw/jdCookie.js" - for ((i=0; i<${#RawUrl[*]}; i++)); do + for ((i = 0; i < ${#RawUrl[*]}; i++)); do raw_file_name[$i]=$(echo ${RawUrl[i]} | awk -F "/" '{print $NF}') echo -e "开始下载:${RawUrl[i]} \n\n保存路径:$dir_raw/${raw_file_name[$i]}\n" wget -q --no-check-certificate -O "$dir_raw/${raw_file_name[$i]}.new" ${RawUrl[i]} @@ -307,10 +292,9 @@ update_own_raw () { } ## 调用用户自定义的extra.sh -run_extra_shell () { +run_extra_shell() { if [[ ${EnableExtraShell} == true ]]; then - if [ -f $file_extra_shell ] - then + if [ -f $file_extra_shell ]; then echo -e "--------------------------------------------------------------\n" . $file_extra_shell else @@ -320,17 +304,17 @@ run_extra_shell () { } ## 脚本用法 -usage () { +usage() { echo -e "本脚本用法:" - echo -e "1. $cmd_update all # 更新qinglong、所有你设置的仓库和raw文件,如果启用了EnableExtraShell还将在最后运行你自己编写的extra.sh" - echo -e "2. $cmd_update ql # 只更新qinglong,和输入 $cmd_update qinglong 时功能一样,不会运行extra.sh" + echo -e "2. $cmd_update update # 只更新qinglong,不会运行extra.sh" + echo -e "2. $cmd_update rebuild # 重新编译qinglong,不会运行extra.sh" echo -e "3. $cmd_update raw # 只更新raw文件,不会运行extra.sh" echo -e "4. $cmd_update repo # 更新所有设置的REPO,不会运行extra.sh" echo -e "5. $cmd_update # 指定scripts脚本目录下某个文件夹名称,只更新这个文件夹中的脚本,当该文件夹已经存在并且是git仓库才可使用此命令,不会运行extra.sh" } ## 更新qinglong -update_qinglong () { +update_qinglong() { echo -e "--------------------------------------------------------------\n" git_pull_scripts $dir_root if [[ $exit_status -eq 0 ]]; then @@ -345,79 +329,104 @@ update_qinglong () { fi } -## 更新所有脚本 -update_all_scripts () { - count_own_repo_sum - gen_own_dir_and_path - if [[ ${#array_own_scripts_path[*]} -gt 0 ]]; then - update_own_repo - update_own_raw - gen_list_own - diff_cron $list_own_scripts $list_own_user $list_own_add $list_own_drop +## 重新编译qinglong +rebuild_qinglong() { + echo -e "--------------------------------------------------------------\n" + 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" - if [ -s $list_own_drop ]; then - output_list_add_drop $list_own_drop "失效" - [[ ${AutoDelCron} == true ]] && del_cron $list_own_drop - fi - if [ -s $list_own_add ]; then - output_list_add_drop $list_own_add "新" - if [[ ${AutoAddCron} == true ]]; then - add_cron $list_own_add - fi + echo -e "重启青龙...\n" + pm2 restart panel 2>/dev/null || pm2 start $dir_root/build/app.js -n panel + nginx -s reload + echo -e "重启青龙完成...\n" + fi +} + +## 对比脚本 +diff_scripts() { + gen_list_repo $1 $2 $3 $4 + 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 "失效" + [[ ${AutoDelCron} == true ]] && del_cron $list_own_drop + fi + if [ -s $list_own_add ]; then + output_list_add_drop $list_own_add "新" + if [[ ${AutoAddCron} == true ]]; then + add_cron $list_own_add fi fi } -## 更新指定仓库 -update_specify_scripts_repo () { - local tmp_dir=$1 - if [ -d $dir_scripts/$tmp_dir ]; then - if [ -d $dir_scripts/$tmp_dir/.git ]; then - git_pull_scripts $dir_scripts/$tmp_dir - else - echo -e "$dir_scripts/$tmp_dir 不是一个git仓库...\n" - fi - else - echo -e "$dir_scripts/$tmp_dir 还不存在,可能是还没有clone?\n" - usage +## 生成脚本的路径清单文件 +gen_list_repo() { + local dir_current=$(pwd) + local repo_path="$1" + local author="$2" + local path="$3" + local blackword="$4" + # rm -f $dir_list_tmp/own*.list >/dev/null 2>&1 + + cd ${repo_path} + files=$(find . -name "*.js") + if [ $path ]; then + files=$(find . -name "*.js" | egrep $path) fi + if [ $blackword ]; then + files=$(find . -name "*.js" | egrep -v $blackword | egrep $path) + fi + for file in ${files}; do + if [ -f $file ]; then + # base=$(basename $file) + # echo $base | head -1 >>$list_own_scripts + perl -ne "{ + print if /.*([\d\*]*[\*-\/,\d]*[\d\*] ){4}[\d\*]*[\*-\/,\d]*[\d\*]( |,|\").*\/?$file/ + }" $file | perl -pe "{ + s|.*(([\d\*]*[\*-\/,\d]*[\d\*] ){4}[\d\*]*[\*-\/,\d]*[\d\*])( \|,\|\").*/?$file.*|${repo_path}/$file|g; + s|$dir_scripts/|| + }" | head -1 >> $list_own_scripts + fi + done + grep -E "$cmd_task $author" $list_crontab_user | perl -pe "s|.*ID=(.*) $cmd_task ($author_.*)\.*|\2|" | sort -u >$list_own_user + cd $dir_current } -main () { +main() { local p1=$1 + local p2=$2 + local p3=$3 + local p4=$4 log_time=$(date "+%Y-%m-%d-%H-%M-%S") log_path="$dir_log/update/${log_time}_$p1.log" make_dir "$dir_log/update" - if [[ $# -ne 1 ]]; then + case $p1 in + update) + update_qinglong | tee $log_path + run_extra_shell | tee -a $log_path + ;; + rebuild) + rebuild_qinglong | tee $log_path + ;; + repo) + update_repo "$p2" "$p3" "$p4" | tee $log_path + ;; + raw) + update_raw | tee $log_path + ;; + *) echo -e "命令输入错误...\n" usage - else - case $p1 in - all) - update_qinglong | tee $log_path - update_all_scripts | tee -a $log_path - run_extra_shell | tee -a $log_path - ;; - ql | qinglong) - update_qinglong | tee $log_path - ;; - repo) - count_own_repo_sum - gen_own_dir_and_path - update_own_repo | tee $log_path - ;; - raw) - count_own_repo_sum - gen_own_dir_and_path - update_own_raw | tee $log_path - ;; - *) - update_specify_scripts_repo "$p1" | tee $log_path - ;; - esac - fi + ;; + esac } main "$@" -exit 0 \ No newline at end of file +exit 0