-
-
Save galenzhao/6d879ac220c83ea2dcd309fe9ecab137 to your computer and use it in GitHub Desktop.
backup
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
京东多合一签到,自用,可N个京东账号 | |
活动入口:各处的签到汇总 | |
Node.JS专用 | |
IOS软件用户请使用 https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js | |
更新时间:2021-8-18 | |
推送通知默认简洁模式(多账号只发送一次)。如需详细通知,设置环境变量 JD_BEAN_SIGN_NOTIFY_SIMPLE 为false即可(N账号推送N次通知)。 | |
Modified From github https://github.com/ruicky/jd_sign_bot | |
*/ | |
const $ = new Env('京东多合一签到'); | |
const notify = $.isNode() ? require('./sendNotify') : ''; | |
//Node.js用户请在jdCookie.js处填写京东ck; | |
const jdCookieNode = $.isNode() ? require('./jdCookie.js') : ''; | |
const exec = require('child_process').execSync | |
const fs = require('fs') | |
const download = require('download'); | |
let resultPath = "./result.txt"; | |
let JD_DailyBonusPath = "./JD_DailyBonus.js"; | |
let outPutUrl = './'; | |
let NodeSet = 'CookieSet.json'; | |
let cookiesArr = [], cookie = '', allMessage = ''; | |
if ($.isNode()) { | |
Object.keys(jdCookieNode).forEach((item) => { | |
cookiesArr.push(jdCookieNode[item]) | |
}) | |
if (process.env.JD_DEBUG && process.env.JD_DEBUG === 'false') console.log = () => {}; | |
} | |
!(async() => { | |
if (!cookiesArr[0]) { | |
$.msg($.name, '【提示】请先获取cookie\n直接使用NobyDa的京东签到获取', 'https://bean.m.jd.com/bean/signIndex.action', {"open-url": "https://bean.m.jd.com/bean/signIndex.action"}); | |
return; | |
} | |
process.env.JD_BEAN_SIGN_NOTIFY_SIMPLE = process.env.JD_BEAN_SIGN_NOTIFY_SIMPLE ? process.env.JD_BEAN_SIGN_NOTIFY_SIMPLE : 'true'; | |
await requireConfig(); | |
// 下载最新代码 | |
await downFile(); | |
if (!await fs.existsSync(JD_DailyBonusPath)) { | |
console.log(`\nJD_DailyBonus.js 文件不存在,停止执行${$.name}\n`); | |
await notify.sendNotify($.name, `本次执行${$.name}失败,JD_DailyBonus.js 文件下载异常,详情请查看日志`) | |
return | |
} | |
const content = await fs.readFileSync(JD_DailyBonusPath, 'utf8') | |
for (let i =0; i < cookiesArr.length; i++) { | |
cookie = cookiesArr[i]; | |
if (cookie) { | |
$.UserName = decodeURIComponent(cookie.match(/pt_pin=([^; ]+)(?=;?)/) && cookie.match(/pt_pin=([^; ]+)(?=;?)/)[1]) | |
$.index = i + 1; | |
$.nickName = ''; | |
$.isLogin = true; | |
await TotalBean(); | |
console.log(`*****************开始京东账号${$.index} ${$.nickName || $.UserName} ${$.name}*******************\n`); | |
if (!$.isLogin) { | |
$.msg($.name, `【提示】cookie已失效`, `京东账号${$.index} ${$.nickName || $.UserName}\n请重新登录获取\nhttps://bean.m.jd.com/bean/signIndex.action`, {"open-url": "https://bean.m.jd.com/bean/signIndex.action"}); | |
if ($.isNode()) { | |
await notify.sendNotify(`${$.name}cookie已失效 - ${$.UserName}`, `京东账号${$.index} ${$.UserName}\n请重新登录获取cookie`); | |
} | |
continue | |
} | |
await changeFile(content); | |
await execSign(); | |
} | |
} | |
//await deleteFile(JD_DailyBonusPath);//删除下载的JD_DailyBonus.js文件 | |
if ($.isNode() && allMessage && process.env.JD_BEAN_SIGN_NOTIFY_SIMPLE === 'true') { | |
$.msg($.name, '', allMessage); | |
await notify.sendNotify($.name, allMessage) | |
} | |
})() | |
.catch((e) => $.logErr(e)) | |
.finally(() => $.done()) | |
async function execSign() { | |
console.log(`\n开始执行 ${$.name} 签到,请稍等...\n`); | |
try { | |
// if (notify.SCKEY || notify.BARK_PUSH || notify.DD_BOT_TOKEN || (notify.TG_BOT_TOKEN && notify.TG_USER_ID) || notify.IGOT_PUSH_KEY || notify.QQ_SKEY) { | |
// await exec(`${process.execPath} ${JD_DailyBonusPath} >> ${resultPath}`); | |
// const notifyContent = await fs.readFileSync(resultPath, "utf8"); | |
// console.log(`👇👇👇👇👇👇👇👇👇👇👇LOG记录👇👇👇👇👇👇👇👇👇👇👇\n${notifyContent}\n👆👆👆👆👆👆👆👆👆LOG记录👆👆👆👆👆👆👆👆👆👆👆`); | |
// } else { | |
// console.log('没有提供通知推送,则打印脚本执行日志') | |
// await exec(`${process.execPath} ${JD_DailyBonusPath}`, { stdio: "inherit" }); | |
// } | |
await exec(`${process.execPath} ${JD_DailyBonusPath} >> ${resultPath}`); | |
const notifyContent = await fs.readFileSync(resultPath, "utf8"); | |
console.log(`👇👇👇👇👇👇👇👇👇👇👇签到详情👇👇👇👇👇👇👇👇👇👇👇\n${notifyContent}\n👆👆👆👆👆👆👆👆👆签到详情👆👆👆👆👆👆👆👆👆👆👆`); | |
// await exec("node JD_DailyBonus.js", { stdio: "inherit" }); | |
// console.log('执行完毕', new Date(new Date().getTime() + 8 * 3600000).toLocaleDateString()) | |
//发送通知 | |
let BarkContent = ''; | |
if (fs.existsSync(resultPath)) { | |
const barkContentStart = notifyContent.indexOf('【签到概览】') | |
const barkContentEnd = notifyContent.length; | |
if (process.env.JD_BEAN_SIGN_STOP_NOTIFY !== 'true') { | |
if (process.env.JD_BEAN_SIGN_NOTIFY_SIMPLE === 'true') { | |
if (barkContentStart > -1 && barkContentEnd > -1) { | |
BarkContent = notifyContent.substring(barkContentStart, barkContentEnd); | |
} | |
BarkContent = BarkContent.split('\n\n')[0]; | |
} else { | |
if (barkContentStart > -1 && barkContentEnd > -1) { | |
BarkContent = notifyContent.substring(barkContentStart, barkContentEnd); | |
} | |
} | |
} | |
} | |
//不管哪个时区,这里得到的都是北京时间的时间戳; | |
const UTC8 = new Date().getTime() + new Date().getTimezoneOffset()*60000 + 28800000; | |
$.beanSignTime = new Date(UTC8).toLocaleString('zh', {hour12: false}); | |
//console.log(`脚本执行完毕时间:${$.beanSignTime}`) | |
if (BarkContent) { | |
allMessage += `【京东号 ${$.index}】: ${$.nickName || $.UserName}\n【签到时间】: ${$.beanSignTime}\n${BarkContent}${$.index !== cookiesArr.length ? '\n\n' : ''}`; | |
if (!process.env.JD_BEAN_SIGN_NOTIFY_SIMPLE || (process.env.JD_BEAN_SIGN_NOTIFY_SIMPLE && process.env.JD_BEAN_SIGN_NOTIFY_SIMPLE !== 'true')) { | |
await notify.sendNotify(`${$.name} - 账号${$.index} - ${$.nickName || $.UserName}`, `【签到号 ${$.index}】: ${$.nickName || $.UserName}\n【签到时间】: ${$.beanSignTime}\n${BarkContent}`); | |
} | |
} | |
//运行完成后,删除下载的文件 | |
await Promise.all([ | |
deleteFile(resultPath),//删除result.txt | |
deleteFile(NodeSet),//删除CookieSet.json | |
]) | |
console.log(`\n\n*****************${new Date(new Date().getTime()).toLocaleString('zh', {hour12: false})} 京东账号${$.index} ${$.nickName || $.UserName} ${$.name}完成*******************\n\n`); | |
} catch (e) { | |
console.log("京东签到脚本执行异常:" + e); | |
} | |
} | |
async function downFile () { | |
let url = ''; | |
await downloadUrl(); | |
if ($.body) { | |
url = 'https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js'; | |
} else { | |
url = 'https://cdn.jsdelivr.net/gh/NobyDa/Script@master/JD-DailyBonus/JD_DailyBonus.js'; | |
} | |
try { | |
const options = { } | |
if (process.env.TG_PROXY_HOST && process.env.TG_PROXY_PORT) { | |
url = 'https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js'; | |
const tunnel = require("tunnel"); | |
const agent = { | |
https: tunnel.httpsOverHttp({ | |
proxy: { | |
host: process.env.TG_PROXY_HOST, | |
port: process.env.TG_PROXY_PORT * 1 | |
} | |
}) | |
} | |
Object.assign(options, { agent }) | |
} | |
await download(url, outPutUrl, options); | |
console.log(`JD_DailyBonus.js文件下载完毕\n\n`); | |
} catch (e) { | |
console.log("JD_DailyBonus.js 文件下载异常:" + e); | |
} | |
} | |
async function changeFile (content) { | |
console.log(`开始替换变量`) | |
// let newContent = content.replace(/var OtherKey = `.*`/, "var OtherKey = " + "`[{\"cookie\":\"" + cookie+ "\"}]`"); | |
let newContent = content.replace(/var OtherKey = `.*`/, `var OtherKey = \`[{"cookie":"${cookie}"}]\``); | |
newContent = newContent.replace(/const NodeSet = 'CookieSet.json'/, `const NodeSet = '${NodeSet}'`) | |
if (process.env.JD_BEAN_STOP && process.env.JD_BEAN_STOP !== '0') { | |
newContent = newContent.replace(/var stop = '0'/, `var stop = '${process.env.JD_BEAN_STOP}'`); | |
} | |
const zone = new Date().getTimezoneOffset(); | |
if (zone === 0) { | |
//此处针对UTC-0时区用户做的 | |
newContent = newContent.replace(/tm\s=.*/, `tm = new Date(new Date().toLocaleDateString()).getTime() - 28800000;`); | |
} | |
try { | |
await fs.writeFileSync(JD_DailyBonusPath, newContent, 'utf8'); | |
console.log('替换变量完毕'); | |
} catch (e) { | |
console.log("京东签到写入文件异常:" + e); | |
} | |
} | |
async function deleteFile(path) { | |
// 查看文件result.txt是否存在,如果存在,先删除 | |
const fileExists = await fs.existsSync(path); | |
// console.log('fileExists', fileExists); | |
if (fileExists) { | |
const unlinkRes = await fs.unlinkSync(path); | |
// console.log('unlinkRes', unlinkRes) | |
} | |
} | |
function TotalBean() { | |
return new Promise(async resolve => { | |
const options = { | |
"url": `https://wq.jd.com/user/info/QueryJDUserInfo?sceneval=2`, | |
"headers": { | |
"Accept": "application/json,text/plain, */*", | |
"Content-Type": "application/x-www-form-urlencoded", | |
"Accept-Encoding": "gzip, deflate, br", | |
"Accept-Language": "zh-cn", | |
"Connection": "keep-alive", | |
"Cookie": cookie, | |
"Referer": "https://wqs.jd.com/my/jingdou/my.shtml?sceneval=2", | |
"User-Agent": $.isNode() ? (process.env.JD_USER_AGENT ? process.env.JD_USER_AGENT : (require('./USER_AGENTS').USER_AGENT)) : ($.getdata('JDUA') ? $.getdata('JDUA') : "jdapp;iPhone;9.4.4;14.3;network/4g;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1") | |
}, | |
"timeout": 10000 | |
} | |
$.post(options, (err, resp, data) => { | |
try { | |
if (err) { | |
console.log(`${JSON.stringify(err)}`) | |
console.log(`${$.name} API请求失败,请检查网路重试`) | |
} else { | |
if (data) { | |
data = JSON.parse(data); | |
if (data['retcode'] === 13) { | |
$.isLogin = false; //cookie过期 | |
return | |
} | |
if (data['retcode'] === 0) { | |
$.nickName = (data['base'] && data['base'].nickname) || $.UserName; | |
} else { | |
$.nickName = $.UserName | |
} | |
} else { | |
console.log(`京东服务器返回空数据`) | |
} | |
} | |
} catch (e) { | |
$.logErr(e, resp) | |
} finally { | |
resolve(); | |
} | |
}) | |
}) | |
} | |
function downloadUrl(url = 'https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js') { | |
return new Promise(resolve => { | |
const options = { url, "timeout": 10000 }; | |
if ($.isNode() && process.env.TG_PROXY_HOST && process.env.TG_PROXY_PORT) { | |
const tunnel = require("tunnel"); | |
const agent = { | |
https: tunnel.httpsOverHttp({ | |
proxy: { | |
host: process.env.TG_PROXY_HOST, | |
port: process.env.TG_PROXY_PORT * 1 | |
} | |
}) | |
} | |
Object.assign(options, { agent }) | |
} | |
$.get(options, async (err, resp, data) => { | |
try { | |
if (err) { | |
// console.log(`${JSON.stringify(err)}`) | |
console.log(`检测到您当前网络环境不能访问外网,将使用jsdelivr CDN下载JD_DailyBonus.js文件`); | |
await $.http.get({url: `https://purge.jsdelivr.net/gh/NobyDa/Script@master/JD-DailyBonus/JD_DailyBonus.js`, timeout: 10000}).then((resp) => { | |
if (resp.statusCode === 200) { | |
let { body } = resp; | |
body = JSON.parse(body); | |
if (body['success']) { | |
console.log(`JD_DailyBonus.js文件 CDN刷新成功`) | |
} else { | |
console.log(`JD_DailyBonus.js文件 CDN刷新失败`) | |
} | |
} | |
}); | |
} else { | |
$.body = data; | |
} | |
} catch (e) { | |
$.logErr(e, resp) | |
} finally { | |
resolve(); | |
} | |
}) | |
}) | |
} | |
function requireConfig() { | |
return new Promise(resolve => { | |
// const file = 'jd_bean_sign.js'; | |
// fs.access(file, fs.constants.W_OK, (err) => { | |
// resultPath = err ? '/tmp/result.txt' : resultPath; | |
// JD_DailyBonusPath = err ? '/tmp/JD_DailyBonus.js' : JD_DailyBonusPath; | |
// outPutUrl = err ? '/tmp/' : outPutUrl; | |
// NodeSet = err ? '/tmp/CookieSet.json' : NodeSet; | |
// resolve() | |
// }); | |
//判断是否是云函数环境。原函数跟目录目录没有可写入权限,文件只能放到根目录下虚拟的/temp/文件夹(具有可写入权限) | |
resultPath = process.env.TENCENTCLOUD_RUNENV === 'SCF' ? '/tmp/result.txt' : resultPath; | |
JD_DailyBonusPath = process.env.TENCENTCLOUD_RUNENV === 'SCF' ? '/tmp/JD_DailyBonus.js' : JD_DailyBonusPath; | |
outPutUrl = process.env.TENCENTCLOUD_RUNENV === 'SCF' ? '/tmp/' : outPutUrl; | |
NodeSet = process.env.TENCENTCLOUD_RUNENV === 'SCF' ? '/tmp/CookieSet.json' : NodeSet; | |
resolve() | |
}) | |
} | |
function timeFormat(time) { | |
let date; | |
if (time) { | |
date = new Date(time) | |
} else { | |
date = new Date(); | |
} | |
return date.getFullYear() + '-' + ((date.getMonth() + 1) >= 10 ? (date.getMonth() + 1) : '0' + (date.getMonth() + 1)) + '-' + (date.getDate() >= 10 ? date.getDate() : '0' + date.getDate()); | |
} | |
function Env(t,e){"undefined"!=typeof process&&JSON.stringify(process.env).indexOf("GITHUB")>-1&&process.exit(0);class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}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}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),n={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(n,(t,e,i)=>s(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),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;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),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}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,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||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,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============📣系统通知📣=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`❗️${this.name}, 错误!`,t.stack):this.log("",`❗️${this.name}, 错误!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`🔔${this.name}, 结束! 🕛 ${s} 秒`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Last Modified time: 2021-9-28 17:42:54 | |
*/ | |
/** | |
* sendNotify 推送通知功能 | |
* @param text 通知头 | |
* @param desp 通知体 | |
* @param params 某些推送通知方式点击弹窗可跳转, 例:{ url: 'https://abc.com' } | |
* @param author 作者仓库等信息 例:`本脚本免费使用 By:xxx` | |
* @returns {Promise<unknown>} | |
*/ | |
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 = ''; | |
//BARK v1.1.5版本的BARK 支持分组功能,可在历史消息中分组查看消息,默认'京东' | |
let BARK_GROUP = '京东'; | |
// =======================================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) | |
企业微信应用消息通知已实现一对一推送:(第一个微信ID可为@all,也可为具体某个人的微信ID,例3情况则发送到第一个微信ID,如果有不想发送通知的账号,可设置为@N) | |
1、@ll|账号1|账号2|@N|账号4(配置说明:例3情况发送给@all,账号1发送给配置的微信ID1,账号2发送给配置的微信ID2,@N则表示不给账号3推送,账号4发送给配置的微信ID4) | |
2、如果只配置了一个微信ID,则把全部消息发送给这个已配置的微信ID | |
3、如果账号数量比已配置的微信ID数量要多,则超出的账号消息合并到一块,再一次性发送给第一个配置的微信ID | |
*/ | |
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}` | |
} | |
} 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.BARK_SOUND) { | |
BARK_SOUND = process.env.BARK_SOUND | |
} | |
if (process.env.BARK_GROUP) { | |
BARK_GROUP = process.env.BARK_GROUP; | |
} | |
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:xxxx` | |
* @returns {Promise<unknown>} | |
*/ | |
async function sendNotify(text, desp, params = {}, author = '') { | |
//提供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酷推 | |
]) | |
let despArr = desp.split('\n\n'); | |
let str = '', arr = []; | |
for (let i = 0; i < despArr.length; i++) { | |
if (i + 1 === despArr.length) { | |
str += despArr[i] | |
} else { | |
str += despArr[i] + '\n\n' | |
} | |
if (str.length >= 3000) { | |
if (str.lastIndexOf('\n\n') > -1) str = str.substring(0, str.length - 2); | |
arr.push(str); | |
str = ''; | |
continue | |
} | |
if (i + 1 === despArr.length) { | |
arr.push(str); | |
str = ''; | |
} | |
} | |
if (arr.length > 1) console.log(`tg bot 机器人拆分${arr.length}次发送\n`) | |
let promiseArr = arr.filter(item => !!item).map(des => tgBotNotify(text, des)); | |
await Promise.all(promiseArr); | |
str = '', arr = []; | |
for (let i = 0; i < despArr.length; i++) { | |
if (i + 1 === despArr.length) { | |
str += despArr[i] | |
} else { | |
str += despArr[i] + '\n\n' | |
} | |
if (str.length >= 500) { | |
if (str.lastIndexOf('\n\n') > -1) str = str.substring(0, str.length - 2); | |
arr.push(str); | |
str = ''; | |
continue | |
} | |
if (i + 1 === despArr.length) { | |
arr.push(str); | |
str = ''; | |
} | |
} | |
if (arr.length > 1) console.log(`BARK APP 将拆分${arr.length}次发送\n`) | |
promiseArr = arr.filter(item => !!item).map(des => BarkNotify(text, des, params)); | |
await Promise.all(promiseArr); | |
} | |
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}&group=${BARK_GROUP}&${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 isBlank(str) { | |
str = str.replace(/\ +/g, ""); | |
str = str.replace(/[ ]/g, ""); | |
str = str.replace(/[\r\n]/g, ""); | |
return !Boolean(str); | |
} | |
async function qywxamNotify(text, desp) { | |
if (!QYWX_AM) return; | |
const [corpid, corpsecret, userIds, agentid, thumb_media_id] = QYWX_AM.split(","); | |
const despTmp = desp.split("\n\n").filter(item => !!item); | |
const userIdsTmp = userIds.split("|"); | |
const accIdxRE = /\d+/; | |
let accIdx, userId, remainDes = []; | |
for (let i = 0; i < despTmp.length; i++) { | |
if (despTmp[i].match(accIdxRE) && despTmp[i].indexOf('账号') > -1) { | |
accIdx = parseInt(despTmp[i].match(accIdxRE)[0]); | |
if (userIdsTmp.length === 1) { | |
//如果只配置了一个微信ID,则把已经拆分的消息合并起来再一次性发送给这个已配置的微信ID | |
accIdx = 0; | |
remainDes.push(despTmp[i]); | |
continue; | |
} | |
userId = userIdsTmp[accIdx]; | |
if (typeof userId == "undefined") { | |
//如果账号数量比配置的微信ID数量要多,则超出的账号消息合并到一块,再一次性发送给第一个配置的微信ID | |
remainDes.push(despTmp[i]); | |
} else if (userId === "@N") { | |
console.log("\n账户" + despTmp[i].match(accIdxRE)[0] + " 企业微信应用通知配置ID为@N,跳过通知\n"); | |
} else if (!!userId) { | |
//账号与对应微信userId存在 | |
await qywxamSplitNotify(text, despTmp[i], userIdsTmp[accIdx]); | |
} | |
} else if (!isBlank(despTmp[i])) { | |
await qywxamSplitNotify(text, despTmp[i], userIdsTmp[0]); | |
} | |
} | |
if (remainDes && remainDes.length) { | |
let str = ''; | |
for (let i = 0; i < remainDes.length; i++) { | |
if (i + 1 === remainDes.length) { | |
str += remainDes[i] | |
} else { | |
str += remainDes[i] + '\n\n' | |
} | |
} | |
await qywxamSplitNotify(text, str, userIdsTmp[0]); | |
} | |
} | |
function qywxamSplitNotify(text, desp, userId = '@all') { | |
return new Promise(resolve => { | |
if (QYWX_AM) { | |
// const QYWX_AM_AY = QYWX_AM.split(','); | |
const [corpid, corpsecret, userIds, agentid, thumb_media_id] = QYWX_AM.split(','); | |
const options_accesstoken = { | |
url: `https://qyapi.weixin.qq.com/cgi-bin/gettoken`, | |
json: { | |
corpid, | |
corpsecret, | |
}, | |
headers: { | |
'Content-Type': 'application/json', | |
}, | |
timeout | |
}; | |
$.post(options_accesstoken, (err, resp, data) => { | |
html = desp.replace(/\n/g, "<br/>") | |
var json = JSON.parse(data); | |
accesstoken = json.access_token; | |
let options; | |
switch (thumb_media_id) { | |
case '0': | |
options = { | |
msgtype: 'textcard', | |
textcard: { | |
title: `${text}`, | |
description: `${desp}`, | |
url: '', | |
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, | |
author: `智能助手`, | |
content_source_url: ``, | |
content: `${html}`, | |
digest: `${desp}` | |
} | |
] | |
} | |
} | |
}; | |
if (!thumb_media_id) { | |
//如不提供第四个参数,则默认进行文本消息类型推送 | |
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: `${userId}`, | |
agentid: agentid, | |
safe: '0', | |
...options | |
}, | |
headers: { | |
'Content-Type': 'application/json', | |
}, | |
} | |
$.post(options, (err, resp, data) => { | |
try { | |
if (err) { | |
console.log('\n成员ID:' + userId + ' 企业微信应用消息发送通知消息失败!!\n'); | |
console.log(err); | |
} else { | |
data = JSON.parse(data); | |
if (data.errcode === 0) { | |
console.log('\n成员ID:' + userId + ' 企业微信应用消息发送通知消息成功🎉。\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, '<br>'); // 默认为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)} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const USER_AGENTS = [] | |
/** | |
* 生成随机数字 | |
* @param {number} min 最小值(包含) | |
* @param {number} max 最大值(不包含) | |
*/ | |
function randomNumber(min = 0, max = 100) { | |
return Math.min(Math.floor(min + Math.random() * (max - min)), max); | |
} | |
/** | |
* 得到一个两数之间的随机整数,包括两个数在内 | |
* @param min | |
* @param max | |
* @returns {number} | |
*/ | |
function getRandomIntInclusive(min, max) { | |
min = Math.ceil(min); | |
max = Math.floor(max); | |
return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值 | |
} | |
/** | |
* 生成随机 iPhoneID | |
* @returns {string} | |
*/ | |
function randPhoneId() { | |
return Math.random().toString(36).slice(2, 10) + | |
Math.random().toString(36).slice(2, 10) + | |
Math.random().toString(36).slice(2, 10) + | |
Math.random().toString(36).slice(2, 10) + | |
Math.random().toString(36).slice(2, 10); | |
} | |
const USER_AGENT = `jdapp;iPhone;10.1.2;${Math.ceil(Math.random()*4+10)}.${Math.ceil(Math.random()*4)};${randPhoneId()};network/4g;model/iPhone11,8;addressid/1188016812;appBuild/167724;jdSupportDarkMode/0;Mozilla/5.0 (iPhone; CPU iPhone OS ${getRandomIntInclusive(11, 14)}_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1`; | |
module.exports = { | |
USER_AGENT | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment