918 lines
84 KiB
JavaScript
918 lines
84 KiB
JavaScript
|
/*
|
|||
|
cron 14 10 * * * https://raw.githubusercontent.com/smiek2121/scripts/master/jd_sign_graphics.js
|
|||
|
|
|||
|
*/
|
|||
|
|
|||
|
// const Faker=require('./sign_graphics_validate.js');
|
|||
|
|
|||
|
const $ = new Env('京东签到图形验证');
|
|||
|
const notify = $.isNode() ? require('./sendNotify') : '';
|
|||
|
//Node.js用户请在jdCookie.js处填写京东ck;
|
|||
|
const jdCookieNode = $.isNode() ? require('./jdCookie.js') : '';
|
|||
|
CryptoScripts()
|
|||
|
$.CryptoJS = $.isNode() ? require('crypto-js') : CryptoJS;
|
|||
|
let cookiesArr = [], cookie = '';
|
|||
|
|
|||
|
const validatorCount = process.env.JDJR_validator_Count ? process.env.JDJR_validator_Count : 100
|
|||
|
const PNG = require('png-js');
|
|||
|
const https = require('https');
|
|||
|
const stream = require('stream');
|
|||
|
const zlib = require('zlib');
|
|||
|
const vm = require('vm');
|
|||
|
|
|||
|
let message = '', subTitle = '', beanNum = 0;
|
|||
|
let fp = ''
|
|||
|
let eid = ''
|
|||
|
let signFlag = false
|
|||
|
let successNum = 0
|
|||
|
let errorNum = 0
|
|||
|
let JD_API_HOST = 'https://jdjoy.jd.com'
|
|||
|
$.invokeKey = "q8DNJdpcfRQ69gIx"
|
|||
|
$.invokeKey = $.isNode() ? (process.env.JD_invokeKey ? process.env.JD_invokeKey : `${$.invokeKey}`) : ($.getdata('JD_invokeKey') ? $.getdata('JD_invokeKey') : `${$.invokeKey}`);
|
|||
|
let lkt = 0
|
|||
|
|
|||
|
if ($.isNode()) {
|
|||
|
if(process.env.JOY_HOST){
|
|||
|
JD_API_HOST = process.env.JOY_HOST
|
|||
|
}
|
|||
|
Object.keys(jdCookieNode).forEach((item) => {
|
|||
|
cookiesArr.push(jdCookieNode[item])
|
|||
|
})
|
|||
|
if (process.env.JD_DEBUG && process.env.JD_DEBUG === 'false') console.log = () => { };
|
|||
|
} else {
|
|||
|
cookiesArr = [$.getdata('CookieJD'), $.getdata('CookieJD2'), ...jsonParse($.getdata('CookiesJD') || "[]").map(item => item.cookie)].filter(item => !!item);
|
|||
|
}
|
|||
|
|
|||
|
const turnTableId = [
|
|||
|
{ "name": "京东商城-健康", "id": 527, "url": "https://prodev.m.jd.com/mall/active/w2oeK5yLdHqHvwef7SMMy4PL8LF/index.html" },
|
|||
|
{ "name": "京东商城-清洁", "id": 446, "url": "https://prodev.m.jd.com/mall/active/2Tjm6ay1ZbZ3v7UbriTj6kHy9dn6/index.html" },
|
|||
|
{ "name": "京东商城-个护", "id": 336, "url": "https://prodev.m.jd.com/mall/active/2tZssTgnQsiUqhmg5ooLSHY9XSeN/index.html" },
|
|||
|
{ "name": "京东商城-母婴", "id": 458, "url": "https://prodev.m.jd.com/mall/active/3BbAVGQPDd6vTyHYjmAutXrKAos6/index.html" },
|
|||
|
{ "name": "京东商城-数码", "id": 347, "url": "https://prodev.m.jd.com/mall/active/4SWjnZSCTHPYjE5T7j35rxxuMTb6/index.html" },
|
|||
|
{ "name": "PLUS会员定制", "id": 1265, "url": "https://prodev.m.jd.com/mall/active/N9MpLQdxZgiczZaMx2SzmSfZSvF/index.html" },
|
|||
|
// { "name": "京东商城-童装", "id": 511, "url": "https://prodev.m.jd.com/mall/active/3Af6mZNcf5m795T8dtDVfDwWVNhJ/index.html" },
|
|||
|
// { "name": "京东商城-内衣", "id": 1071, "url": "https://prodev.m.jd.com/mall/active/4PgpL1xqPSW1sVXCJ3xopDbB1f69/index.html" },
|
|||
|
// { "name": "京东超市", "id": 1204, "url": "https://pro.m.jd.com/mall/active/QPwDgLSops2bcsYqQ57hENGrjgj/index.html" },
|
|||
|
]
|
|||
|
|
|||
|
!(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;
|
|||
|
}
|
|||
|
for (let i = 0; i < cookiesArr.length; i++) {
|
|||
|
if (cookiesArr[i]) {
|
|||
|
cookie = cookiesArr[i];
|
|||
|
$.UserName = decodeURIComponent(cookie.match(/pt_pin=(.+?);/) && cookie.match(/pt_pin=(.+?);/)[1])
|
|||
|
$.index = i + 1;
|
|||
|
$.nickName = '';
|
|||
|
console.log(`\n开始【京东账号${$.index}】${$.nickName || $.UserName}\n`);
|
|||
|
beanNum = 0
|
|||
|
successNum = 0
|
|||
|
errorNum = 0
|
|||
|
invalidNum = 0
|
|||
|
subTitle = '';
|
|||
|
lkt = new Date().getTime()
|
|||
|
await getUA()
|
|||
|
await signRun()
|
|||
|
const UTC8 = new Date().getTime() + new Date().getTimezoneOffset()*60000 + 28800000;
|
|||
|
$.beanSignTime = new Date(UTC8).toLocaleString('zh', {hour12: false}).replace(' 24:',' 00:');
|
|||
|
let msg = `【京东账号${$.index}】${$.nickName || $.UserName}\n【签到时间】: ${$.beanSignTime}\n【签到概览】: 成功${successNum}个, 失败${errorNum}个${invalidNum && ",失效"+invalidNum+"个" || ""}\n${beanNum > 0 && "【签到奖励】: "+beanNum+"京豆\n" || ""}`
|
|||
|
message += msg + '\n'
|
|||
|
if($.isNode()) $.msg($.name, msg);
|
|||
|
}
|
|||
|
}
|
|||
|
await showMsg();
|
|||
|
})()
|
|||
|
.catch((e) => {
|
|||
|
$.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '')
|
|||
|
})
|
|||
|
.finally(() => {
|
|||
|
$.done();
|
|||
|
})
|
|||
|
|
|||
|
async function showMsg() {
|
|||
|
$.msg($.name, `【签到数量】: ${turnTableId.length}个\n` + subTitle + message);
|
|||
|
if ($.isNode() && message) await notify.sendNotify(`${$.name}`, `【签到数量】: ${turnTableId.length}个\n` + subTitle + message);
|
|||
|
}
|
|||
|
async function signRun() {
|
|||
|
for (let i in turnTableId) {
|
|||
|
$.validatorUrl = turnTableId[i].url || ''
|
|||
|
signFlag = 0
|
|||
|
await Login(i)
|
|||
|
if(signFlag == 1){
|
|||
|
successNum++;
|
|||
|
}else if(signFlag == 2){
|
|||
|
invalidNum++;
|
|||
|
}else{
|
|||
|
errorNum++;
|
|||
|
}
|
|||
|
let time = Math.random() * 2000 + 2000
|
|||
|
console.log(`等待${(time/1000).toFixed(3)}秒`)
|
|||
|
await $.wait(parseInt(time, 10))
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function Login(i) {
|
|||
|
return new Promise(async resolve => {
|
|||
|
$.appId = '9a4de';
|
|||
|
await requestAlgo();
|
|||
|
$.get(taskUrl(turnTableId[i].id), async (err, resp, data) => {
|
|||
|
try {
|
|||
|
if (err) {
|
|||
|
console.log(`\n${turnTableId[i].name} 登录: API查询请求失败 ‼️‼️`)
|
|||
|
console.log(`${JSON.stringify(err)}`)
|
|||
|
} else {
|
|||
|
if (data) {
|
|||
|
// console.log(data)
|
|||
|
data = JSON.parse(data);
|
|||
|
if (data.success && data.data) {
|
|||
|
data = data.data
|
|||
|
if (data.hasSign === false) {
|
|||
|
// let arr = await Faker.getBody($.UA,turnTableId[i].url)
|
|||
|
// fp = arr.fp
|
|||
|
// await getEid(arr)
|
|||
|
$.appId = 'b342e';
|
|||
|
await requestAlgo();
|
|||
|
await Sign(i,1)
|
|||
|
// console.log("验证码:"+$.validate)
|
|||
|
if($.validate){
|
|||
|
if($.validatorTime < 33){
|
|||
|
let time = Math.random() * 5000 + 33000 - $.validatorTime*1000
|
|||
|
console.log(`等待${(time/1000).toFixed(3)}秒`)
|
|||
|
await $.wait(parseInt(time, 10))
|
|||
|
}
|
|||
|
await Sign(i,3)
|
|||
|
}
|
|||
|
let time = Math.random() * 5000 + 32000
|
|||
|
console.log(`等待${(time/1000).toFixed(3)}秒`)
|
|||
|
await $.wait(parseInt(time, 10))
|
|||
|
} else if (data.hasSign === true) {
|
|||
|
if(data.records && data.records[0]){
|
|||
|
for(let i in data.records){
|
|||
|
let item = data.records[i]
|
|||
|
if((item.hasSign == false && item.index != 1) || i == data.records.length-1){
|
|||
|
if(item.hasSign == false) i = i-1
|
|||
|
// beanNum += Number(data.records[i].beanQuantity)
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
signFlag = 1;
|
|||
|
console.log(`${turnTableId[i].name} 已签到`)
|
|||
|
}else{
|
|||
|
signFlag = 2;
|
|||
|
console.log(`${turnTableId[i].name} 无法签到\n签到地址:${turnTableId[i].url}\n`)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (data.errorMessage) {
|
|||
|
if(data.errorMessage.indexOf('已签到') > -1 || data.errorMessage.indexOf('今天已经签到') > -1){
|
|||
|
signFlag = 1;
|
|||
|
}
|
|||
|
console.log(`${turnTableId[i].name} ${data.errorMessage}`)
|
|||
|
} else {
|
|||
|
console.log(`${turnTableId[i].name} ${JSON.stringify(data)}`)
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
console.log(`京豆api返回数据为空,请检查自身原因`)
|
|||
|
}
|
|||
|
}
|
|||
|
} catch (e) {
|
|||
|
$.logErr(e, resp);
|
|||
|
} finally {
|
|||
|
resolve(data);
|
|||
|
}
|
|||
|
})
|
|||
|
})
|
|||
|
}
|
|||
|
function Sign(i,t) {
|
|||
|
return new Promise(resolve => {
|
|||
|
let options = tasPostkUrl(turnTableId[i].id)
|
|||
|
$.post(options, async (err, resp, data) => {
|
|||
|
try {
|
|||
|
if (err) {
|
|||
|
console.log(`\n${turnTableId[i].name} 签到: API查询请求失败 ‼️‼️`)
|
|||
|
throw new Error(err);
|
|||
|
} else {
|
|||
|
$.validate = ''
|
|||
|
let res = $.toObj(data,data)
|
|||
|
if (typeof res === 'object') {
|
|||
|
if (res.success && res.data) {
|
|||
|
let resData = res.data
|
|||
|
if (Number(resData.jdBeanQuantity) > 0) beanNum += Number(resData.jdBeanQuantity)
|
|||
|
signFlag = true;
|
|||
|
console.log(`${turnTableId[i].name} 签到成功:获得 ${Number(resData.jdBeanQuantity)}京豆`)
|
|||
|
} else {
|
|||
|
if (res.errorMessage) {
|
|||
|
if(res.errorMessage.indexOf('已签到') > -1 || res.errorMessage.indexOf('今天已经签到') > -1){
|
|||
|
signFlag = true;
|
|||
|
}else if(res.errorMessage.indexOf('进行验证') > -1){
|
|||
|
await injectToRequest('channelSign')
|
|||
|
}else if(res.errorMessage.indexOf('火爆') > -1 && t == 2){
|
|||
|
await Sign(i,2)
|
|||
|
}else{
|
|||
|
console.log(`${turnTableId[i].name} ${res.errorMessage}`)
|
|||
|
}
|
|||
|
} else {
|
|||
|
console.log(`${turnTableId[i].name} ${data}`)
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
console.log(`${turnTableId[i].name} ${data}`)
|
|||
|
}
|
|||
|
}
|
|||
|
} catch (e) {
|
|||
|
$.logErr(e, resp);
|
|||
|
} finally {
|
|||
|
resolve(data);
|
|||
|
}
|
|||
|
})
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function getEid(arr) {
|
|||
|
return new Promise(resolve => {
|
|||
|
const options = {
|
|||
|
url: `https://gia.jd.com/fcf.html?a=${arr.a}`,
|
|||
|
body: `d=${arr.d}`,
|
|||
|
headers: {
|
|||
|
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
|
|||
|
"User-Agent": $.UA
|
|||
|
}
|
|||
|
}
|
|||
|
$.post(options, async (err, resp, data) => {
|
|||
|
try {
|
|||
|
if (err) {
|
|||
|
console.log(`\n${turnTableId[i].name} 登录: API查询请求失败 ‼️‼️`)
|
|||
|
throw new Error(err);
|
|||
|
} else {
|
|||
|
if (data.indexOf("*_*") > 0) {
|
|||
|
data = data.split("*_*", 2);
|
|||
|
data = JSON.parse(data[1]);
|
|||
|
eid = data.eid
|
|||
|
} else {
|
|||
|
console.log(`京豆api返回数据为空,请检查自身原因`)
|
|||
|
}
|
|||
|
}
|
|||
|
} catch (e) {
|
|||
|
$.logErr(e, resp);
|
|||
|
} finally {
|
|||
|
resolve(data);
|
|||
|
}
|
|||
|
})
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function taskUrl(turnTableId) {
|
|||
|
let time = Date.now()
|
|||
|
let body = {"turnTableId":`${turnTableId}`}
|
|||
|
let t = [{"key":"appid","value":"jdchoujiang_h5"},{"key":"body","value":$.CryptoJS.SHA256($.toStr(body,body)).toString()},{"key":"client","value":""},{"key":"clientVersion","value":""},{"key":"functionId","value":"turncardChannelDetail"},{"key":"t","value":time}]
|
|||
|
let h5st = geth5st(t) || 'undefined'
|
|||
|
let url = `https://api.m.jd.com/api?client=&clientVersion=&appid=jdchoujiang_h5&t=${time}&functionId=turncardChannelDetail&body=${JSON.stringify(body)}&h5st=${h5st}`
|
|||
|
return {
|
|||
|
url,
|
|||
|
headers: {
|
|||
|
"Accept": "application/json, text/plain, */*",
|
|||
|
"Accept-Encoding": "gzip, deflate, br",
|
|||
|
"Accept-Language": "zh-cn",
|
|||
|
"Connection": "keep-alive",
|
|||
|
'Cookie': cookie,
|
|||
|
"Origin": "https://prodev.m.jd.com",
|
|||
|
"Referer": "https://prodev.m.jd.com/",
|
|||
|
"User-Agent": $.UA,
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
function tasPostkUrl(turnTableId) {
|
|||
|
let time = Date.now()
|
|||
|
let body = {"turnTableId":`${turnTableId}`,"fp":fp,"eid":eid}
|
|||
|
if($.validate){
|
|||
|
body["validate"] = $.validate
|
|||
|
}
|
|||
|
let t = [{"key":"appid","value":"jdchoujiang_h5"},{"key":"body","value":$.CryptoJS.SHA256($.toStr(body,body)).toString()},{"key":"client","value":""},{"key":"clientVersion","value":""},{"key":"functionId","value":"turncardChannelSign"},{"key":"t","value":time}]
|
|||
|
let h5st = geth5st(t) || 'undefined'
|
|||
|
let url = `https://api.m.jd.com/api?client=&clientVersion=&appid=jdchoujiang_h5&functionId=turncardChannelSign&t=${time}&body=${(JSON.stringify(body))}&h5st=${h5st}`
|
|||
|
return {
|
|||
|
url,
|
|||
|
headers: {
|
|||
|
"Accept": "application/json, text/plain, */*",
|
|||
|
"Accept-Encoding": "gzip, deflate, br",
|
|||
|
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
|
|||
|
'Cookie': cookie,
|
|||
|
"Origin": "https://prodev.m.jd.com",
|
|||
|
"Referer": "https://prodev.m.jd.com/",
|
|||
|
"User-Agent": $.UA,
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
async function requestAlgo() {
|
|||
|
var s = "", a = "0123456789", u = a, c = (Math.random() * 10) | 0;
|
|||
|
do{
|
|||
|
ss = getRandomIDPro({ size: 1 ,customDict:a})+""
|
|||
|
if(s.indexOf(ss) == -1) s += ss
|
|||
|
}while (s.length < 3)
|
|||
|
for(let i of s.slice()) u = u.replace(i,'')
|
|||
|
$.fp = getRandomIDPro({size:c, customDict:u})+""+s+getRandomIDPro({size:(14-(c+3))+1, customDict:u})+c+""
|
|||
|
let opts = {
|
|||
|
url: `https://cactus.jd.com/request_algo?g_ty=ajax`,
|
|||
|
headers: {
|
|||
|
'Accept': 'application/json',
|
|||
|
'Content-Type': 'application/json',
|
|||
|
"Accept-Encoding": "gzip, deflate, br",
|
|||
|
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
|
|||
|
'Origin': 'https://prodev.m.jd.com',
|
|||
|
'Referer': 'https://prodev.m.jd.com/',
|
|||
|
'User-Agent': $.UA,
|
|||
|
},
|
|||
|
body: `{"version":"3.0","fp":"${$.fp}","appId":"${$.appId}","timestamp":${Date.now()},"platform":"web","expandParams":""}`
|
|||
|
}
|
|||
|
return new Promise(async resolve => {
|
|||
|
$.post(opts, (err, resp, data) => {
|
|||
|
try {
|
|||
|
const { ret, msg, data: { result } = {} } = JSON.parse(data);
|
|||
|
$.token = result.tk;
|
|||
|
$.genKey = new Function(`return ${result.algo}`)();
|
|||
|
} catch (e) {
|
|||
|
$.logErr(e, resp);
|
|||
|
} finally {
|
|||
|
resolve();
|
|||
|
}
|
|||
|
})
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function getRandomIDPro() {
|
|||
|
var e,
|
|||
|
t,
|
|||
|
a = void 0 === (n = (t = 0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : {}).size) ? 10 : n,
|
|||
|
n = void 0 === (n = t.dictType) ? 'number' : n,
|
|||
|
i = '';
|
|||
|
if ((t = t.customDict) && 'string' == typeof t) e = t;
|
|||
|
else
|
|||
|
switch (n) {
|
|||
|
case 'alphabet':
|
|||
|
e = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|||
|
break;
|
|||
|
case 'max':
|
|||
|
e = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-';
|
|||
|
break;
|
|||
|
case 'number':
|
|||
|
default:
|
|||
|
e = '0123456789';
|
|||
|
}
|
|||
|
|
|||
|
for (; a--;) i += e[(Math.random() * e.length) | 0];
|
|||
|
return i;
|
|||
|
}
|
|||
|
function geth5st(t){
|
|||
|
// return ''
|
|||
|
let a = t.map(function(e) {
|
|||
|
return e["key"] + ":" + e["value"]
|
|||
|
})["join"]("&")
|
|||
|
let time = Date.now()
|
|||
|
let hash1 = ''
|
|||
|
let timestamp = format("yyyyMMddhhmmssSSS", time);
|
|||
|
hash1 = $.genKey($.token, $.fp.toString(), timestamp.toString(), $.appId.toString(), $.CryptoJS).toString();
|
|||
|
const hash2 = $.CryptoJS.HmacSHA256(a, hash1.toString()).toString();
|
|||
|
let h5st = ["".concat(timestamp.toString()), "".concat($.fp.toString()), "".concat($.appId.toString()), "".concat($.token), "".concat(hash2),"3.0","".concat(time)].join(";")
|
|||
|
return h5st
|
|||
|
}
|
|||
|
function format(a, time) {
|
|||
|
if (!a) a = 'yyyy-MM-dd';
|
|||
|
var t;
|
|||
|
if (!time) {
|
|||
|
t = Date.now();
|
|||
|
} else {
|
|||
|
t = new Date(time);
|
|||
|
}
|
|||
|
var e,
|
|||
|
n = new Date(t),
|
|||
|
d = a,
|
|||
|
l = {
|
|||
|
'M+': n.getMonth() + 1,
|
|||
|
'd+': n.getDate(),
|
|||
|
'D+': n.getDate(),
|
|||
|
'h+': n.getHours(),
|
|||
|
'H+': n.getHours(),
|
|||
|
'm+': n.getMinutes(),
|
|||
|
's+': n.getSeconds(),
|
|||
|
'w+': n.getDay(),
|
|||
|
'q+': Math.floor((n.getMonth() + 3) / 3),
|
|||
|
'S+': n.getMilliseconds(),
|
|||
|
};
|
|||
|
/(y+)/i.test(d) && (d = d.replace(RegExp.$1, ''.concat(n.getFullYear()).substr(4 - RegExp.$1.length)));
|
|||
|
Object.keys(l).forEach(e => {
|
|||
|
if (new RegExp('('.concat(e, ')')).test(d)) {
|
|||
|
var t,
|
|||
|
a = 'S+' === e ? '000' : '00';
|
|||
|
d = d.replace(RegExp.$1, 1 == RegExp.$1.length ? l[e] : ''.concat(a).concat(l[e]).substr(''.concat(l[e]).length));
|
|||
|
}
|
|||
|
});
|
|||
|
return d;
|
|||
|
}
|
|||
|
function jsonParse(str) {
|
|||
|
if (typeof str == "string") {
|
|||
|
try {
|
|||
|
return JSON.parse(str);
|
|||
|
} catch (e) {
|
|||
|
console.log(e);
|
|||
|
$.msg($.name, '', '请勿随意在BoxJs输入框修改内容\n建议通过脚本去获取cookie')
|
|||
|
return [];
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function getUA(){
|
|||
|
$.UA = `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36`
|
|||
|
}
|
|||
|
function randomString(e) {
|
|||
|
e = e || 32;
|
|||
|
let t = "abcdef0123456789", a = t.length, n = "";
|
|||
|
for (i = 0; i < e; i++)
|
|||
|
n += t.charAt(Math.floor(Math.random() * a));
|
|||
|
return n
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
async function injectToRequest(scene = 'cww') {
|
|||
|
console.log('JDJR验证中......');
|
|||
|
let res = await new JDJRValidator().run(scene, eid);
|
|||
|
if(res.validate){
|
|||
|
$.validate = res.validate
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Math.avg = function average() {
|
|||
|
var sum = 0;
|
|||
|
var len = this.length;
|
|||
|
for (var i = 0; i < len; i++) {
|
|||
|
sum += this[i];
|
|||
|
}
|
|||
|
return sum / len;
|
|||
|
};
|
|||
|
|
|||
|
function sleep(timeout) {
|
|||
|
return new Promise((resolve) => setTimeout(resolve, timeout));
|
|||
|
}
|
|||
|
class PNGDecoder extends PNG {
|
|||
|
constructor(args) {
|
|||
|
super(args);
|
|||
|
this.pixels = [];
|
|||
|
}
|
|||
|
decodeToPixels() {
|
|||
|
return new Promise((resolve) => {
|
|||
|
this.decode((pixels) => {
|
|||
|
this.pixels = pixels;
|
|||
|
resolve();
|
|||
|
});
|
|||
|
});
|
|||
|
}
|
|||
|
getImageData(x, y, w, h) {
|
|||
|
const {pixels} = this;
|
|||
|
const len = w * h * 4;
|
|||
|
const startIndex = x * 4 + y * (w * 4);
|
|||
|
return {data: pixels.slice(startIndex, startIndex + len)};
|
|||
|
}
|
|||
|
}
|
|||
|
const PUZZLE_GAP = 8;
|
|||
|
const PUZZLE_PAD = 10;
|
|||
|
class PuzzleRecognizer {
|
|||
|
constructor(bg, patch, y) {
|
|||
|
// console.log(bg);
|
|||
|
const imgBg = new PNGDecoder(Buffer.from(bg, 'base64'));
|
|||
|
const imgPatch = new PNGDecoder(Buffer.from(patch, 'base64'));
|
|||
|
// console.log(imgBg);
|
|||
|
this.bg = imgBg;
|
|||
|
this.patch = imgPatch;
|
|||
|
this.rawBg = bg;
|
|||
|
this.rawPatch = patch;
|
|||
|
this.y = y;
|
|||
|
this.w = imgBg.width;
|
|||
|
this.h = imgBg.height;
|
|||
|
// this.w = 260;
|
|||
|
// this.h = 101;
|
|||
|
}
|
|||
|
async run() {
|
|||
|
await this.bg.decodeToPixels();
|
|||
|
await this.patch.decodeToPixels();
|
|||
|
return this.recognize();
|
|||
|
}
|
|||
|
|
|||
|
recognize() {
|
|||
|
const {ctx, w: width, bg} = this;
|
|||
|
const {width: patchWidth, height: patchHeight} = this.patch;
|
|||
|
const posY = this.y + PUZZLE_PAD + ((patchHeight - PUZZLE_PAD) / 2) - (PUZZLE_GAP / 2);
|
|||
|
// const cData = ctx.getImageData(0, a.y + 10 + 20 - 4, 360, 8).data;
|
|||
|
const cData = bg.getImageData(0, posY, width, PUZZLE_GAP).data;
|
|||
|
const lumas = [];
|
|||
|
for (let x = 0; x < width; x++) {
|
|||
|
var sum = 0;
|
|||
|
// y xais
|
|||
|
for (let y = 0; y < PUZZLE_GAP; y++) {
|
|||
|
var idx = x * 4 + y * (width * 4);
|
|||
|
var r = cData[idx];
|
|||
|
var g = cData[idx + 1];
|
|||
|
var b = cData[idx + 2];
|
|||
|
var luma = 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|||
|
sum += luma;
|
|||
|
}
|
|||
|
lumas.push(sum / PUZZLE_GAP);
|
|||
|
}
|
|||
|
const n = 2; // minium macroscopic image width (px)
|
|||
|
const margin = patchWidth - PUZZLE_PAD;
|
|||
|
const diff = 20; // macroscopic brightness difference
|
|||
|
const radius = PUZZLE_PAD;
|
|||
|
for (let i = 0, len = lumas.length - 2 * 4; i < len; i++) {
|
|||
|
const left = (lumas[i] + lumas[i + 1]) / n;
|
|||
|
const right = (lumas[i + 2] + lumas[i + 3]) / n;
|
|||
|
const mi = margin + i;
|
|||
|
const mLeft = (lumas[mi] + lumas[mi + 1]) / n;
|
|||
|
const mRigth = (lumas[mi + 2] + lumas[mi + 3]) / n;
|
|||
|
if (left - right > diff && mLeft - mRigth < -diff) {
|
|||
|
const pieces = lumas.slice(i + 2, margin + i + 2);
|
|||
|
const median = pieces.sort((x1, x2) => x1 - x2)[20];
|
|||
|
const avg = Math.avg(pieces);
|
|||
|
// noise reducation
|
|||
|
if (median > left || median > mRigth) return;
|
|||
|
if (avg > 100) return;
|
|||
|
// console.table({left,right,mLeft,mRigth,median});
|
|||
|
// ctx.fillRect(i+n-radius, 0, 1, 360);
|
|||
|
// console.log(i+n-radius);
|
|||
|
return i + n - radius;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// not found
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
runWithCanvas() {
|
|||
|
const {createCanvas, Image} = require('canvas');
|
|||
|
const canvas = createCanvas();
|
|||
|
const ctx = canvas.getContext('2d');
|
|||
|
const imgBg = new Image();
|
|||
|
const imgPatch = new Image();
|
|||
|
const prefix = 'data:image/png;base64,';
|
|||
|
imgBg.src = prefix + this.rawBg;
|
|||
|
imgPatch.src = prefix + this.rawPatch;
|
|||
|
const {naturalWidth: w, naturalHeight: h} = imgBg;
|
|||
|
canvas.width = w;
|
|||
|
canvas.height = h;
|
|||
|
ctx.clearRect(0, 0, w, h);
|
|||
|
ctx.drawImage(imgBg, 0, 0, w, h);
|
|||
|
const width = w;
|
|||
|
const {naturalWidth, naturalHeight} = imgPatch;
|
|||
|
const posY = this.y + PUZZLE_PAD + ((naturalHeight - PUZZLE_PAD) / 2) - (PUZZLE_GAP / 2);
|
|||
|
// const cData = ctx.getImageData(0, a.y + 10 + 20 - 4, 360, 8).data;
|
|||
|
const cData = ctx.getImageData(0, posY, width, PUZZLE_GAP).data;
|
|||
|
const lumas = [];
|
|||
|
for (let x = 0; x < width; x++) {
|
|||
|
var sum = 0;
|
|||
|
// y xais
|
|||
|
for (let y = 0; y < PUZZLE_GAP; y++) {
|
|||
|
var idx = x * 4 + y * (width * 4);
|
|||
|
var r = cData[idx];
|
|||
|
var g = cData[idx + 1];
|
|||
|
var b = cData[idx + 2];
|
|||
|
var luma = 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|||
|
sum += luma;
|
|||
|
}
|
|||
|
lumas.push(sum / PUZZLE_GAP);
|
|||
|
}
|
|||
|
const n = 2; // minium macroscopic image width (px)
|
|||
|
const margin = naturalWidth - PUZZLE_PAD;
|
|||
|
const diff = 20; // macroscopic brightness difference
|
|||
|
const radius = PUZZLE_PAD;
|
|||
|
for (let i = 0, len = lumas.length - 2 * 4; i < len; i++) {
|
|||
|
const left = (lumas[i] + lumas[i + 1]) / n;
|
|||
|
const right = (lumas[i + 2] + lumas[i + 3]) / n;
|
|||
|
const mi = margin + i;
|
|||
|
const mLeft = (lumas[mi] + lumas[mi + 1]) / n;
|
|||
|
const mRigth = (lumas[mi + 2] + lumas[mi + 3]) / n;
|
|||
|
if (left - right > diff && mLeft - mRigth < -diff) {
|
|||
|
const pieces = lumas.slice(i + 2, margin + i + 2);
|
|||
|
const median = pieces.sort((x1, x2) => x1 - x2)[20];
|
|||
|
const avg = Math.avg(pieces);
|
|||
|
// noise reducation
|
|||
|
if (median > left || median > mRigth) return;
|
|||
|
if (avg > 100) return;
|
|||
|
// console.table({left,right,mLeft,mRigth,median});
|
|||
|
// ctx.fillRect(i+n-radius, 0, 1, 360);
|
|||
|
// console.log(i+n-radius);
|
|||
|
return i + n - radius;
|
|||
|
}
|
|||
|
}
|
|||
|
// not found
|
|||
|
return -1;
|
|||
|
}
|
|||
|
}
|
|||
|
const DATA = {
|
|||
|
"appId": "17839d5db83",
|
|||
|
"product": "embed",
|
|||
|
"lang": "zh_CN",
|
|||
|
};
|
|||
|
const SERVER = 'iv.jd.com';
|
|||
|
class JDJRValidator {
|
|||
|
constructor() {
|
|||
|
this.data = {};
|
|||
|
this.x = 0;
|
|||
|
this.t = Date.now();
|
|||
|
this.count = 0;
|
|||
|
}
|
|||
|
async run(scene = 'cww', eid='') {
|
|||
|
const tryRecognize = async () => {
|
|||
|
const x = await this.recognize(scene, eid);
|
|||
|
if (x > 0) {
|
|||
|
return x;
|
|||
|
}
|
|||
|
// retry
|
|||
|
return await tryRecognize();
|
|||
|
};
|
|||
|
const puzzleX = await tryRecognize();
|
|||
|
// console.log(puzzleX);
|
|||
|
const pos = new MousePosFaker(puzzleX).run();
|
|||
|
const d = getCoordinate(pos);
|
|||
|
// console.log(pos[pos.length-1][2] -Date.now());
|
|||
|
// await sleep(4500);
|
|||
|
await sleep(pos[pos.length - 1][2] - Date.now());
|
|||
|
this.count++;
|
|||
|
const result = await JDJRValidator.jsonp('/slide/s.html', {d, ...this.data}, scene);
|
|||
|
if (result.message === 'success') {
|
|||
|
// console.log(result);
|
|||
|
$.validatorTime = (Date.now() - this.t) / 1000
|
|||
|
console.log(`JDJR验证用时: ${$.validatorTime}秒`);
|
|||
|
return result;
|
|||
|
} else {
|
|||
|
console.log(`验证失败: ${this.count}/${validatorCount}`);
|
|||
|
// console.log(JSON.stringify(result));
|
|||
|
if(this.count >= validatorCount){
|
|||
|
console.log("JDJR验证次数已达上限,退出验证");
|
|||
|
return result;
|
|||
|
}else{
|
|||
|
// await sleep(300);
|
|||
|
return await this.run(scene, eid);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
async recognize(scene, eid) {
|
|||
|
const data = await JDJRValidator.jsonp('/slide/g.html', {e: eid}, scene);
|
|||
|
const {bg, patch, y} = data;
|
|||
|
// const uri = 'data:image/png;base64,';
|
|||
|
// const re = new PuzzleRecognizer(uri+bg, uri+patch, y);
|
|||
|
const re = new PuzzleRecognizer(bg, patch, y);
|
|||
|
// console.log(JSON.stringify(re))
|
|||
|
const puzzleX = await re.run();
|
|||
|
|
|||
|
if (puzzleX > 0) {
|
|||
|
this.data = {
|
|||
|
c: data.challenge,
|
|||
|
w: re.w,
|
|||
|
e: eid,
|
|||
|
s: '',
|
|||
|
o: '',
|
|||
|
o1: 0,
|
|||
|
u: $.validatorUrl || 'https://prodev.m.jd.com',
|
|||
|
};
|
|||
|
this.x = puzzleX;
|
|||
|
}
|
|||
|
return puzzleX;
|
|||
|
}
|
|||
|
|
|||
|
async report(n) {
|
|||
|
console.time('PuzzleRecognizer');
|
|||
|
let count = 0;
|
|||
|
|
|||
|
for (let i = 0; i < n; i++) {
|
|||
|
const x = await this.recognize();
|
|||
|
|
|||
|
if (x > 0) count++;
|
|||
|
if (i % 50 === 0) {
|
|||
|
// console.log('%f\%', (i / n) * 100);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
console.log('验证成功: %f\%', (count / n) * 100);
|
|||
|
console.clear()
|
|||
|
console.timeEnd('PuzzleRecognizer');
|
|||
|
}
|
|||
|
|
|||
|
static jsonp(api, data = {}, scene) {
|
|||
|
return new Promise((resolve, reject) => {
|
|||
|
const fnId = `jsonp_${String(Math.random()).replace('.', '')}`;
|
|||
|
const extraData = {callback: fnId};
|
|||
|
const query = new URLSearchParams({...DATA,...{"scene": scene}, ...data, ...extraData}).toString();
|
|||
|
const url = `https://${SERVER}${api}?${query}`;
|
|||
|
const headers = {
|
|||
|
'Accept': '*/*',
|
|||
|
'Accept-Encoding': 'gzip,deflate,br',
|
|||
|
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
|
|||
|
'Connection': 'keep-alive',
|
|||
|
'Host': "iv.jd.com",
|
|||
|
'Referer': 'https://prodev.m.jd.com/',
|
|||
|
'User-Agent': $.UA,
|
|||
|
};
|
|||
|
|
|||
|
const req = https.get(url, {headers}, (response) => {
|
|||
|
let res = response;
|
|||
|
if (res.headers['content-encoding'] === 'gzip') {
|
|||
|
const unzipStream = new stream.PassThrough();
|
|||
|
stream.pipeline(
|
|||
|
response,
|
|||
|
zlib.createGunzip(),
|
|||
|
unzipStream,
|
|||
|
reject,
|
|||
|
);
|
|||
|
res = unzipStream;
|
|||
|
}
|
|||
|
res.setEncoding('utf8');
|
|||
|
|
|||
|
let rawData = '';
|
|||
|
|
|||
|
res.on('data', (chunk) => rawData += chunk);
|
|||
|
res.on('end', () => {
|
|||
|
try {
|
|||
|
const ctx = {
|
|||
|
[fnId]: (data) => ctx.data = data,
|
|||
|
data: {},
|
|||
|
};
|
|||
|
|
|||
|
vm.createContext(ctx);
|
|||
|
vm.runInContext(rawData, ctx);
|
|||
|
|
|||
|
// console.log(ctx.data);
|
|||
|
res.resume();
|
|||
|
resolve(ctx.data);
|
|||
|
} catch (e) {
|
|||
|
reject(e);
|
|||
|
}
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
req.on('error', reject);
|
|||
|
req.end();
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function getCoordinate(c) {
|
|||
|
function string10to64(d) {
|
|||
|
var c = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-~".split("")
|
|||
|
, b = c.length
|
|||
|
, e = +d
|
|||
|
, a = [];
|
|||
|
do {
|
|||
|
mod = e % b;
|
|||
|
e = (e - mod) / b;
|
|||
|
a.unshift(c[mod])
|
|||
|
} while (e);
|
|||
|
return a.join("")
|
|||
|
}
|
|||
|
|
|||
|
function prefixInteger(a, b) {
|
|||
|
return (Array(b).join(0) + a).slice(-b)
|
|||
|
}
|
|||
|
|
|||
|
function pretreatment(d, c, b) {
|
|||
|
var e = string10to64(Math.abs(d));
|
|||
|
var a = "";
|
|||
|
if (!b) {
|
|||
|
a += (d > 0 ? "1" : "0")
|
|||
|
}
|
|||
|
a += prefixInteger(e, c);
|
|||
|
return a
|
|||
|
}
|
|||
|
|
|||
|
var b = new Array();
|
|||
|
for (var e = 0; e < c.length; e++) {
|
|||
|
if (e == 0) {
|
|||
|
b.push(pretreatment(c[e][0] < 262143 ? c[e][0] : 262143, 3, true));
|
|||
|
b.push(pretreatment(c[e][1] < 16777215 ? c[e][1] : 16777215, 4, true));
|
|||
|
b.push(pretreatment(c[e][2] < 4398046511103 ? c[e][2] : 4398046511103, 7, true))
|
|||
|
} else {
|
|||
|
var a = c[e][0] - c[e - 1][0];
|
|||
|
var f = c[e][1] - c[e - 1][1];
|
|||
|
var d = c[e][2] - c[e - 1][2];
|
|||
|
b.push(pretreatment(a < 4095 ? a : 4095, 2, false));
|
|||
|
b.push(pretreatment(f < 4095 ? f : 4095, 2, false));
|
|||
|
b.push(pretreatment(d < 16777215 ? d : 16777215, 4, true))
|
|||
|
}
|
|||
|
}
|
|||
|
return b.join("")
|
|||
|
}
|
|||
|
|
|||
|
const HZ = 20;
|
|||
|
|
|||
|
class MousePosFaker {
|
|||
|
constructor(puzzleX) {
|
|||
|
this.x = parseInt(Math.random() * 20 + 20, 10);
|
|||
|
this.y = parseInt(Math.random() * 80 + 80, 10);
|
|||
|
this.t = Date.now();
|
|||
|
this.pos = [[this.x, this.y, this.t]];
|
|||
|
this.minDuration = parseInt(1000 / HZ, 10);
|
|||
|
// this.puzzleX = puzzleX;
|
|||
|
this.puzzleX = puzzleX + parseInt(Math.random() * 2 - 1, 10);
|
|||
|
|
|||
|
this.STEP = parseInt(Math.random() * 6 + 5, 10);
|
|||
|
this.DURATION = parseInt(Math.random() * 7 + 14, 10) * 100;
|
|||
|
// [9,1600] [10,1400]
|
|||
|
this.STEP = 9;
|
|||
|
// this.DURATION = 2000;
|
|||
|
// console.log(this.STEP, this.DURATION);
|
|||
|
}
|
|||
|
|
|||
|
run() {
|
|||
|
const perX = this.puzzleX / this.STEP;
|
|||
|
const perDuration = this.DURATION / this.STEP;
|
|||
|
const firstPos = [this.x - parseInt(Math.random() * 6, 10), this.y + parseInt(Math.random() * 11, 10), this.t];
|
|||
|
|
|||
|
this.pos.unshift(firstPos);
|
|||
|
this.stepPos(perX, perDuration);
|
|||
|
this.fixPos();
|
|||
|
|
|||
|
const reactTime = parseInt(60 + Math.random() * 100, 10);
|
|||
|
const lastIdx = this.pos.length - 1;
|
|||
|
const lastPos = [this.pos[lastIdx][0], this.pos[lastIdx][1], this.pos[lastIdx][2] + reactTime];
|
|||
|
|
|||
|
this.pos.push(lastPos);
|
|||
|
return this.pos;
|
|||
|
}
|
|||
|
|
|||
|
stepPos(x, duration) {
|
|||
|
let n = 0;
|
|||
|
const sqrt2 = Math.sqrt(2);
|
|||
|
for (let i = 1; i <= this.STEP; i++) {
|
|||
|
n += 1 / i;
|
|||
|
}
|
|||
|
for (let i = 0; i < this.STEP; i++) {
|
|||
|
x = this.puzzleX / (n * (i + 1));
|
|||
|
const currX = parseInt((Math.random() * 30 - 15) + x, 10);
|
|||
|
const currY = parseInt(Math.random() * 7 - 3, 10);
|
|||
|
const currDuration = parseInt((Math.random() * 0.4 + 0.8) * duration, 10);
|
|||
|
|
|||
|
this.moveToAndCollect({
|
|||
|
x: currX,
|
|||
|
y: currY,
|
|||
|
duration: currDuration,
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
fixPos() {
|
|||
|
const actualX = this.pos[this.pos.length - 1][0] - this.pos[1][0];
|
|||
|
const deviation = this.puzzleX - actualX;
|
|||
|
|
|||
|
if (Math.abs(deviation) > 4) {
|
|||
|
this.moveToAndCollect({
|
|||
|
x: deviation,
|
|||
|
y: parseInt(Math.random() * 8 - 3, 10),
|
|||
|
duration: 250,
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
moveToAndCollect({x, y, duration}) {
|
|||
|
let movedX = 0;
|
|||
|
let movedY = 0;
|
|||
|
let movedT = 0;
|
|||
|
const times = duration / this.minDuration;
|
|||
|
let perX = x / times;
|
|||
|
let perY = y / times;
|
|||
|
let padDuration = 0;
|
|||
|
|
|||
|
if (Math.abs(perX) < 1) {
|
|||
|
padDuration = duration / Math.abs(x) - this.minDuration;
|
|||
|
perX = 1;
|
|||
|
perY = y / Math.abs(x);
|
|||
|
}
|
|||
|
|
|||
|
while (Math.abs(movedX) < Math.abs(x)) {
|
|||
|
const rDuration = parseInt(padDuration + Math.random() * 16 - 4, 10);
|
|||
|
|
|||
|
movedX += perX + Math.random() * 2 - 1;
|
|||
|
movedY += perY;
|
|||
|
movedT += this.minDuration + rDuration;
|
|||
|
|
|||
|
const currX = parseInt(this.x + movedX, 10);
|
|||
|
const currY = parseInt(this.y + movedY, 10);
|
|||
|
const currT = this.t + movedT;
|
|||
|
|
|||
|
this.pos.push([currX, currY, currT]);
|
|||
|
}
|
|||
|
|
|||
|
this.x += x;
|
|||
|
this.y += y;
|
|||
|
this.t += Math.max(duration, movedT);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function CryptoScripts() {
|
|||
|
// prettier-ignore
|
|||
|
!function(t,e){"object"==typeof exports?module.exports=exports=e():"function"==typeof define&&define.amd?define([],e):t.CryptoJS=e()}(this,function(){var t,e,r,i,n,o,s,c,a,h,l,f,d,u,p,_,v,y,g,B,w,k,S,m,x,b,H,z,A,C,D,E,R,M,F,P,W,O,I,U,K,X,L,j,N,T,q,Z,V,G,J,$,Q,Y,tt,et,rt,it,nt,ot,st,ct,at,ht,lt,ft,dt,ut,pt,_t,vt,yt,gt,Bt,wt,kt,St,mt=mt||function(t){var e;if("undefined"!=typeof window&&window.crypto&&(e=window.crypto),!e&&"undefined"!=typeof window&&window.msCrypto&&(e=window.msCrypto),!e&&"undefined"!=typeof global&&global.crypto&&(e=global.crypto),!e&&"function"==typeof require)try{e=require("crypto")}catch(e){}function r(){if(e){if("function"==typeof e.getRandomValues)try{return e.getRandomValues(new Uint32Array(1))[0]}catch(t){}if("function"==typeof e.randomBytes)try{return e.randomBytes(4).readInt32LE()}catch(t){}}throw new Error("Native crypto module could not be used to get secure random number.")}var i=Object.create||function(t){var e;return n.prototype=t,e=new n,n.prototype=null,e};function n(){}var o={},s=o.lib={},c=s.Base={extend:function(t){var e=i(this);return t&&e.mixIn(t),e.hasOwnProperty("init")&&this.init!==e.init||(e.init=function(){e.$super.init.apply(this,arguments)}),(e.init.prototype=e).$super=this,e},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var e in t)t.hasOwnProperty(e)&&(this[e]=t[e]);t.hasOwnProperty("toString")&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}},a=s.WordArray=c.extend({init:function(t,e){t=this.words=t||[],this.sigBytes=null!=e?e:4*t.length},toString:function(t){return(t||l).stringify(this)},concat:function(t){var e=this.words,r=t.words,i=this.sigBytes,n=t.sigBytes;if(this.clamp(),i%4)for(var o=0;o<n;o++){var s=r[o>>>2]>>>24-o%4*8&255;e[i+o>>>2]|=s<<24-(i+o)%4*8}else for(o=0;o<n;o+=4)e[i+o>>>2]=r[o>>>2];return this.sigBytes+=n,this},clamp:function(){var e=this.words,r=this.sigBytes;e[r>>>2]&=4294967295<<32-r%4*8,e.length=t.ceil(r/4)},clone:function(){var t=c.clone.call(this);return t.words=this.words.slice(0),t},random:function(t){for(var e=[],i=0;i<t;i+=4)e.push(r());return new a.init(e,t)}}),h=o.enc={},l=h.Hex={stringify:function(t){for(var e=t.words,r=t.sigBytes,i=[],n=0;n<r;n++){var o=e[n>>>2]>>>24-n%4*8&255;i.push((o>>>4).toString(16)),i.push((15&o).toString(16))}return i.join("")},parse:function(t){for(var e=t.length,r=[],i=0;i<e;i+=2)r[i>>>3]|=parseInt(t.substr(i,2),16)<<24-i%8*4;return new a.init(r,e/2)}},f=h.Latin1={stringify:function(t){for(var e=t.words,r=t.sigBytes,i=[],n=0;n<r;n++){var o=e[n>>>2]>>>24-n%4*8&255;i.push(String.fromCharCode(o))}return i.join("")},parse:function(t){for(var e=t.length,r=[],i=0;i<e;i++)r[i>>>2]|=(255&t.charCodeAt(i))<<24-i%4*8;return new a.init(r,e)}},d=h.Utf8={stringify:function(t){try{return decodeURIComponent(escape(f.stringify(t)))}catch(t){throw new Error("Malformed UTF-8 data")}},parse:function(t){return f.parse(unescape(encodeURIComponent(t)))}},u=s.BufferedBlockAlgorithm=c.extend({reset:function(){this._data=new a.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=d.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(e){var r,i=this._data,n=i.words,o=i.sigBytes,s=this.blockSize,c=o/(4*s),h=(c=e?t.ceil(c):t.max((0|c)-this._minBufferSize,0))*s,l=t.min(4*h,o);if(h){for(var f=0;f<h;f+=s)this._doProcessBlock(n,f);r=n.splice(0,h),i.sigBytes-=l}return new a.init(r,l)},clone:function(){var t=c.clone.call(this);return t._data=this._data.clone(),t},_minBufferSize:0}),p=(s.Hasher=u.extend({cfg:c.extend(),init:function(t){this.cfg=this.cfg.extend(t),this.reset()},reset:function(){u.reset.call(this),this._doReset()},update:function(t){return this._append(t),this._process(),this},finalize:function(t){return t&&this._append(t),this._doFinalize()},blockSize:16,_createHelper:function(t){return function(e,r){return new t.init(r).finalize(e)}},_createHmacHelper:function(t){return function(e,r){return new p.HMAC.init(t,r).finalize(e)}}}),o.algo={});return o}(Math);function xt(t,e,r){return t^e^r}fu
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
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"])
|