mirror of
https://github.com/6dylan6/jdpro.git
synced 2026-05-01 09:36:41 +08:00
1
This commit is contained in:
@@ -0,0 +1,558 @@
|
||||
/*
|
||||
由于 canvas 依赖系统底层需要编译且预编译包在 github releases 上,改用另一个纯 js 解码图片。若想继续使用 canvas 可调用 runWithCanvas 。
|
||||
添加 injectToRequest 用以快速修复需验证的请求。eg: $.get=injectToRequest($.get.bind($))
|
||||
*/
|
||||
const https = require('https');
|
||||
const http = require('http');
|
||||
const stream = require('stream');
|
||||
const zlib = require('zlib');
|
||||
const vm = require('vm');
|
||||
const PNG = require('png-js');
|
||||
const UA = require('./USER_AGENTS.js').USER_AGENT;
|
||||
|
||||
|
||||
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) => {
|
||||
try {
|
||||
this.decode((pixels) => {
|
||||
this.pixels = pixels;
|
||||
resolve();
|
||||
});
|
||||
} catch (e) {
|
||||
console.info(e)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
async run() {
|
||||
try {
|
||||
await this.bg.decodeToPixels();
|
||||
await this.patch.decodeToPixels();
|
||||
|
||||
return this.recognize();
|
||||
} catch (e) {
|
||||
console.info(e)
|
||||
}
|
||||
}
|
||||
|
||||
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 = '61.49.99.122';
|
||||
|
||||
class JDJRValidator {
|
||||
constructor() {
|
||||
this.data = {};
|
||||
this.x = 0;
|
||||
this.t = Date.now();
|
||||
this.trynum = 0;
|
||||
}
|
||||
|
||||
async run(scene) {
|
||||
try {
|
||||
if (this.trynum > 5) return '';
|
||||
const tryRecognize = async () => {
|
||||
const x = await this.recognize(scene);
|
||||
|
||||
if (x > 0) {
|
||||
return x;
|
||||
}
|
||||
// retry
|
||||
return 124;
|
||||
};
|
||||
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);
|
||||
//console.log(pos[pos.length - 1][2] - Date.now());
|
||||
await sleep(pos[pos.length - 1][2] - Date.now());
|
||||
const result = await JDJRValidator.jsonp('/slide/s.html', {d, ...this.data}, scene);
|
||||
|
||||
if (result.message === 'success') {
|
||||
// console.log(result);
|
||||
console.log('JDJR验证用时: %fs', (Date.now() - this.t) / 1000);
|
||||
return result;
|
||||
} else {
|
||||
console.count("验证失败");
|
||||
this.trynum++
|
||||
// console.count(JSON.stringify(result));
|
||||
await sleep(300);
|
||||
return await this.run(scene);
|
||||
}
|
||||
} catch (e) {
|
||||
console.info(e)
|
||||
}
|
||||
}
|
||||
|
||||
async recognize(scene) {
|
||||
try {
|
||||
const data = await JDJRValidator.jsonp('/slide/g.html', {e: ''}, scene);
|
||||
const {bg, patch, y} = data;
|
||||
if (bg.length < 10000) return;
|
||||
// const uri = 'data:image/png;base64,';
|
||||
// const re = new PuzzleRecognizer(uri+bg, uri+patch, y);
|
||||
const re = new PuzzleRecognizer(bg, patch, y);
|
||||
const puzzleX = await re.run();
|
||||
|
||||
if (puzzleX > 0) {
|
||||
this.data = {
|
||||
c: data.challenge,
|
||||
w: re.w,
|
||||
e: '',
|
||||
s: '',
|
||||
o: '',
|
||||
};
|
||||
this.x = puzzleX;
|
||||
}
|
||||
return puzzleX;
|
||||
} catch (e) {
|
||||
console.info(e)
|
||||
}
|
||||
}
|
||||
|
||||
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.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}, ...extraData, ...data}).toString();
|
||||
const url = `http://${SERVER}${api}?${query}`;
|
||||
const headers = {
|
||||
'Accept': '*/*',
|
||||
'Accept-Encoding': 'gzip,deflate,br',
|
||||
'Accept-Language': 'zh-CN,en-US',
|
||||
'Connection': 'keep-alive',
|
||||
'Host': SERVER,
|
||||
'Proxy-Connection': 'keep-alive',
|
||||
'Referer': 'https://h5.m.jd.com/babelDiy/Zeus/2wuqXrZrhygTQzYA7VufBEpj4amH/index.html',
|
||||
'User-Agent': UA,
|
||||
};
|
||||
const req = http.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 = 5;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// new JDJRValidator().run();
|
||||
// new JDJRValidator().report(1000);
|
||||
// console.log(getCoordinate(new MousePosFaker(100).run()));
|
||||
|
||||
function injectToRequest2(fn, scene = 'cww') {
|
||||
return (opts, cb) => {
|
||||
fn(opts, async (err, resp, data) => {
|
||||
try {
|
||||
if (err) {
|
||||
console.error('验证请求失败.');
|
||||
return;
|
||||
}
|
||||
if (data.search('验证') > -1) {
|
||||
console.log('JDJR验证中......');
|
||||
const res = await new JDJRValidator().run(scene);
|
||||
if (res) {
|
||||
opts.url += `&validate=${res.validate}`;
|
||||
}
|
||||
fn(opts, cb);
|
||||
} else {
|
||||
cb(err, resp, data);
|
||||
}
|
||||
} catch (e) {
|
||||
console.info(e)
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
async function injectToRequest(scene = 'cww') {
|
||||
console.log('JDJR验证中......');
|
||||
const res = await new JDJRValidator().run(scene);
|
||||
if (res == '') return;
|
||||
return res.validate;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
sleep,
|
||||
injectToRequest,
|
||||
injectToRequest2
|
||||
}
|
||||
+2080
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,92 @@
|
||||
const USER_AGENTS = [
|
||||
'jdltapp;iPad;3.7.0;14.4;network/wifi;Mozilla/5.0 (iPad; CPU OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;android;3.7.0;10;2346663656561603-4353564623932316;network/wifi;model/ONEPLUS A5010;addressid/0;aid/2dfceea045ed292a;oaid/;osVer/29;appBuild/1436;psn/BS6Y9SAiw0IpJ4ro7rjSOkCRZTgR3z2K|10;psq/5;adk/;ads/;pap/JA2020_3112531|3.7.0|ANDROID 10;osv/10;pv/10.5;jdv/;ref/com.jd.jdlite.lib.personal.view.fragment.JDPersonalFragment;partner/oppo;apprpd/MyJD_Main;eufv/1;Mozilla/5.0 (Linux; Android 10; ONEPLUS A5010 Build/QKQ1.191014.012; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045140 Mobile Safari/537.36',
|
||||
'jdltapp;iPhone;3.7.0;14.1;59d6ae6e8387bd09fe046d5b8918ead51614e80a;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone12,1;hasOCPay/0;appBuild/1017;supportBestPay/0;addressid/;pv/1.26;apprpd/;ref/JDLTSubMainPageViewController;psq/0;ads/;psn/59d6ae6e8387bd09fe046d5b8918ead51614e80a|3;jdv/0|;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.1;Mozilla/5.0 (iPhone; CPU iPhone OS 14_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;13.5;22d679c006bf9c087abf362cf1d2e0020ebb8798;network/wifi;ADID/10857A57-DDF8-4A0D-A548-7B8F43AC77EE;hasUPPay/0;pushNoticeIsOpen/1;lang/zh_CN;model/iPhone12,1;addressid/2378947694;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/15.7;apprpd/Allowance_Registered;ref/JDLTTaskCenterViewController;psq/6;ads/;psn/22d679c006bf9c087abf362cf1d2e0020ebb8798|22;jdv/0|kong|t_1000170135|tuiguang|notset|1614153044558|1614153044;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 13.5;Mozilla/5.0 (iPhone; CPU iPhone OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;android;3.7.0;10;2616935633265383-5333463636261326;network/UNKNOWN;model/M2007J3SC;addressid/1840745247;aid/ba9e3b5853dccb1b;oaid/371d8af7dd71e8d5;osVer/29;appBuild/1436;psn/t7JmxZUXGkimd4f9Jdul2jEeuYLwxPrm|8;psq/6;adk/;ads/;pap/JA2020_3112531|3.7.0|ANDROID 10;osv/10;pv/5.6;jdv/;ref/com.jd.jdlite.lib.jdlitemessage.view.activity.MessageCenterMainActivity;partner/xiaomi;apprpd/MessageCenter_MessageMerge;eufv/1;Mozilla/5.0 (Linux; Android 10; M2007J3SC Build/QKQ1.200419.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045135 Mobile Safari/537.36',
|
||||
'jdltapp;iPhone;3.7.0;14.3;d7beab54ae7758fa896c193b49470204fbb8fce9;network/4g;ADID/97AD46C9-6D49-4642-BF6F-689256673906;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone11,2;addressid/;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/6.28;apprpd/;ref/JDLTRedPacketViewController;psq/3;ads/;psn/d7beab54ae7758fa896c193b49470204fbb8fce9|8;jdv/0|kong|t_1001707023_|jingfen|79ad0319fa4d47e38521a616d80bc4bd|1613800945610|1613824900;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.3;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;android;3.7.0;9;D246836333735-3264353430393;network/4g;model/MIX 2;addressid/138678023;aid/bf8bcf1214b3832a;oaid/308540d1f1feb2f5;osVer/28;appBuild/1436;psn/Z/rGqfWBY/h5gcGFnVIsRw==|16;psq/3;adk/;ads/;pap/JA2020_3112531|3.7.0|ANDROID 9;osv/9;pv/13.7;jdv/;ref/com.jd.jdlite.lib.personal.view.fragment.JDPersonalFragment;partner/xiaomi;apprpd/MyJD_Main;eufv/1;Mozilla/5.0 (Linux; Android 9; MIX 2 Build/PKQ1.190118.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045135 Mobile Safari/537.36',
|
||||
'jdltapp;iPhone;3.7.0;14.4;eb5a9e7e596e262b4ffb3b6b5c830984c8a5c0d5;network/wifi;ADID/5603541B-30C1-4B5C-A782-20D0B569D810;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone9,2;addressid/1041002757;hasOCPay/0;appBuild/101;supportBestPay/0;pv/34.6;apprpd/MyJD_Main;ref/MyJdMTAManager;psq/5;ads/;psn/eb5a9e7e596e262b4ffb3b6b5c830984c8a5c0d5|44;jdv/0|androidapp|t_335139774|appshare|CopyURL|1612612940307|1612612944;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.3;21631ed983b3e854a3154b0336413825ad0d6783;network/3g;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone13,4;addressid/;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/4.47;apprpd/;ref/JDLTSubMainPageViewController;psq/8;ads/;psn/21631ed983b3e854a3154b0336413825ad0d6783|9;jdv/0|direct|-|none|-|1614150725100|1614225882;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.3;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;13.5;500a795cb2abae60b877ee4a1930557a800bef1c;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone8,1;addressid/669949466;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/9.11;apprpd/;ref/JDLTSubMainPageViewController;psq/10;ads/;psn/500a795cb2abae60b877ee4a1930557a800bef1c|11;jdv/;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 13.5;Mozilla/5.0 (iPhone; CPU iPhone OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPad;3.7.0;14.4;f5e7b7980fb50efc9c294ac38653c1584846c3db;network/wifi;hasUPPay/0;pushNoticeIsOpen/1;lang/zh_CN;model/iPad6,3;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/231.11;pap/JA2020_3112531|3.7.0|IOS 14.4;apprpd/;psn/f5e7b7980fb50efc9c294ac38653c1584846c3db|305;usc/kong;jdv/0|kong|t_1000170135|tuiguang|notset|1613606450668|1613606450;umd/tuiguang;psq/2;ucp/t_1000170135;app_device/IOS;utr/notset;ref/JDLTRedPacketViewController;adk/;ads/;Mozilla/5.0 (iPad; CPU OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;19fef5419f88076c43f5317eabe20121d52c6a61;network/wifi;ADID/00000000-0000-0000-0000-000000000000;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone11,8;addressid/3430850943;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/10.4;apprpd/;ref/JDLTSubMainPageViewController;psq/3;ads/;psn/19fef5419f88076c43f5317eabe20121d52c6a61|16;jdv/0|kong|t_1001327829_|jingfen|f51febe09dd64b20b06bc6ef4c1ad790#/|1614096460311|1614096511;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
|
||||
'jdltapp;iPhone;3.7.0;12.2;f995bc883282f7c7ea9d7f32da3f658127aa36c7;network/4g;ADID/9F40F4CA-EA7C-4F2E-8E09-97A66901D83E;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone10,4;addressid/525064695;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/11.11;apprpd/;ref/JDLTSubMainPageViewController;psq/2;ads/;psn/f995bc883282f7c7ea9d7f32da3f658127aa36c7|22;jdv/0|;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 12.2;Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;android;3.7.0;10;5366566313931326-6633931643233693;network/wifi;model/Mi9 Pro 5G;addressid/0;aid/5fe6191bf39a42c9;oaid/e3a9473ef6699f75;osVer/29;appBuild/1436;psn/b3rJlGi AwLqa9AqX7Vp0jv4T7XPMa0o|5;psq/4;adk/;ads/;pap/JA2020_3112531|3.7.0|ANDROID 10;osv/10;pv/5.4;jdv/;ref/HomeFragment;partner/xiaomi;apprpd/Home_Main;eufv/1;Mozilla/5.0 (Linux; Android 10; Mi9 Pro 5G Build/QKQ1.190825.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045135 Mobile Safari/537.36',
|
||||
'jdltapp;iPhone;3.7.0;14.4;4e6b46913a2e18dd06d6d69843ee4cdd8e033bc1;network/3g;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone13,2;addressid/666624049;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/54.11;apprpd/MessageCenter_MessageMerge;ref/MessageCenterController;psq/10;ads/;psn/4e6b46913a2e18dd06d6d69843ee4cdd8e033bc1|101;jdv/0|kong|t_2010804675_|jingfen|810dab1ba2c04b8588c5aa5a0d44c4bd|1614183499;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.2;c71b599e9a0bcbd8d1ad924d85b5715530efad06;network/wifi;ADID/751C6E92-FD10-4323-B37C-187FD0CF0551;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone11,8;addressid/4053561885;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/263.8;apprpd/;ref/JDLTSubMainPageViewController;psq/2;ads/;psn/c71b599e9a0bcbd8d1ad924d85b5715530efad06|481;jdv/0|kong|t_1001610202_|jingfen|3911bea7ee2f4fcf8d11fdf663192bbe|1614157052210|1614157056;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.2;Mozilla/5.0 (iPhone; CPU iPhone OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;2d306ee3cacd2c02560627a5113817ebea20a2c9;network/4g;ADID/A346F099-3182-4889-9A62-2B3C28AB861E;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone13,3;hasOCPay/0;appBuild/1017;supportBestPay/0;addressid/;pv/1.35;apprpd/Allowance_Registered;ref/JDLTTaskCenterViewController;psq/0;ads/;psn/2d306ee3cacd2c02560627a5113817ebea20a2c9|2;jdv/0|;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;28355aff16cec8bcf3e5728dbbc9725656d8c2c2;network/4g;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone10,2;addressid/833058617;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/4.10;apprpd/;ref/JDLTWebViewController;psq/9;ads/;psn/28355aff16cec8bcf3e5728dbbc9725656d8c2c2|5;jdv/0|;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;13.5;24ddac73a3de1b91816b7aedef53e97c4c313733;network/4g;ADID/598C6841-76AC-4512-AA97-CBA940548D70;hasUPPay/0;pushNoticeIsOpen/1;lang/zh_CN;model/iPhone11,6;addressid/;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/12.6;apprpd/;ref/JDLTSubMainPageViewController;psq/5;ads/;psn/24ddac73a3de1b91816b7aedef53e97c4c313733|23;jdv/0|kong|t_1000170135|tuiguang|notset|1614126110904|1614126110;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 13.5;Mozilla/5.0 (iPhone; CPU iPhone OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;d7732ba60c8ff73cc3f5ba7290a3aa9551f73a1b;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone12,1;addressid/25239372;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/8.6;apprpd/;ref/JDLTSubMainPageViewController;psq/5;ads/;psn/d7732ba60c8ff73cc3f5ba7290a3aa9551f73a1b|14;jdv/0|kong|t_1001226363_|jingfen|5713234d1e1e4893b92b2de2cb32484d|1614182989528|1614182992;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;ca1a32afca36bc9fb37fd03f18e653bce53eaca5;network/wifi;ADID/3AF380AB-CB74-4FE6-9E7C-967693863CA3;hasUPPay/0;pushNoticeIsOpen/1;lang/zh_CN;model/iPhone8,1;addressid/138323416;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/72.12;apprpd/;ref/JDLTRedPacketViewController;psq/3;ads/;psn/ca1a32afca36bc9fb37fd03f18e653bce53eaca5|109;jdv/0|kong|t_1000536212_|jingfen|c82bfa19e33a4269a5884ffc614790f4|1614141246;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;android;3.7.0;10;7346933333666353-8333366646039373;network/wifi;model/ONEPLUS A5010;addressid/138117973;aid/7d933f6583cfd097;oaid/;osVer/29;appBuild/1436;psn/T/eqfRSwp8VKEvvXyEunq09Cg2MUkiQ5|17;psq/4;adk/;ads/;pap/JA2020_3112531|3.7.0|ANDROID 10;osv/10;pv/11.4;jdv/0|kong|t_1001849073_|jingfen|495a47f6c0b8431c9d460f61ad2304dc|1614084403978|1614084407;ref/HomeFragment;partner/oppo;apprpd/Home_Main;eufv/1;Mozilla/5.0 (Linux; Android 10; ONEPLUS A5010 Build/QKQ1.191014.012; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045140 Mobile Safari/537.36',
|
||||
'jdltapp;android;3.7.0;11;4626269356736353-5353236346334673;network/wifi;model/M2006J10C;addressid/0;aid/dbb9e7655526d3d7;oaid/66a7af49362987b0;osVer/30;appBuild/1436;psn/rQRQgJ 4 S3qkq8YDl28y6jkUHmI/rlX|3;psq/4;adk/;ads/;pap/JA2020_3112531|3.7.0|ANDROID 11;osv/11;pv/3.4;jdv/;ref/HomeFragment;partner/xiaomi;apprpd/Home_Main;eufv/1;Mozilla/5.0 (Linux; Android 11; M2006J10C Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045513 Mobile Safari/537.36',
|
||||
'jdltapp;iPhone;3.7.0;14.4;78fc1d919de0c8c2de15725eff508d8ab14f9c82;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone13,1;addressid/137829713;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/23.11;apprpd/;ref/JDLTSubMainPageViewController;psq/10;ads/;psn/78fc1d919de0c8c2de15725eff508d8ab14f9c82|34;jdv/0|iosapp|t_335139774|appshare|Wxfriends|1612508702380|1612534293;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;android;3.7.0;10;0373263343266633-5663030363465326;network/wifi;model/Redmi Note 7;addressid/590846082;aid/07b34bf3e6006d5b;oaid/17975a142e67ec92;osVer/29;appBuild/1436;psn/OHNqtdhQKv1okyh7rB3HxjwI00ixJMNG|4;psq/3;adk/;ads/;pap/JA2020_3112531|3.7.0|ANDROID 10;osv/10;pv/2.3;jdv/;ref/activityId=8a8fabf3cccb417f8e691b6774938bc2;partner/xiaomi;apprpd/jsbqd_home;eufv/1;Mozilla/5.0 (Linux; Android 10; Redmi Note 7 Build/QKQ1.190910.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/88.0.4324.152 Mobile Safari/537.36',
|
||||
'jdltapp;android;3.7.0;10;3636566623663623-1693635613166646;network/wifi;model/ASUS_I001DA;addressid/1397761133;aid/ccef2fc2a96e1afd;oaid/;osVer/29;appBuild/1436;psn/T8087T0D82PHzJ4VUMGFrfB9dw4gUnKG|76;psq/5;adk/;ads/;pap/JA2020_3112531|3.7.0|ANDROID 10;osv/10;pv/73.5;jdv/0|kong|t_1002354188_|jingfen|2335e043b3344107a2750a781fde9a2e#/|1614097081426|1614097087;ref/com.jd.jdlite.lib.personal.view.fragment.JDPersonalFragment;partner/yingyongbao;apprpd/MyJD_Main;eufv/1;Mozilla/5.0 (Linux; Android 10; ASUS_I001DA Build/QKQ1.190825.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045140 Mobile Safari/537.36',
|
||||
'jdltapp;iPhone;3.7.0;14.4;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone10,2;addressid/138419019;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/5.7;apprpd/MyJD_Main;ref/MyJdMTAManager;psq/6;ads/;psn/4ee6af0db48fd605adb69b63f00fcbb51c2fc3f0|9;jdv/0|direct|-|none|-|1613705981655|1613823229;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.3;network/wifi;ADID/F9FD7728-2956-4DD1-8EDD-58B07950864C;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone10,1;addressid/1346909722;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/30.8;apprpd/;ref/JDLTSubMainPageViewController;psq/7;ads/;psn/40d4d4323eb3987226cae367d6b0d8be50f2c7b3|39;jdv/0|kong|t_1000252057_0|tuiguang|eba7648a0f4445aa9cfa6f35c6f36e15|1613995717959|1613995723;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.3;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;network/wifi;ADID/5D306F0D-A131-4B26-947E-166CCB9BFFFF;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone11,6;addressid/138164461;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/7.8;apprpd/;ref/JDLTSubMainPageViewController;psq/7;ads/;psn/d40e5d4a33c100e8527f779557c347569b49c304|7;jdv/0|kong|t_1001226363_|jingfen|3bf5372cb9cd445bbb270b8bc9a34f00|1608439066693|1608439068;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPad;3.7.0;14.5;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPad8,9;hasOCPay/0;appBuild/1017;supportBestPay/0;addressid/;pv/1.20;apprpd/MyJD_Main;ref/MyJdMTAManager;psq/5;ads/;psn/d9f5ddaa0160a20f32fb2c8bfd174fae7993c1b4|3;jdv/0|;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.5;Mozilla/5.0 (iPad; CPU OS 14_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.3;network/wifi;ADID/31548A9C-8A01-469A-B148-E7D841C91FD0;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone11,2;addressid/;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/10.5;apprpd/;ref/JDLTSubMainPageViewController;psq/4;ads/;psn/a858fb4b40e432ea32f80729916e6c3e910bb922|12;jdv/0|direct|-|none|-|1613898710373|1613898712;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.3;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;13.5;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone9,2;addressid/2237496805;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/13.6;apprpd/;ref/JDLTSubMainPageViewController;psq/5;ads/;psn/48e495dcf5dc398b4d46b27e9f15a2b427a154aa|15;jdv/0|direct|-|none|-|1613354874698|1613952828;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 13.5;Mozilla/5.0 (iPhone; CPU iPhone OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;android;3.7.0;10;3346332626262353-1666434336539336;network/wifi;model/ONEPLUS A6000;addressid/0;aid/3d3bbb25af44c59c;oaid/;osVer/29;appBuild/1436;psn/ECbc2EqmdSa7mDF1PS1GSrV/Tn7R1LS1|6;psq/8;adk/;ads/;pap/JA2020_3112531|3.7.0|ANDROID 10;osv/10;pv/2.67;jdv/0|direct|-|none|-|1613822479379|1613991194;ref/com.jd.jdlite.lib.personal.view.fragment.JDPersonalFragment;partner/oppo;apprpd/MyJD_Main;eufv/1;Mozilla/5.0 (Linux; Android 10; ONEPLUS A6000 Build/QKQ1.190716.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045140 Mobile Safari/537.36',
|
||||
'jdltapp;android;3.7.0;8.1.0;8363834353530333132333132373-43D2930366035323639333662383;network/wifi;model/16th Plus;addressid/0;aid/f909e5f2c464c7c6;oaid/;osVer/27;appBuild/1436;psn/c21YWvVr77Hn6 pOZfxXGY4TZrre1 UOL5hcPbCEDMo=|3;psq/10;adk/;ads/;pap/JA2020_3112531|3.7.0|ANDROID 8.1.0;osv/8.1.0;pv/2.15;jdv/;ref/com.jd.jdlite.lib.personal.view.fragment.JDPersonalFragment;partner/jsxdlyqj09;apprpd/MyJD_Main;eufv/1;Mozilla/5.0 (Linux; Android 8.1.0; 16th Plus Build/OPM1.171019.026; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045514 Mobile Safari/537.36',
|
||||
'jdltapp;android;3.7.0;11;1343467336264693-3343562673463613;network/wifi;model/Mi 10 Pro;addressid/0;aid/14d7cbd934eb7dc1;oaid/335f198546eb3141;osVer/30;appBuild/1436;psn/ZcQh/Wov sNYfZ6JUjTIUBu28 KT0T3u|1;psq/24;adk/;ads/;pap/JA2020_3112531|3.7.0|ANDROID 11;osv/11;pv/1.24;jdv/;ref/com.jd.jdlite.lib.jdlitemessage.view.activity.MessageCenterMainActivity;partner/xiaomi;apprpd/MessageCenter_MessageMerge;eufv/1;Mozilla/5.0 (Linux; Android 11; Mi 10 Pro Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/88.0.4324.181 Mobile Safari/537.36',
|
||||
'jdltapp;android;3.7.0;10;8353636393732346-6646931673935346;network/wifi;model/MI 8;addressid/1969998059;aid/8566972dfd9a795d;oaid/4a8b773c3e307386;osVer/29;appBuild/1436;psn/PhYbUtCsCJo r 1b8hwxjnY8rEv5S8XC|383;psq/14;adk/;ads/;pap/JA2020_3112531|3.7.0|ANDROID 10;osv/10;pv/374.14;jdv/0|iosapp|t_335139774|liteshare|CopyURL|1609306590175|1609306596;ref/com.jd.jdlite.lib.jdlitemessage.view.activity.MessageCenterMainActivity;partner/jsxdlyqj09;apprpd/MessageCenter_MessageMerge;eufv/1;Mozilla/5.0 (Linux; Android 10; MI 8 Build/QKQ1.190828.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045140 Mobile Safari/537.36',
|
||||
'jdltapp;iPhone;3.7.0;14.4;6d343c58764a908d4fa56609da4cb3a5cc1396d3;network/wifi;ADID/4965D884-3E61-4C4E-AEA7-9A8CE3742DA7;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone9,1;addressid/70390480;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/4.24;apprpd/MyJD_Main;ref/https%3A%2F%2Fjdcs.m.jd.com%2Fafter%2Findex.action%3FcategoryId%3D600%26v%3D6%26entry%3Dm_self_jd;psq/4;ads/;psn/6d343c58764a908d4fa56609da4cb3a5cc1396d3|17;jdv/0|;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;13.6.1;4606ddccdfe8f343f8137de7fea7f91fc4aef3a3;network/4g;ADID/C6FB6E20-D334-45FA-818A-7A4C58305202;hasUPPay/0;pushNoticeIsOpen/1;lang/zh_CN;model/iPhone10,1;addressid/;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/5.9;apprpd/MyJD_Main;ref/MyJdMTAManager;psq/8;ads/;psn/4606ddccdfe8f343f8137de7fea7f91fc4aef3a3|5;jdv/0|iosapp|t_335139774|liteshare|Qqfriends|1614206359106|1614206366;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 13.6.1;Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;3b6e79334551fc6f31952d338b996789d157c4e8;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone10,1;addressid/138051400;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/14.34;apprpd/MyJD_Main;ref/MyJdMTAManager;psq/12;ads/;psn/3b6e79334551fc6f31952d338b996789d157c4e8|46;jdv/0|kong|t_1001707023_|jingfen|e80d7173a4264f4c9a3addcac7da8b5d|1613837384708|1613858760;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;android;3.7.0;10;1346235693831363-2373837393932673;network/wifi;model/LYA-AL00;addressid/3321567203;aid/1d2e9816278799b7;oaid/00000000-0000-0000-0000-000000000000;osVer/29;appBuild/1436;psn/45VUZFTZJkhP5fAXbeBoQ0 O2GCB I|7;psq/5;adk/;ads/;pap/JA2020_3112531|3.7.0|ANDROID 10;osv/10;pv/5.8;jdv/0|iosapp|t_335139774|liteshare|CopyURL|1614066210320|1614066219;ref/com.jd.jdlite.lib.personal.view.fragment.JDPersonalFragment;partner/huawei;apprpd/MyJD_Main;eufv/1;Mozilla/5.0 (Linux; Android 10; LYA-AL00 Build/HUAWEILYA-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36',
|
||||
'jdltapp;iPhone;3.7.0;14.3;c2a8854e622a1b17a6c56c789f832f9d78ef1ba7;network/wifi;hasUPPay/0;pushNoticeIsOpen/1;lang/zh_CN;model/iPhone12,5;addressid/;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/3.9;apprpd/MyJD_Main;ref/MyJdMTAManager;psq/8;ads/;psn/c2a8854e622a1b17a6c56c789f832f9d78ef1ba7|6;jdv/0|direct|-|none|-|1613541016735|1613823566;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.3;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;android;3.7.0;9;;network/wifi;model/MIX 2S;addressid/;aid/f87efed6d9ed3c65;oaid/94739128ef9dd245;osVer/28;appBuild/1436;psn/R7wD/OWkQjYWxax1pDV6kTIDFPJCUid7C/nl2hHnUuI=|3;psq/13;adk/;ads/;pap/JA2020_3112531|3.7.0|ANDROID 9;osv/9;pv/1.42;jdv/;ref/activityId=8a8fabf3cccb417f8e691b6774938bc2;partner/xiaomi;apprpd/jsbqd_home;eufv/1;Mozilla/5.0 (Linux; Android 9; MIX 2S Build/PKQ1.180729.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/88.0.4324.181 Mobile Safari/537.36',
|
||||
'jdltapp;iPhone;3.7.0;14.4;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;android;3.7.0;10;network/wifi;Mozilla/5.0 (Linux; Android 10; Redmi Note 7 Build/QKQ1.190910.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/88.0.4324.152 Mobile Safari/537.36',
|
||||
'jdltapp;iPhone;3.7.0;14.4;network/3g;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
|
||||
'jdltapp;iPad;3.7.0;14.4;network/wifi;hasUPPay/0;pushNoticeIsOpen/1;lang/zh_CN;model/iPad6,3;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/231.11;pap/JA2020_3112531|3.7.0|IOS 14.4;apprpd/;psn/f5e7b7980fb50efc9c294ac38653c1584846c3db|305;usc/kong;jdv/0|kong|t_1000170135|tuiguang|notset|1613606450668|1613606450;umd/tuiguang;psq/2;ucp/t_1000170135;app_device/IOS;utr/notset;ref/JDLTRedPacketViewController;adk/;ads/;Mozilla/5.0 (iPad; CPU OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;13.5;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone8,1;addressid/669949466;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/9.11;apprpd/;ref/JDLTSubMainPageViewController;psq/10;ads/;psn/500a795cb2abae60b877ee4a1930557a800bef1c|11;jdv/;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 13.5;Mozilla/5.0 (iPhone; CPU iPhone OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.3;network/3g;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone13,4;addressid/;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/4.47;apprpd/;ref/JDLTSubMainPageViewController;psq/8;ads/;psn/21631ed983b3e854a3154b0336413825ad0d6783|9;jdv/0|direct|-|none|-|1614150725100|1614225882;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.3;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.3;network/3g;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone13,4;addressid/;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/4.47;apprpd/;ref/JDLTSubMainPageViewController;psq/8;ads/;psn/21631ed983b3e854a3154b0336413825ad0d6783|9;jdv/0|direct|-|none|-|1614150725100|1614225882;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.3;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone13,2;addressid/;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/3.15;apprpd/;ref/https%3A%2F%2Fjdcs.m.jd.com%2Fchat%2Findex.action%3Fentry%3Djd_m_JiSuCommodity%26pid%3D7763388%26lng%3D118.159665%26lat%3D24.504633%26sid%3D31cddc2d58f6e36bf2c31c4e8a79767w%26un_area%3D16_1315_3486_0;psq/12;ads/;psn/c10e0db6f15dec57a94637365f4c3d43e05bbd48|4;jdv/0|;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone13,2;addressid/;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/3.15;apprpd/;ref/https%3A%2F%2Fjdcs.m.jd.com%2Fchat%2Findex.action%3Fentry%3Djd_m_JiSuCommodity%26pid%3D7763388%26lng%3D118.159665%26lat%3D24.504633%26sid%3D31cddc2d58f6e36bf2c31c4e8a79767w%26un_area%3D16_1315_3486_0;psq/12;ads/;psn/c10e0db6f15dec57a94637365f4c3d43e05bbd48|4;jdv/0|;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone13,2;addressid/;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/3.15;apprpd/;ref/https%3A%2F%2Fjdcs.m.jd.com%2Fchat%2Findex.action%3Fentry%3Djd_m_JiSuCommodity%26pid%3D7763388%26lng%3D118.159665%26lat%3D24.504633%26sid%3D31cddc2d58f6e36bf2c31c4e8a79767w%26un_area%3D16_1315_3486_0;psq/12;ads/;psn/c10e0db6f15dec57a94637365f4c3d43e05bbd48|4;jdv/0|;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone11,6;hasOCPay/0;appBuild/1017;supportBestPay/0;addressid/2813715704;pv/67.38;apprpd/MyJD_Main;ref/https%3A%2F%2Fh5.m.jd.com%2FbabelDiy%2FZeus%2F2ynE8QDtc2svd36VowmYWBzzDdK6%2Findex.html%3Flng%3D103.957532%26lat%3D30.626962%26sid%3D4fe8ef4283b24723a7bb30ee87c18b2w%26un_area%3D22_1930_49324_52512;psq/4;ads/;psn/5aef178f95931bdbbde849ea9e2fc62b18bc5829|127;jdv/0|direct|-|none|-|1612588090667|1613822580;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.3;;network/4g;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone11,2;addressid/;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/6.28;apprpd/;ref/JDLTRedPacketViewController;psq/3;ads/;psn/d7beab54ae7758fa896c193b49470204fbb8fce9|8;jdv/0|kong|t_1001707023_|jingfen|79ad0319fa4d47e38521a616d80bc4bd|1613800945610|1613824900;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.3;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.3;network/4g;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone11,2;addressid/;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/6.28;apprpd/;ref/JDLTRedPacketViewController;psq/3;ads/;psn/d7beab54ae7758fa896c193b49470204fbb8fce9|8;jdv/0|kong|t_1001707023_|jingfen|79ad0319fa4d47e38521a616d80bc4bd|1613800945610|1613824900;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.3;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.3;;network/4g;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone11,2;addressid/;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/6.28;apprpd/;ref/JDLTRedPacketViewController;psq/3;ads/;psn/d7beab54ae7758fa896c193b49470204fbb8fce9|8;jdv/0|kong|t_1001707023_|jingfen|79ad0319fa4d47e38521a616d80bc4bd|1613800945610|1613824900;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.3;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.3;network/4g;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone11,2;addressid/;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/6.28;apprpd/;ref/JDLTRedPacketViewController;psq/3;ads/;psn/d7beab54ae7758fa896c193b49470204fbb8fce9|8;jdv/0|kong|t_1001707023_|jingfen|79ad0319fa4d47e38521a616d80bc4bd|1613800945610|1613824900;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.3;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.3;network/4g;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone11,2;addressid/;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/6.28;apprpd/;ref/JDLTRedPacketViewController;psq/3;ads/;psn/d7beab54ae7758fa896c193b49470204fbb8fce9|8;jdv/0|kong|t_1001707023_|jingfen|79ad0319fa4d47e38521a616d80bc4bd|1613800945610|1613824900;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.3;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;network/4g;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone12,1;addressid/3104834020;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/4.6;apprpd/;ref/JDLTSubMainPageViewController;psq/5;ads/;psn/c633e62b5a4ad0fdd93d9862bdcacfa8f3ecef63|6;jdv/0|;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.3;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone10,1;addressid/1346909722;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/30.8;apprpd/;ref/JDLTSubMainPageViewController;psq/7;ads/;psn/40d4d4323eb3987226cae367d6b0d8be50f2c7b3|39;jdv/0|kong|t_1000252057_0|tuiguang|eba7648a0f4445aa9cfa6f35c6f36e15|1613995717959|1613995723;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.3;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.3;network/wifi;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone10,1;addressid/1346909722;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/30.8;apprpd/;ref/JDLTSubMainPageViewController;psq/7;ads/;psn/40d4d4323eb3987226cae367d6b0d8be50f2c7b3|39;jdv/0|kong|t_1000252057_0|tuiguang|eba7648a0f4445aa9cfa6f35c6f36e15|1613995717959|1613995723;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.3;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone11,6;addressid/138164461;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/7.8;apprpd/;ref/JDLTSubMainPageViewController;psq/7;ads/;psn/d40e5d4a33c100e8527f779557c347569b49c304|7;jdv/0|kong|t_1001226363_|jingfen|3bf5372cb9cd445bbb270b8bc9a34f00|1608439066693|1608439068;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone11,6;addressid/138164461;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/7.8;apprpd/;ref/JDLTSubMainPageViewController;psq/7;ads/;psn/d40e5d4a33c100e8527f779557c347569b49c304|7;jdv/0|kong|t_1001226363_|jingfen|3bf5372cb9cd445bbb270b8bc9a34f00|1608439066693|1608439068;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone11,6;addressid/138164461;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/7.8;apprpd/;ref/JDLTSubMainPageViewController;psq/7;ads/;psn/d40e5d4a33c100e8527f779557c347569b49c304|7;jdv/0|kong|t_1001226363_|jingfen|3bf5372cb9cd445bbb270b8bc9a34f00|1608439066693|1608439068;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;13.5;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone9,2;addressid/2237496805;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/13.6;apprpd/;ref/JDLTSubMainPageViewController;psq/5;ads/;psn/48e495dcf5dc398b4d46b27e9f15a2b427a154aa|15;jdv/0|direct|-|none|-|1613354874698|1613952828;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 13.5;Mozilla/5.0 (iPhone; CPU iPhone OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;android;3.7.0;10;network/wifi;model/ONEPLUS A6000;addressid/0;aid/3d3bbb25af44c59c;oaid/;osVer/29;appBuild/1436;psn/ECbc2EqmdSa7mDF1PS1GSrV/Tn7R1LS1|6;psq/8;adk/;ads/;pap/JA2020_3112531|3.7.0|ANDROID 10;osv/10;pv/2.67;jdv/0|direct|-|none|-|1613822479379|1613991194;ref/com.jd.jdlite.lib.personal.view.fragment.JDPersonalFragment;partner/oppo;apprpd/MyJD_Main;eufv/1;Mozilla/5.0 (Linux; Android 10; ONEPLUS A6000 Build/QKQ1.190716.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045140 Mobile Safari/537.36',
|
||||
'jdltapp;android;3.7.0;8.1.0;network/wifi;model/16th Plus;addressid/0;aid/f909e5f2c464c7c6;oaid/;osVer/27;appBuild/1436;psn/c21YWvVr77Hn6 pOZfxXGY4TZrre1 UOL5hcPbCEDMo=|3;psq/10;adk/;ads/;pap/JA2020_3112531|3.7.0|ANDROID 8.1.0;osv/8.1.0;pv/2.15;jdv/;ref/com.jd.jdlite.lib.personal.view.fragment.JDPersonalFragment;partner/jsxdlyqj09;apprpd/MyJD_Main;eufv/1;Mozilla/5.0 (Linux; Android 8.1.0; 16th Plus Build/OPM1.171019.026; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045514 Mobile Safari/537.36',
|
||||
'jdltapp;android;3.7.0;11;network/wifi;model/Mi 10 Pro;addressid/0;aid/14d7cbd934eb7dc1;oaid/335f198546eb3141;osVer/30;appBuild/1436;psn/ZcQh/Wov sNYfZ6JUjTIUBu28 KT0T3u|1;psq/24;adk/;ads/;pap/JA2020_3112531|3.7.0|ANDROID 11;osv/11;pv/1.24;jdv/;ref/com.jd.jdlite.lib.jdlitemessage.view.activity.MessageCenterMainActivity;partner/xiaomi;apprpd/MessageCenter_MessageMerge;eufv/1;Mozilla/5.0 (Linux; Android 11; Mi 10 Pro Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/88.0.4324.181 Mobile Safari/537.36',
|
||||
'jdltapp;android;3.7.0;10;network/wifi;model/MI 8;addressid/1969998059;aid/8566972dfd9a795d;oaid/4a8b773c3e307386;osVer/29;appBuild/1436;psn/PhYbUtCsCJo r 1b8hwxjnY8rEv5S8XC|383;psq/14;adk/;ads/;pap/JA2020_3112531|3.7.0|ANDROID 10;osv/10;pv/374.14;jdv/0|iosapp|t_335139774|liteshare|CopyURL|1609306590175|1609306596;ref/com.jd.jdlite.lib.jdlitemessage.view.activity.MessageCenterMainActivity;partner/jsxdlyqj09;apprpd/MessageCenter_MessageMerge;eufv/1;Mozilla/5.0 (Linux; Android 10; MI 8 Build/QKQ1.190828.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045140 Mobile Safari/537.36',
|
||||
'jdltapp;iPhone;3.7.0;14.4;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone8,4;addressid/1477231693;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/21.15;apprpd/MyJD_Main;ref/https%3A%2F%2Fgold.jd.com%2F%3Flng%3D0.000000%26lat%3D0.000000%26sid%3D4584eb84dc00141b0d58e000583a338w%26un_area%3D19_1607_3155_62114;psq/0;ads/;psn/2c822e59db319590266cc83b78c4a943783d0077|46;jdv/0|;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone9,1;addressid/70390480;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/4.24;apprpd/MyJD_Main;ref/https%3A%2F%2Fjdcs.m.jd.com%2Fafter%2Findex.action%3FcategoryId%3D600%26v%3D6%26entry%3Dm_self_jd;psq/4;ads/;psn/6d343c58764a908d4fa56609da4cb3a5cc1396d3|17;jdv/0|;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone9,1;addressid/70390480;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/4.24;apprpd/MyJD_Main;ref/https%3A%2F%2Fjdcs.m.jd.com%2Fafter%2Findex.action%3FcategoryId%3D600%26v%3D6%26entry%3Dm_self_jd;psq/4;ads/;psn/6d343c58764a908d4fa56609da4cb3a5cc1396d3|17;jdv/0|;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;network/wifi;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone9,1;addressid/70390480;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/4.24;apprpd/MyJD_Main;ref/https%3A%2F%2Fjdcs.m.jd.com%2Fafter%2Findex.action%3FcategoryId%3D600%26v%3D6%26entry%3Dm_self_jd;psq/4;ads/;psn/6d343c58764a908d4fa56609da4cb3a5cc1396d3|17;jdv/0|;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone9,1;addressid/70390480;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/4.24;apprpd/MyJD_Main;ref/https%3A%2F%2Fjdcs.m.jd.com%2Fafter%2Findex.action%3FcategoryId%3D600%26v%3D6%26entry%3Dm_self_jd;psq/4;ads/;psn/6d343c58764a908d4fa56609da4cb3a5cc1396d3|17;jdv/0|;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPhone;3.7.0;14.4;network/4g;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPhone12,3;hasOCPay/0;appBuild/1017;supportBestPay/0;addressid/;pv/3.49;apprpd/MyJD_Main;ref/MyJdMTAManager;psq/7;ads/;psn/9e0e0ea9c6801dfd53f2e50ffaa7f84c7b40cd15|6;jdv/0|;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
'jdltapp;iPad;3.7.0;14.4;network/wifi;hasUPPay/0;pushNoticeIsOpen/0;lang/zh_CN;model/iPad7,5;addressid/;hasOCPay/0;appBuild/1017;supportBestPay/0;pv/4.14;apprpd/MyJD_Main;ref/MyJdMTAManager;psq/3;ads/;psn/956c074c769cd2eeab2e36fca24ad4c9e469751a|8;jdv/0|;adk/;app_device/IOS;pap/JA2020_3112531|3.7.0|IOS 14.4;Mozilla/5.0 (iPad; CPU OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||||
]
|
||||
/**
|
||||
* 生成随机数字
|
||||
* @param {number} min 最小值(包含)
|
||||
* @param {number} max 最大值(不包含)
|
||||
*/
|
||||
function randomNumber(min = 0, max = 100) {
|
||||
return Math.min(Math.floor(min + Math.random() * (max - min)), max);
|
||||
}
|
||||
const USER_AGENT = USER_AGENTS[randomNumber(0, USER_AGENTS.length)];
|
||||
|
||||
module.exports = {
|
||||
USER_AGENT
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
|
||||
## 6dy
|
||||
|
||||
>加密审查,无重复,默认不开卡加购,内部互助(可调模式);
|
||||
|
||||
|
||||
>欢迎大家issue、pr,会一一回复!
|
||||
|
||||
|
||||
### 注意ck安全,谨慎执行不明来历的js、app、exe、插件等,过期ck都能复活(还有其他不为人知的手段。。。)!
|
||||
|
||||
### 已知MaiARK短信登录工具偷CK,不要使用!!!
|
||||
|
||||
### 防走失[TG频道](https://t.me/dylan_jdpro)
|
||||
|
||||
### 一键部署(2.11.3版本青龙,默认国内机拉库命令,建好后根据自己情况调整)
|
||||
|
||||
使用root用户运行下面一串命令,仅在Centos/Ubuntu系统测试,其他系统自测
|
||||
|
||||
```
|
||||
curl -sSL https://js.dayplus.xyz/https://raw.githubusercontent.com/6dylan6/jdpro/main/docker/ql1key.sh -o install.sh && bash install.sh
|
||||
```
|
||||
|
||||
## 拉库指令
|
||||
|
||||
【注意】2.11.1前版本青龙config.sh配置把GithubProxyUrl="https://ghproxy.com/ (差不在多19行)" 修改为GithubProxyUrl="",否则拉取失败,以上版本无需配置。
|
||||
|
||||
2.13版本以上青龙拉库方式变了,到订阅管理新建订阅,正确配置[参考](https://github.com/6dylan6/jdpro/discussions/680)
|
||||
|
||||
国内机用下面指令(带代理):
|
||||
|
||||
```
|
||||
ql repo https://ghproxy.com/https://github.com/6dylan6/jdpro.git "jd_|jx_|jddj_" "backUp" "^jd[^_]|USER|JD|function|sendNotify"
|
||||
|
||||
```
|
||||
如默认代理ghproxy.com 拉不动,换备用的 js.nbplay.site 试试
|
||||
|
||||
国外机用下面指令(无需代理):
|
||||
|
||||
```
|
||||
ql repo https://github.com/6dylan6/jdpro.git "jd_|jx_|jddj_" "backUp" "^jd[^_]|USER|JD|function|sendNotify"
|
||||
|
||||
```
|
||||
|
||||
Gitee版不能正常拉取,已停止维护!(20220711)
|
||||
|
||||
|
||||
任务定时建议(每2小时的45分更新) 45 7-23/2 * * *
|
||||
|
||||
(定时可随意,不一定按这个来,但不要设置为每秒或每分钟)
|
||||
|
||||
|
||||
线报监控类脚本,需要的到 https://github.com/6dylan6/jdm.git
|
||||
|
||||
带图自动评价(PC版CK)需要的到 https://github.com/6dylan6/auto_comment.git
|
||||
|
||||
|
||||
## 使用流程
|
||||
|
||||
1、青龙部署。
|
||||
|
||||
2、修改青龙config.sh配置,差不多在17行(特别注意,没有修改此配置,任务拉不全,一键部署可忽略此处);
|
||||
|
||||
RepoFileExtensions="js py"修改为 RepoFileExtensions="js py sh ts" 保存;
|
||||
|
||||
3、新建拉库任务或订阅,并执行,刷新浏览器即可看到添加的任务;
|
||||
|
||||
4、添加CK环境变量,多CK不要写在一起,每个都新建JD_COOKIE变量;
|
||||
|
||||
5,通知key变量请添加到配置管理config.sh文件,否则收不到通知;
|
||||
|
||||
|
||||
|
||||
<details>
|
||||
<summary>使用技巧与问题解答</summary>
|
||||
<pre><code>
|
||||
|
||||
1、任务并发和分组
|
||||
|
||||
并发配置方法:
|
||||
|
||||
在任务后面加conc JD_COOKIE
|
||||
|
||||
如 task XXXXX.js conc JD_COOKIE
|
||||
|
||||
任务分组运行方法:
|
||||
|
||||
在任务后面加desi JD_COOKIE 需要运行的ck序号
|
||||
|
||||
如 task XXXX.js desi JD_COOKIE 1-10 前10个一组运行,2 8 9就是第2/8/9序号的ck执行,以此类推。
|
||||
|
||||
2、通知支持一对一推送和显示备注(需用本库sendnotify文件),还有分组通知等用法参考[notify.md](./notify.md)
|
||||
|
||||
备注显示变量如下
|
||||
|
||||
export NOTIFY_SHOWNAMETYPE="1" 不做任何变动
|
||||
|
||||
export NOTIFY_SHOWNAMETYPE="2" 效果是 : 账号名称:别名(备注)
|
||||
|
||||
export NOTIFY_SHOWNAMETYPE="3" 效果是 : 账号名称:pin(备注)
|
||||
|
||||
export NOTIFY_SHOWNAMETYPE="4" 效果是 : 账号名称:备注
|
||||
|
||||
3、因为青龙有随机延时(可以在配置文件设置为0,默认300秒),所以涉及准点运行的任务,最后加now,如果是desi或conc不用加也会准时跑。
|
||||
|
||||
4、青龙系统通知(新增删除任务、登录等通知),需把通知变量写到config.sh文件,在环境变量里只发脚本运行通知哈。
|
||||
|
||||
5、如果通知文件发现和库里的不一致,那是被青龙自带的覆盖了,手动拷贝一份到deps目录下。
|
||||
|
||||
6、建议调整任务运行超时时间,青龙默认1小时有些跑不完就被强制结束,config.sh里配置。CommandTimeoutTime="3h" 即改为3小时,根据自己ck数量调整。
|
||||
</code></pre>
|
||||
</details>
|
||||
|
||||
|
||||
## 互助模式使用说明
|
||||
|
||||
集成互助研究院taskbefore,code模块,可实现临时禁止某些CK参加所有活动或某些活动功能,实现重组CK顺序功能,包括随机、优先、轮换、组队、分段等功能
|
||||
|
||||
常用变量举例:
|
||||
|
||||
Recombin_CK_Mode="1" 全部顺序随机
|
||||
|
||||
Recombin_CK_Mode="2" Recombin_CK_ARG1="15" 假设有100个CK,前15个CK按正常顺序靠前,其余CK随机乱序
|
||||
|
||||
Recombin_CK_Mode="3" Recombin_CK_ARG1="5" Recombin_CK_ARG2="5" 假设有100个CK,希望前5个账号始终保持在前部,剩余95个账号按照轮换模式每天轮换5个
|
||||
|
||||
其他用法具体参考[文档](https://docs.qq.com/doc/DTXh6QUVjRXJ1TFdN)
|
||||
|
||||
|
||||
## 支持的通知方式
|
||||
|
||||
server酱,go-cqhttp,pushdeer,Bark App,tg bot,钉钉bot,企业微信bot,企业微信应用消息,飞书,iGot,push plus,WxPusher,gotify
|
||||
|
||||
请在配置管理config文件里写变量
|
||||
@@ -0,0 +1,399 @@
|
||||
import axios from "axios"
|
||||
import {Md5} from "ts-md5"
|
||||
import * as dotenv from "dotenv"
|
||||
import {existsSync, readFileSync} from "fs"
|
||||
import {sendNotify} from './sendNotify'
|
||||
|
||||
dotenv.config()
|
||||
|
||||
let fingerprint: string | number, token: string = '', enCryptMethodJD: any
|
||||
|
||||
const USER_AGENTS: Array<string> = [
|
||||
"jdapp;android;10.0.2;10;network/wifi;Mozilla/5.0 (Linux; Android 10; ONEPLUS A5010 Build/QKQ1.191014.012; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045230 Mobile Safari/537.36",
|
||||
"jdapp;iPhone;10.0.2;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",
|
||||
"jdapp;android;10.0.2;9;network/4g;Mozilla/5.0 (Linux; Android 9; Mi Note 3 Build/PKQ1.181007.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045131 Mobile Safari/537.36",
|
||||
"jdapp;android;10.0.2;10;network/wifi;Mozilla/5.0 (Linux; Android 10; GM1910 Build/QKQ1.190716.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045230 Mobile Safari/537.36",
|
||||
"jdapp;android;10.0.2;9;network/wifi;Mozilla/5.0 (Linux; Android 9; 16T Build/PKQ1.190616.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36",
|
||||
"jdapp;iPhone;10.0.2;13.6;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1",
|
||||
"jdapp;iPhone;10.0.2;13.6;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1",
|
||||
"jdapp;iPhone;10.0.2;13.5;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1",
|
||||
"jdapp;iPhone;10.0.2;14.1;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1",
|
||||
"jdapp;iPhone;10.0.2;13.3;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1",
|
||||
"jdapp;iPhone;10.0.2;13.7;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1",
|
||||
"jdapp;iPhone;10.0.2;14.1;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1",
|
||||
"jdapp;iPhone;10.0.2;13.3;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1",
|
||||
"jdapp;iPhone;10.0.2;13.4;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1",
|
||||
"jdapp;iPhone;10.0.2;14.3;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1",
|
||||
"jdapp;android;10.0.2;9;network/wifi;Mozilla/5.0 (Linux; Android 9; MI 6 Build/PKQ1.190118.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36",
|
||||
"jdapp;android;10.0.2;11;network/wifi;Mozilla/5.0 (Linux; Android 11; Redmi K30 5G Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045511 Mobile Safari/537.36",
|
||||
"jdapp;iPhone;10.0.2;11.4;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 11_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15F79",
|
||||
"jdapp;android;10.0.2;10;;network/wifi;Mozilla/5.0 (Linux; Android 10; M2006J10C Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045230 Mobile Safari/537.36",
|
||||
"jdapp;android;10.0.2;10;network/wifi;Mozilla/5.0 (Linux; Android 10; M2006J10C Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045230 Mobile Safari/537.36",
|
||||
"jdapp;android;10.0.2;10;network/wifi;Mozilla/5.0 (Linux; Android 10; ONEPLUS A6000 Build/QKQ1.190716.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045224 Mobile Safari/537.36",
|
||||
"jdapp;android;10.0.2;9;network/wifi;Mozilla/5.0 (Linux; Android 9; MHA-AL00 Build/HUAWEIMHA-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36",
|
||||
"jdapp;android;10.0.2;8.1.0;network/wifi;Mozilla/5.0 (Linux; Android 8.1.0; 16 X Build/OPM1.171019.026; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36",
|
||||
"jdapp;android;10.0.2;8.0.0;network/wifi;Mozilla/5.0 (Linux; Android 8.0.0; HTC U-3w Build/OPR6.170623.013; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36",
|
||||
"jdapp;iPhone;10.0.2;14.0.1;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1",
|
||||
"jdapp;android;10.0.2;10;network/wifi;Mozilla/5.0 (Linux; Android 10; LYA-AL00 Build/HUAWEILYA-AL00L; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045230 Mobile Safari/537.36",
|
||||
"jdapp;iPhone;10.0.2;14.2;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1",
|
||||
"jdapp;iPhone;10.0.2;14.3;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1",
|
||||
"jdapp;iPhone;10.0.2;14.2;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1",
|
||||
"jdapp;android;10.0.2;8.1.0;network/wifi;Mozilla/5.0 (Linux; Android 8.1.0; MI 8 Build/OPM1.171019.026; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045131 Mobile Safari/537.36",
|
||||
"jdapp;android;10.0.2;10;network/wifi;Mozilla/5.0 (Linux; Android 10; Redmi K20 Pro Premium Edition Build/QKQ1.190825.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045227 Mobile Safari/537.36",
|
||||
"jdapp;iPhone;10.0.2;14.3;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1",
|
||||
"jdapp;iPhone;10.0.2;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",
|
||||
"jdapp;android;10.0.2;11;network/wifi;Mozilla/5.0 (Linux; Android 11; Redmi K20 Pro Premium Edition Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045513 Mobile Safari/537.36",
|
||||
"jdapp;android;10.0.2;10;network/wifi;Mozilla/5.0 (Linux; Android 10; MI 8 Build/QKQ1.190828.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045227 Mobile Safari/537.36",
|
||||
"jdapp;iPhone;10.0.2;14.1;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1",
|
||||
]
|
||||
|
||||
function TotalBean(cookie: string) {
|
||||
return {
|
||||
cookie: cookie,
|
||||
isLogin: true,
|
||||
nickName: ''
|
||||
}
|
||||
}
|
||||
|
||||
function getRandomNumberByRange(start: number, end: number) {
|
||||
end <= start && (end = start + 100)
|
||||
return Math.floor(Math.random() * (end - start) + start)
|
||||
}
|
||||
|
||||
let USER_AGENT = USER_AGENTS[getRandomNumberByRange(0, USER_AGENTS.length)]
|
||||
|
||||
async function getBeanShareCode(cookie: string) {
|
||||
let {data}: any = await axios.post('https://api.m.jd.com/client.action',
|
||||
`functionId=plantBeanIndex&body=${encodeURIComponent(
|
||||
JSON.stringify({version: "9.0.0.1", "monitor_source": "plant_app_plant_index", "monitor_refer": ""})
|
||||
)}&appid=ld&client=apple&area=5_274_49707_49973&build=167283&clientVersion=9.1.0`, {
|
||||
headers: {
|
||||
Cookie: cookie,
|
||||
Host: "api.m.jd.com",
|
||||
Accept: "*/*",
|
||||
Connection: "keep-alive",
|
||||
"User-Agent": USER_AGENT
|
||||
}
|
||||
})
|
||||
if (data.data?.jwordShareInfo?.shareUrl)
|
||||
return data.data.jwordShareInfo.shareUrl.split('Uuid=')![1]
|
||||
else
|
||||
return ''
|
||||
}
|
||||
|
||||
async function getFarmShareCode(cookie: string) {
|
||||
let {data}: any = await axios.post('https://api.m.jd.com/client.action?functionId=initForFarm', `body=${encodeURIComponent(JSON.stringify({"version": 4}))}&appid=wh5&clientVersion=9.1.0`, {
|
||||
headers: {
|
||||
"cookie": cookie,
|
||||
"origin": "https://home.m.jd.com",
|
||||
"referer": "https://home.m.jd.com/myJd/newhome.action",
|
||||
"User-Agent": USER_AGENT,
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
}
|
||||
})
|
||||
|
||||
if (data.farmUserPro)
|
||||
return data.farmUserPro.shareCode
|
||||
else
|
||||
return ''
|
||||
}
|
||||
|
||||
async function requireConfig(check: boolean = false): Promise<string[]> {
|
||||
let cookiesArr: string[] = []
|
||||
const jdCookieNode = require('./jdCookie.js')
|
||||
let keys: string[] = Object.keys(jdCookieNode)
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
let cookie = jdCookieNode[keys[i]]
|
||||
if (!check) {
|
||||
cookiesArr.push(cookie)
|
||||
} else {
|
||||
if (await checkCookie(cookie)) {
|
||||
cookiesArr.push(cookie)
|
||||
} else {
|
||||
let username = decodeURIComponent(jdCookieNode[keys[i]].match(/pt_pin=([^;]*)/)![1])
|
||||
console.log('Cookie失效', username)
|
||||
await sendNotify('Cookie失效', '【京东账号】' + username)
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(`共${cookiesArr.length}个京东账号\n`)
|
||||
return cookiesArr
|
||||
}
|
||||
|
||||
async function checkCookie(cookie: string) {
|
||||
await wait(3000)
|
||||
try {
|
||||
let {data}: any = await axios.get(`https://api.m.jd.com/client.action?functionId=GetJDUserInfoUnion&appid=jd-cphdeveloper-m&body=${encodeURIComponent(JSON.stringify({"orgFlag": "JD_PinGou_New", "callSource": "mainorder", "channel": 4, "isHomewhite": 0, "sceneval": 2}))}&loginType=2&_=${Date.now()}&sceneval=2&g_login_type=1&callback=GetJDUserInfoUnion&g_ty=ls`, {
|
||||
headers: {
|
||||
'authority': 'api.m.jd.com',
|
||||
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1',
|
||||
'referer': 'https://home.m.jd.com/',
|
||||
'cookie': cookie
|
||||
}
|
||||
})
|
||||
data = JSON.parse(data.match(/GetJDUserInfoUnion\((.*)\)/)[1])
|
||||
return data.retcode === '0';
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function wait(timeout: number) {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, timeout)
|
||||
})
|
||||
}
|
||||
|
||||
async function requestAlgo(appId: number = 10032) {
|
||||
fingerprint = generateFp()
|
||||
return new Promise<void>(async resolve => {
|
||||
let {data}: any = await axios.post('https://cactus.jd.com/request_algo?g_ty=ajax', {
|
||||
"version": "1.0",
|
||||
"fp": fingerprint,
|
||||
"appId": appId,
|
||||
"timestamp": Date.now(),
|
||||
"platform": "web",
|
||||
"expandParams": ""
|
||||
}, {
|
||||
"headers": {
|
||||
'Authority': 'cactus.jd.com',
|
||||
'Pragma': 'no-cache',
|
||||
'Cache-Control': 'no-cache',
|
||||
'Accept': 'application/json',
|
||||
'User-Agent': USER_AGENT,
|
||||
'Content-Type': 'application/json',
|
||||
'Origin': 'https://st.jingxi.com',
|
||||
'Sec-Fetch-Site': 'cross-site',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
'Referer': 'https://st.jingxi.com/',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.9,zh-TW;q=0.8,en;q=0.7'
|
||||
},
|
||||
})
|
||||
if (data['status'] === 200) {
|
||||
token = data.data.result.tk
|
||||
let enCryptMethodJDString = data.data.result.algo
|
||||
if (enCryptMethodJDString) enCryptMethodJD = new Function(`return ${enCryptMethodJDString}`)()
|
||||
} else {
|
||||
console.log(`fp: ${fingerprint}`)
|
||||
console.log('request_algo 签名参数API请求失败:')
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
|
||||
function generateFp() {
|
||||
let e = "0123456789"
|
||||
let a = 13
|
||||
let i = ''
|
||||
for (; a--;)
|
||||
i += e[Math.random() * e.length | 0]
|
||||
return (i + Date.now()).slice(0, 16)
|
||||
}
|
||||
|
||||
function getJxToken(cookie: string, phoneId: string = '') {
|
||||
function generateStr(input: number) {
|
||||
let src = 'abcdefghijklmnopqrstuvwxyz1234567890'
|
||||
let res = ''
|
||||
for (let i = 0; i < input; i++) {
|
||||
res += src[Math.floor(src.length * Math.random())]
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
if (!phoneId)
|
||||
phoneId = generateStr(40)
|
||||
let timestamp = Date.now().toString()
|
||||
let nickname = cookie.match(/pt_pin=([^;]*)/)![1]
|
||||
let jstoken = Md5.hashStr('' + decodeURIComponent(nickname) + timestamp + phoneId + 'tPOamqCuk9NLgVPAljUyIHcPRmKlVxDy')
|
||||
return {
|
||||
'strPgtimestamp': timestamp,
|
||||
'strPhoneID': phoneId,
|
||||
'strPgUUNum': jstoken
|
||||
}
|
||||
}
|
||||
|
||||
function exceptCookie(filename: string = 'x.ts') {
|
||||
let except: any = []
|
||||
if (existsSync('./utils/exceptCookie.json')) {
|
||||
try {
|
||||
except = JSON.parse(readFileSync('./utils/exceptCookie.json').toString() || '{}')[filename] || []
|
||||
} catch (e) {
|
||||
console.log('./utils/exceptCookie.json JSON格式错误')
|
||||
}
|
||||
}
|
||||
return except
|
||||
}
|
||||
|
||||
function randomString(e: number, word?: number) {
|
||||
e = e || 32
|
||||
let t = word === 26 ? "012345678abcdefghijklmnopqrstuvwxyz" : "0123456789abcdef", a = t.length, n = ""
|
||||
for (let i = 0; i < e; i++)
|
||||
n += t.charAt(Math.floor(Math.random() * a))
|
||||
return n
|
||||
}
|
||||
|
||||
function o2s(arr: object, title: string = '') {
|
||||
title ? console.log(title, JSON.stringify(arr)) : console.log(JSON.stringify(arr))
|
||||
}
|
||||
|
||||
function randomNumString(e: number) {
|
||||
e = e || 32
|
||||
let t = '0123456789', a = t.length, n = ""
|
||||
for (let i = 0; i < e; i++)
|
||||
n += t.charAt(Math.floor(Math.random() * a))
|
||||
return n
|
||||
}
|
||||
|
||||
function randomWord(n: number = 1) {
|
||||
let t = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', a = t.length
|
||||
let rnd: string = ''
|
||||
for (let i = 0; i < n; i++) {
|
||||
rnd += t.charAt(Math.floor(Math.random() * a))
|
||||
}
|
||||
return rnd
|
||||
}
|
||||
|
||||
async function getshareCodeHW(key: string) {
|
||||
let shareCodeHW: string[] = []
|
||||
for (let i = 0; i < 5; i++) {
|
||||
try {
|
||||
let {data}: any = await axios.get('https://api.jdsharecode.xyz/api/HW_CODES')
|
||||
shareCodeHW = data[key] || []
|
||||
if (shareCodeHW.length !== 0) {
|
||||
break
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("getshareCodeHW Error, Retry...")
|
||||
await wait(getRandomNumberByRange(2000, 6000))
|
||||
}
|
||||
}
|
||||
return shareCodeHW
|
||||
}
|
||||
|
||||
async function getShareCodePool(key: string, num: number) {
|
||||
let shareCode: string[] = []
|
||||
for (let i = 0; i < 2; i++) {
|
||||
try {
|
||||
let {data}: any = await axios.get(`https://api.jdsharecode.xyz/api/${key}/${num}`)
|
||||
shareCode = data.data || []
|
||||
console.log(`随机获取${num}个${key}成功:${JSON.stringify(shareCode)}`)
|
||||
if (shareCode.length !== 0) {
|
||||
break
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("getShareCodePool Error, Retry...")
|
||||
await wait(getRandomNumberByRange(2000, 6000))
|
||||
}
|
||||
}
|
||||
return shareCode
|
||||
}
|
||||
|
||||
/*async function wechat_app_msg(title: string, content: string, user: string) {
|
||||
let corpid: string = "", corpsecret: string = ""
|
||||
let {data: gettoken} = await axios.get(`https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=${corpid}&corpsecret=${corpsecret}`)
|
||||
let access_token: string = gettoken.access_token
|
||||
|
||||
let {data: send} = await axios.post(`https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=${access_token}`, {
|
||||
"touser": user,
|
||||
"msgtype": "text",
|
||||
"agentid": 1000002,
|
||||
"text": {
|
||||
"content": `${title}\n\n${content}`
|
||||
},
|
||||
"safe": 0
|
||||
})
|
||||
if (send.errcode === 0) {
|
||||
console.log('企业微信应用消息发送成功')
|
||||
} else {
|
||||
console.log('企业微信应用消息发送失败', send)
|
||||
}
|
||||
}*/
|
||||
|
||||
function obj2str(obj: object) {
|
||||
return JSON.stringify(obj)
|
||||
}
|
||||
|
||||
async function getDevice() {
|
||||
let {data} = await axios.get('https://betahub.cn/api/apple/devices/iPhone', {
|
||||
headers: {
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36'
|
||||
}
|
||||
})
|
||||
data = data[getRandomNumberByRange(0, 16)]
|
||||
return data.identifier
|
||||
}
|
||||
|
||||
async function getVersion(device: string) {
|
||||
let {data} = await axios.get(`https://betahub.cn/api/apple/firmwares/${device}`, {
|
||||
headers: {
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36'
|
||||
}
|
||||
})
|
||||
data = data[getRandomNumberByRange(0, data.length)]
|
||||
return data.firmware_info.version
|
||||
}
|
||||
|
||||
async function jdpingou() {
|
||||
let device: string, version: string;
|
||||
device = await getDevice();
|
||||
version = await getVersion(device);
|
||||
return `jdpingou;iPhone;5.19.0;${version};${randomString(40)};network/wifi;model/${device};appBuild/100833;ADID/;supportApplePay/1;hasUPPay/0;pushNoticeIsOpen/0;hasOCPay/0;supportBestPay/0;session/${getRandomNumberByRange(10, 90)};pap/JA2019_3111789;brand/apple;supportJDSHWK/1;Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148`
|
||||
}
|
||||
|
||||
function get(url: string, headers?: any): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.get(url, {
|
||||
headers: headers
|
||||
}).then(res => {
|
||||
if (typeof res.data === 'string' && res.data.includes('jsonpCBK')) {
|
||||
resolve(JSON.parse(res.data.match(/jsonpCBK.?\(([\w\W]*)\);?/)[1]))
|
||||
} else {
|
||||
resolve(res.data)
|
||||
}
|
||||
}).catch(err => {
|
||||
reject({
|
||||
code: err?.response?.status || -1,
|
||||
msg: err?.response?.statusText || err.message || 'error'
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function post(url: string, prarms?: string | object, headers?: any): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.post(url, prarms, {
|
||||
headers: headers
|
||||
}).then(res => {
|
||||
resolve(res.data)
|
||||
}).catch(err => {
|
||||
reject({
|
||||
code: err?.response?.status || -1,
|
||||
msg: err?.response?.statusText || err.message || 'error'
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export default USER_AGENT
|
||||
export {
|
||||
TotalBean,
|
||||
getBeanShareCode,
|
||||
getFarmShareCode,
|
||||
requireConfig,
|
||||
wait,
|
||||
getRandomNumberByRange,
|
||||
requestAlgo,
|
||||
getJxToken,
|
||||
exceptCookie,
|
||||
randomString,
|
||||
o2s,
|
||||
randomNumString,
|
||||
getshareCodeHW,
|
||||
getShareCodePool,
|
||||
randomWord,
|
||||
obj2str,
|
||||
jdpingou,
|
||||
get,
|
||||
post
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,422 @@
|
||||
/*
|
||||
CK作废,不时之需,希望大家用不到!!!
|
||||
最好改密码!!!
|
||||
*/
|
||||
const $ = new Env('作废CK');
|
||||
const notify = $.isNode() ? require('./sendNotify') : '';
|
||||
//Node.js用户请在jdCookie.js处填写京东ck;
|
||||
const jdCookieNode = $.isNode() ? require('./jdCookie.js') : '';
|
||||
|
||||
//IOS等用户直接用NobyDa的jd cookie
|
||||
let cookiesArr = [], cookie = '';
|
||||
let flg = process.env.killck?process.env.killck:false;
|
||||
if ($.isNode()) {
|
||||
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);
|
||||
}
|
||||
|
||||
!(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;
|
||||
}
|
||||
if (!flg){
|
||||
console.log(`请设置变量killck='true'来运行!!!`);
|
||||
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;
|
||||
$.isLogin = true;
|
||||
$.nickName = '';
|
||||
await TotalBean();
|
||||
console.log(`\n开始【京东账号${$.index}】${$.nickName || $.UserName}\n`);
|
||||
if (!$.isLogin) {
|
||||
$.msg('', `【提示】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 killck();
|
||||
}
|
||||
}
|
||||
})()
|
||||
.catch((e) => {
|
||||
$.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '')
|
||||
})
|
||||
.finally(() => {
|
||||
$.done();
|
||||
})
|
||||
|
||||
function killck() {
|
||||
return new Promise(resolve => {
|
||||
const options = {
|
||||
url: `https://plogin.m.jd.com/cgi-bin/ml/mlogout?appid=300&returnurl=https%3A%2F%2Fm.jd.com%2F`,
|
||||
headers: {
|
||||
'authority': 'plogin.m.jd.com',
|
||||
"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"),
|
||||
'cookie': cookie
|
||||
}
|
||||
}
|
||||
$.get(options, (err, resp, data) => {
|
||||
try {
|
||||
console.log('此CK成功作废,重新获取CK吧!\n')
|
||||
} catch (e) {
|
||||
$.logErr(e, resp);
|
||||
} finally {
|
||||
resolve();
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
function TotalBean () {
|
||||
return new Promise( async resolve => {
|
||||
const options = {
|
||||
url: "https://me-api.jd.com/user_new/info/GetJDUserInfoUnion",
|
||||
headers: {
|
||||
Host: "me-api.jd.com",
|
||||
Accept: "*/*",
|
||||
Connection: "keep-alive",
|
||||
Cookie: cookie,
|
||||
"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" ),
|
||||
"Accept-Language": "zh-cn",
|
||||
"Referer": "https://home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&",
|
||||
"Accept-Encoding": "gzip, deflate, br"
|
||||
}
|
||||
}
|
||||
$.get( options, ( err, resp, data ) => {
|
||||
try {
|
||||
if ( err ) {
|
||||
$.logErr( err )
|
||||
} else {
|
||||
if ( data ) {
|
||||
data = JSON.parse( data );
|
||||
if ( data[ 'retcode' ] === "1001" ) {
|
||||
$.isLogin = false; //cookie过期
|
||||
return;
|
||||
}
|
||||
if ( data[ 'retcode' ] === "0" && data.data && data.data.hasOwnProperty( "userInfo" ) ) {
|
||||
$.nickName = data.data.userInfo.baseInfo.nickname;
|
||||
}
|
||||
if ( data[ 'retcode' ] === '0' && data.data && data.data[ 'assetInfo' ] ) {
|
||||
$.beanCount = data.data && data.data[ 'assetInfo' ][ 'beanNum' ];
|
||||
}
|
||||
} else {
|
||||
$.log( '京东服务器返回空数据' );
|
||||
}
|
||||
}
|
||||
} catch ( e ) {
|
||||
$.logErr( e )
|
||||
} finally {
|
||||
resolve();
|
||||
}
|
||||
} )
|
||||
} )
|
||||
}
|
||||
|
||||
function jsonParse(str) {
|
||||
if (typeof str == "string") {
|
||||
try {
|
||||
return JSON.parse(str);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
$.msg($.name, '', '请勿随意在BoxJs输入框修改内容\n建议通过脚本去获取cookie')
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
// prettier-ignore
|
||||
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();
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,18 @@
|
||||
[
|
||||
{
|
||||
"pt_pin": "中文账号名",
|
||||
"Uid": "UID_XXXXXXXXXXXXXXXXXXX"
|
||||
},
|
||||
{
|
||||
"pt_pin": "XXXXXXX",
|
||||
"Uid": "UID_XXXXXXXXXXXXXXXXXXX"
|
||||
},
|
||||
{
|
||||
"pt_pin": "XXXXXXX",
|
||||
"Uid": "UID_XXXXXXXXXXXXXXXXXXX"
|
||||
},
|
||||
{
|
||||
"pt_pin": "XXXXXXX",
|
||||
"Uid": "UID_XXXXXXXXXXXXXXXXXXX"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,70 @@
|
||||
# Usage
|
||||
|
||||
> 推荐使用`docker-compose`所以这里只介绍`docker-compose`使用方式
|
||||
|
||||
|
||||
|
||||
## Docker安装
|
||||
|
||||
|
||||
|
||||
- 国内一键安装 `sudo curl -sSL https://get.daocloud.io/docker | sh`
|
||||
- 国外一键安装 `sudo curl -sSL get.docker.com | sh`
|
||||
- 北京外国语大学开源软件镜像站 `https://mirrors.bfsu.edu.cn/help/docker-ce/`
|
||||
|
||||
|
||||
docker-compose 安装(群晖`nas docker`自带安装了`docker-compose`)
|
||||
|
||||
```
|
||||
curl -L https://get.daocloud.io/docker/compose/releases/download/v2.1.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
|
||||
chmod +x /usr/local/bin/docker-compose
|
||||
```
|
||||
`Ubuntu`用户快速安装`docker-compose`
|
||||
```
|
||||
sudo apt-get update && sudo apt-get install -y python3-pip curl vim git moreutils
|
||||
pip3 install --upgrade pip
|
||||
pip install docker-compose
|
||||
```
|
||||
|
||||
## win10用户安装[docker desktop](https://www.docker.com/products/docker-desktop)
|
||||
|
||||
通过`docker-compose version`查看`docker-compose`版本,确认是否安装成功。
|
||||
|
||||
|
||||
|
||||
## 常用命令
|
||||
|
||||
`docker-compose up -d` 启动(修改docker-compose.yml后需要使用此命令使更改生效);
|
||||
`docker-compose logs` 打印日志;
|
||||
`docker-compose logs -f` 打印日志,-f表示跟随日志;
|
||||
`docker logs -f qinglong` 和上面两条相比可以显示汉字;
|
||||
`docker-compose pull` 更新镜像;
|
||||
`docker-compose stop` 停止容器;
|
||||
`docker-compose restart` 重启容器;
|
||||
`docker-compose down` 停止并删除容器;
|
||||
|
||||
## 青龙一键部署(2.11.3版本)
|
||||
|
||||
1. 新建一个文件夹,用于存放相关数据
|
||||
2. 下载本仓库中的`docker-compose.yml`至本地,或是复制文件内容后在本地自行建立并粘贴内容
|
||||
3. 使用docker-compose启动
|
||||
4. 浏览器输入ip:5700即可进入面板
|
||||
|
||||
###新建数据文件夹
|
||||
|
||||
```bash
|
||||
mkdir qinglong
|
||||
cd qinglong
|
||||
```
|
||||
|
||||
###下载或复制docker-compose.yml文件
|
||||
|
||||
```bash
|
||||
wget https://ghproxy.com/https://raw.githubusercontent.com/whyour/qinglong/develop/docker-compose.yml
|
||||
```
|
||||
|
||||
###启动
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
@@ -0,0 +1,17 @@
|
||||
version: '2'
|
||||
services:
|
||||
ql_web:
|
||||
image: whyour/qinglong:2.11.3
|
||||
container_name: ql
|
||||
volumes:
|
||||
- ./data/config:/ql/config
|
||||
- ./data/log:/ql/log
|
||||
- ./data/db:/ql/db
|
||||
- ./data/scripts:/ql/scripts
|
||||
- ./data/repo:/ql/repo
|
||||
ports:
|
||||
- "0.0.0.0:5700:5700"
|
||||
environment:
|
||||
- ENABLE_HANGUP=true
|
||||
- ENABLE_WEB_PANEL=true
|
||||
restart: always
|
||||
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
## 添加你需要重启自动执行的任意命令,比如 ql repo
|
||||
## 安装node依赖使用 pnpm install -g xxx xxx
|
||||
## 安装python依赖使用 pip3 install xxx
|
||||
pnpm install -g png-js
|
||||
pnpm install -g date-fns
|
||||
pnpm install -g axios
|
||||
pnpm install -g crypto-js
|
||||
pnpm install -g ts-md5
|
||||
pnpm install -g tslib
|
||||
pnpm install -g @types/node
|
||||
pnpm install -g requests
|
||||
pnpm install -g jsdom
|
||||
@@ -0,0 +1,162 @@
|
||||
#!/usr/bin/env bash
|
||||
#2.11.3版本青龙一键安装并添加拉库任务
|
||||
#端口5500
|
||||
#modify 2022-10-12
|
||||
|
||||
Green="\033[32;1m"
|
||||
Red="\033[31m"
|
||||
Yellow="\033[33;1m"
|
||||
Blue="\033[36;1m"
|
||||
Font="\033[0m"
|
||||
GreenBG="\033[42;37m"
|
||||
RedBG="\033[41;37m"
|
||||
OK="${Green}[OK]${Font}"
|
||||
ERROR="${Red}[ERROR]${Font}"
|
||||
|
||||
ok() {
|
||||
echo
|
||||
echo -e " ${OK} ${Green} $1 ${Font}"
|
||||
echo
|
||||
}
|
||||
error() {
|
||||
echo
|
||||
echo -e "${ERROR} ${RedBG} $1 ${Font}"
|
||||
echo
|
||||
}
|
||||
|
||||
ing () {
|
||||
echo
|
||||
echo -e "${Yellow} $1 ${Font}"
|
||||
echo
|
||||
}
|
||||
|
||||
|
||||
if [[ ! "$USER" == "root" ]]; then
|
||||
error "警告:请使用root用户操作!~~"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
datav=/root/ql$(date +%Y%m%d)
|
||||
mkdir -p $datav && ql_path=$datav
|
||||
|
||||
|
||||
ql_run() {
|
||||
if [ -z "$(docker ps -a |awk '{print $NF}'| grep qinglong 2> /dev/null)" ]; then
|
||||
cd $ql_path
|
||||
cat > docker-compose.yml <<EOF
|
||||
version: '2'
|
||||
services:
|
||||
qinglong:
|
||||
image: whyour/qinglong:2.11.3
|
||||
container_name: qinglong
|
||||
volumes:
|
||||
- ./data/config:/ql/config
|
||||
- ./data/log:/ql/log
|
||||
- ./data/db:/ql/db
|
||||
- ./data/scripts:/ql/scripts
|
||||
- ./data/repo:/ql/repo
|
||||
ports:
|
||||
- "0.0.0.0:5500:5700"
|
||||
networks:
|
||||
- net
|
||||
environment:
|
||||
- ENABLE_HANGUP=true
|
||||
- ENABLE_WEB_PANEL=true
|
||||
restart: always
|
||||
networks:
|
||||
net:
|
||||
EOF
|
||||
docker-compose up -d
|
||||
if [ $? -ne 0 ] ; then
|
||||
error "** 错误:容器创建失败,请翻译以上英文报错,Google/百度尝试解决问题!"
|
||||
else
|
||||
sleep 30
|
||||
ok "青龙面板已启动,请去浏览器访问http://ip:5500进行初始化并登陆进去,完成后回来继续下一步!"
|
||||
fi
|
||||
|
||||
else
|
||||
error "已有qinglong名称的容器在运行,不能重复创建!"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
docker_install() {
|
||||
if [ -x "$(command -v docker)" ]; then
|
||||
ok "检测到 Docker 已安装!"
|
||||
else
|
||||
if [ -r /etc/os-release ]; then
|
||||
lsb_dist="$(. /etc/os-release && echo "$ID")"
|
||||
fi
|
||||
if [ $lsb_dist == "openwrt" ]; then
|
||||
error "openwrt 环境请自行安装 docker"
|
||||
exit 1
|
||||
else
|
||||
ing "开始安装 docker 环境..."
|
||||
curl -sSL https://get.daocloud.io/docker | sh
|
||||
sleep 2
|
||||
if [ -x "$(command -v docker)" ]; then
|
||||
mkdir /etc/docker
|
||||
cat > /etc/docker/daemon.json <<EOF
|
||||
{
|
||||
"registry-mirrors": ["https://pee6w651.mirror.aliyuncs.com/","https://registry.docker-cn.com"]
|
||||
}
|
||||
EOF
|
||||
chmod +x /etc/docker/daemon.json
|
||||
ok "安装 docker 环境...完成!"
|
||||
systemctl enable docker
|
||||
systemctl restart docker
|
||||
else
|
||||
error "docker安装失败,请排查原因或手动完成安装在重新运行"
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
docker_compose() {
|
||||
if [ -x "$(command -v docker-compose)" ]; then
|
||||
ok "docker-compose已安装"
|
||||
else
|
||||
ing "开始安装docker-compose..."
|
||||
curl -L curl -L https://ghproxy.com/https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-linux-x86_64 > /usr/local/bin/docker-compose
|
||||
chmod +x /usr/local/bin/docker-compose
|
||||
ok "安装docker-compose...完成"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
add_repo() {
|
||||
if [ "$(grep -c "6dylan6/jdpro" $ql_path/data/config/crontab.list)" != 0 ]; then
|
||||
error "您的任务列表中已存在拉库任务,刷新浏览器去执行拉库任务吧!"
|
||||
else
|
||||
ing "开始添加6dylan6/jdpro拉库任务"
|
||||
sed -i 's/RepoFileExtensions.*/RepoFileExtensions=\"js py sh ts\"/g' $ql_path/data/config/config.sh
|
||||
if [ "$(grep -c "token" $ql_path/data/config/auth.json)" != 0 ]; then
|
||||
docker exec -it qinglong /bin/bash -c "token=\$(cat /ql/config/auth.json | jq --raw-output .token) && curl -s -H 'Accept: application/json' -H \"Authorization: Bearer \$token\" -H 'Content-Type: application/json;charset=UTF-8' -H 'Accept-Language: zh-CN,zh;q=0.9' --data-binary '{\"name\":\"拉库\",\"command\":\"ql repo https://ghproxy.com/https://github.com/6dylan6/jdpro.git \\\"jd_|jx_|jddj_\\\" \\\"backUp\\\" \\\"^jd[^_]|USER|JD|function|sendNotify\\\"\",\"schedule\":\"45 7-23/2 * * *\"}' --compressed 'http://127.0.0.1:5700/api/crons?t=1627380635389'"
|
||||
ok "已添加拉库任务,刷新浏览器后去执行拉库任务吧!"
|
||||
else
|
||||
error "未检测到 token,请访问web完成初始化并登陆进去后,在运行一次脚本"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
ql_fix() {
|
||||
docker exec -it qinglong /bin/bash -c "grep -lr 'cdn.jsde' /ql/dist/|xargs sed -i 's#cdn.*.net/npm/#unpkg.com/#g'"
|
||||
docker exec -it qinglong /bin/bash -c "grep -lr 'unpkg.com' /ql/dist/ | xargs -I {} sh -c \"gzip -c {} > {}.gz\""
|
||||
docker exec -it qinglong bash -c "curl -so /ql/deps/sendNotify.js https://js.dayplus.xyz/https://raw.githubusercontent.com/6dylan6/jdpro/main/sendNotify.js"
|
||||
}
|
||||
|
||||
ing "开始部署青龙并创建拉库任务,速度根据您的网速决定,请耐心等待....."
|
||||
read -p "按任意键开始部署。。。"
|
||||
docker_install
|
||||
docker_compose
|
||||
ing "开始创建容器,如果长时间卡住 ctrl+c终止后重试!!!"
|
||||
ql_run
|
||||
ql_fix
|
||||
read -p "已初在浏览器始化并登陆青龙了?,那就按任意键继续!"
|
||||
add_repo
|
||||
sleep 2
|
||||
ok "已部署完成,2.11.3版本青龙,数据保存路径为$datav,容器名qinglong,访问地址http://ip:5500"
|
||||
|
||||
@@ -0,0 +1,954 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
## Build 20220831-001-test
|
||||
## 6dylan6_0126
|
||||
|
||||
name_js=(
|
||||
jd_farm_help
|
||||
jd_pet
|
||||
jd_plantBean
|
||||
jd_dreamFactory
|
||||
jd_jdfactory
|
||||
#jd_crazy_joy
|
||||
#jd_jdzz
|
||||
jd_jxnc
|
||||
#jd_bookshop
|
||||
#jd_cash
|
||||
jd_sgmh
|
||||
jd_cfd
|
||||
jd_health
|
||||
#jd_carnivalcity
|
||||
#jd_city
|
||||
#jd_moneyTree
|
||||
#jd_cfdtx
|
||||
)
|
||||
name_config=(
|
||||
Fruit
|
||||
Pet
|
||||
Bean
|
||||
DreamFactory
|
||||
JdFactory
|
||||
#Joy
|
||||
#Jdzz
|
||||
Jxnc
|
||||
#BookShop
|
||||
#Cash
|
||||
Sgmh
|
||||
Cfd
|
||||
Health
|
||||
#Carni
|
||||
#City
|
||||
#MoneyTree
|
||||
#TokenJxnc
|
||||
)
|
||||
name_chinese=(
|
||||
东东农场
|
||||
东东萌宠
|
||||
京东种豆得豆
|
||||
京喜工厂
|
||||
东东工厂
|
||||
#crazyJoy任务
|
||||
#京东赚赚
|
||||
京喜农场
|
||||
#口袋书店
|
||||
#签到领现金
|
||||
闪购盲盒
|
||||
京喜财富岛
|
||||
东东健康社区
|
||||
#京东手机狂欢城
|
||||
#城城领现金
|
||||
#摇钱树
|
||||
#京喜token
|
||||
)
|
||||
env_name=(
|
||||
FRUITSHARECODES ## 1、东东农场互助码
|
||||
PETSHARECODES ## 2、东东萌宠互助码
|
||||
PLANT_BEAN_SHARECODES ## 3、种豆得豆互助码
|
||||
DREAM_FACTORY_SHARE_CODES ## 4、京喜工厂互助码
|
||||
DDFACTORY_SHARECODES ## 5、东东工厂互助码
|
||||
#JDJOY_SHARECODES ## 6、疯狂的JOY互助码
|
||||
#JDZZ_SHARECODES ## 7、京东赚赚互助码
|
||||
JXNC_SHARECODES ## 8、京喜农场助力码
|
||||
#BOOKSHOP_SHARECODES ## 9、口袋书店互助码
|
||||
#JD_CASH_SHARECODES ## 10、签到领现金互助码
|
||||
JDSGMH_SHARECODES ## 11、闪购盲盒互助码
|
||||
JDCFD_SHARECODES ## 12、京喜财富岛互助码
|
||||
JDHEALTH_SHARECODES ## 13、东东健康社区互助码
|
||||
#JD818_SHARECODES ## 14、京东手机狂欢城互助码
|
||||
#CITY_SHARECODES ## 15、城城领现金互助码
|
||||
#MONEYTREE_SHARECODES ## 16、摇钱树
|
||||
#JXNCTOKENS ## 17、京喜Token(京喜财富岛提现用)
|
||||
)
|
||||
var_name=(
|
||||
ForOtherFruit ## 1、东东农场互助规则
|
||||
ForOtherPet ## 2、东东萌宠互助规则
|
||||
ForOtherBean ## 3、种豆得豆互助规则
|
||||
ForOtherDreamFactory ## 4、京喜工厂互助规则
|
||||
ForOtherJdFactory ## 5、东东工厂互助规则
|
||||
#ForOtherJoy ## 6、疯狂的JOY互助规则
|
||||
#ForOtherJdzz ## 7、京东赚赚互助规则
|
||||
ForOtherJxnc ## 8、京喜农场助力码
|
||||
#ForOtherBookShop ## 9、口袋书店互助规则
|
||||
#ForOtherCash ## 10、签到领现金互助规则
|
||||
ForOtherSgmh ## 11、闪购盲盒互助规则
|
||||
ForOtherCfd ## 12、京喜财富岛互助规则
|
||||
ForOtherHealth ## 13、东东健康社区互助规则
|
||||
#ForOtherCarni ## 14、京东手机狂欢城互助规则
|
||||
#ForOtherCity ## 15、城城领现金互助规则
|
||||
ForOtherMoneyTree ## 16、摇钱树
|
||||
#TokenJxnc ## 17、京喜Token(京喜财富岛提现用)
|
||||
)
|
||||
|
||||
local_scr=$1
|
||||
relative_path="${local_scr%/*}"
|
||||
repo_dir=""
|
||||
sub_dir_scripts="$(ls -l $dir_scripts |awk '/^d/ {print $NF}')"
|
||||
if [[ ! -z ${relative_path} ]] && [[ ${local_scr} =~ "/" ]]; then
|
||||
local_scr_name="$(echo ${local_scr##*/})"
|
||||
if [[ ${relative_path} =~ "$dir_scripts" ]]; then
|
||||
repo_dir="$(echo ${relative_path#$dir_scripts} | awk -F '/' '{print $(NF)}')"
|
||||
local_scr_dir="${relative_path}"
|
||||
elif [[ ${relative_path} =~ "/ql/" ]]; then
|
||||
local_scr_dir="$dir_scripts"
|
||||
else
|
||||
repo_dir="$(echo $local_scr | awk -F '/' '{print $(NF-1)}')"
|
||||
local_scr_dir="$dir_scripts/${repo_dir}"
|
||||
fi
|
||||
else
|
||||
local_scr_name=$local_scr
|
||||
local_scr_dir="$dir_scripts"
|
||||
fi
|
||||
|
||||
## 选择python3还是node
|
||||
define_program() {
|
||||
local first_param=$1
|
||||
if [[ $first_param == *.js ]]; then
|
||||
which_program="node"
|
||||
elif [[ $first_param == *.py ]]; then
|
||||
which_program="python3"
|
||||
elif [[ $first_param == *.sh ]]; then
|
||||
which_program="bash"
|
||||
elif [[ $first_param == *.ts ]]; then
|
||||
which_program="ts-node-transpile-only"
|
||||
else
|
||||
which_program=""
|
||||
fi
|
||||
}
|
||||
|
||||
# 定义 json 数据查询工具
|
||||
def_envs_tool(){
|
||||
local i
|
||||
for i in $@; do
|
||||
local token=$(cat $file_auth_user | jq -r .token)
|
||||
if [[ ! -z ${token} ]]; then
|
||||
curl -s --noproxy "*" "http://0.0.0.0:5600/api/envs?searchValue=$i" -H "Authorization: Bearer $token" | jq .data
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
def_json_total(){
|
||||
def_envs_tool $1 | jq .[].$2 | tr -d '[]," '
|
||||
}
|
||||
|
||||
def_json_grep_match(){
|
||||
def_envs_tool $1 | jq .[] | perl -pe '{s|([^}])\n|\1|g}' | grep "$3" | jq .$2 | tr -d '[]," '
|
||||
}
|
||||
|
||||
def_json(){
|
||||
def_envs_tool $1 | jq .[$2].$3 | perl -pe '{s|^"\|"$||g}' | grep -v "null"
|
||||
}
|
||||
|
||||
def_json_match(){
|
||||
if [[ -f $1 ]]; then
|
||||
if [[ $3 && $(cat "$1" | grep "$3") ]]; then
|
||||
cat "$1" | perl -pe '{s|^\[\|\]$||g; s|\n||g; s|\},$|\}\n|g}' | grep "$2" | jq -r .$3 | grep -v "null"
|
||||
else
|
||||
cat "$1" | perl -pe '{s|^\[\|\]$||g; s|\n||g; s|\},$|\}\n|g}' | grep "$2" | grep -v "null"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
def_json_value(){
|
||||
if [[ -f $1 ]]; then
|
||||
if [[ $(cat "$1" | grep "$2") ]]; then
|
||||
cat "$1" | perl -pe "{s|^\[\|\]$||g; s|\n||g; s|\},$|\}\n|g}" | grep "$3" | jq -r .$2 | grep -v "null"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
def_sub(){
|
||||
local i j
|
||||
for i in $(def_json_total $1 $2 | awk '/'$3'/{print NR}'); do
|
||||
j=$((i - 1));
|
||||
echo $j
|
||||
done
|
||||
}
|
||||
|
||||
def_sub_value(){
|
||||
local line=$(($3 + 1))
|
||||
def_json_total $1 $2 | awk 'NR=='$line''
|
||||
}
|
||||
|
||||
def_urldecode(){
|
||||
local i
|
||||
for i in $@; do
|
||||
echo $i | awk 'BEGIN{for(i=0;i<10;i++)hex[i]=i;hex["A"]=hex["a"]=10;hex["B"]=hex["b"]=11;hex["C"]=hex["c"]=12;hex["D"]=hex["d"]=13;hex["E"]=hex["e"]=14;hex["F"]=hex["f"]=15;}{gsub(/\+/," ");i=$0;while(match(i,/%../)){;if(RSTART>1);printf"%s",substr(i,1,RSTART-1);printf"%c",hex[substr(i,RSTART+1,1)]*16+hex[substr(i,RSTART+2,1)];i=substr(i,RSTART+RLENGTH);}print i;}'
|
||||
done
|
||||
}
|
||||
|
||||
def_pin_sub(){
|
||||
if [[ $@ ]]; then
|
||||
local i j k
|
||||
for i in $@; do
|
||||
for j in $(def_urldecode $(def_json_total JD_COOKIE value | perl -pe "{s|.*pt_pin=([^; ]+)(?=;?).*|\1|}") | awk '/'$i'/{print NR}'); do
|
||||
k=$((j - 1));
|
||||
echo $k
|
||||
done
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
# 字符串 def_urldecode 解密
|
||||
def_urldecode(){
|
||||
for i in $@; do
|
||||
echo $i | awk 'BEGIN{for(i=0;i<10;i++)hex[i]=i;hex["A"]=hex["a"]=10;hex["B"]=hex["b"]=11;hex["C"]=hex["c"]=12;hex["D"]=hex["d"]=13;hex["E"]=hex["e"]=14;hex["F"]=hex["f"]=15;}{gsub(/\+/," ");i=$0;while(match(i,/%../)){;if(RSTART>1);printf"%s",substr(i,1,RSTART-1);printf"%c",hex[substr(i,RSTART+1,1)]*16+hex[substr(i,RSTART+2,1)];i=substr(i,RSTART+RLENGTH);}print i;}'
|
||||
done
|
||||
}
|
||||
|
||||
# 字符串 urldecode 解密
|
||||
urldecode() {
|
||||
local url_encoded="${1//+/ }"
|
||||
printf '%b' "${url_encoded//%/\\x}"
|
||||
}
|
||||
|
||||
## 生成pt_pin清单
|
||||
gen_pt_pin_array() {
|
||||
## 生成 json 值清单
|
||||
gen_basic_value(){
|
||||
for i in $@; do
|
||||
eval $i='($(def_json_total JD_COOKIE $i | perl -pe "{s| ||g}"))'
|
||||
done
|
||||
}
|
||||
|
||||
gen_basic_value value status
|
||||
# 生成JD_COOKIE下标数组
|
||||
ori_sub=(${!value[@]})
|
||||
# 生成序号数组
|
||||
sn=($(def_json_total JD_COOKIE value | awk '{print NR}'))
|
||||
# 生成pin值数组
|
||||
pin=($(def_json_total JD_COOKIE value | perl -pe "{s|.*pt_pin=([^; ]+)(?=;?).*|\1|}"))
|
||||
# 生成非转码pin值数组
|
||||
pt_pin=($(urldecode "${pin[*]}"))
|
||||
#面板 JD_COOKIE 数组
|
||||
ori_array=(${value[@]})
|
||||
#面板 JD_COOKIE 总数
|
||||
ori_user_sum=${#ori_array[@]}
|
||||
|
||||
#剔除已禁用 JD_COOKIE 数组元素
|
||||
for j in $(def_sub JD_COOKIE status 1); do unset ori_array[j]; done
|
||||
|
||||
#本次导出的 JD_COOKIE 数组
|
||||
array=(${ori_array[@]})
|
||||
#本次导出的 JD_COOKIE 总数
|
||||
user_sum=${#array[@]}
|
||||
}
|
||||
|
||||
## 获取用户昵称 API
|
||||
Get_NickName() {
|
||||
local currentTimeStamp=$(date +%s)
|
||||
local cookie=$1
|
||||
local url_1="https://me-api.jd.com/user_new/info/GetJDUserInfoUnion"
|
||||
local url_2="https://wxapp.m.jd.com/kwxhome/myJd/home.json?&useGuideModule=0&bizId=&brandId=&fromType=wxapp×tamp=$currentTimeStamp"
|
||||
local UA_1="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62"
|
||||
local UA_2="Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.10(0x18000a2a) NetType/WIFI Language/zh_CN"
|
||||
|
||||
local api_1=$(
|
||||
curl -s --connect-timeout 20 --retry 3 --noproxy "*" "$url_1" \
|
||||
-H "Host: me-api.jd.com" \
|
||||
-H "Accept: */*" \
|
||||
-H "Connection: keep-alive" \
|
||||
-H "Cookie: $cookie" \
|
||||
-H "User-Agent: $UA_1" \
|
||||
-H "Accept-Language: zh-cn" \
|
||||
-H "Referer: https://home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&" \
|
||||
-H "Accept-Encoding: deflate, br"
|
||||
)
|
||||
|
||||
local api_2=$(
|
||||
curl -s --connect-timeout 20 --retry 3 --noproxy "*" "$url_2" \
|
||||
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||
-H "Host: wxapp.m.jd.com" \
|
||||
-H "Connection: keep-alive" \
|
||||
-H "Cookie: $cookie" \
|
||||
-H "User-Agent: $UA_2" \
|
||||
-H "Referer: https://servicewechat.com/wxa5bf5ee667d91626/161/page-frame.html" \
|
||||
-H "Accept-Encoding: compress,deflate, br"
|
||||
)
|
||||
|
||||
retcode=$(echo $api_1 | jq -r .retcode)
|
||||
if [[ $retcode == 0 ]]; then
|
||||
nickname=$(echo $api_1 | jq -r .data | jq -r .userInfo | jq -r .baseInfo | jq -r .nickname)
|
||||
echo -e "$nickname"
|
||||
else
|
||||
code=$(echo $api_2 | jq -r .code)
|
||||
if [[ $code != 999 ]]; then
|
||||
nickname=$(echo $api_2 | jq -r .user | jq -r .petName)
|
||||
echo -e "$nickname"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
## 生成用户信息清单
|
||||
gen_uesr_info(){
|
||||
remarks[$1]="$(def_json JD_COOKIE remarks "pin=${pin[$1]};" | head -1)"
|
||||
if [[ ${remarks[$1]} == *@@* ]]; then
|
||||
remarks_name[$1]="($(echo ${remarks[$1]} | awk -F '@@' '{print $1}'))"
|
||||
elif [[ ${remarks[$1]} && ${remarks[$1]} != null ]]; then
|
||||
remarks_name[$1]="(${remarks[$1]})"
|
||||
else
|
||||
remarks_name[$1]="(未备注)"
|
||||
fi
|
||||
tmp_NickName_1=$(Get_NickName "${value[$1]}")
|
||||
[[ -f $CK_WxPusherUid_dir/$CK_WxPusherUid_file ]] && tmp_NickName_2="$(def_json_value "$CK_WxPusherUid_dir/$CK_WxPusherUid_file" NickName "pin=${pin[$1]};")"
|
||||
if [[ $tmp_NickName_1 ]]; then
|
||||
NickName[$1]="$tmp_NickName_1"
|
||||
elif [[ $tmp_NickName_2 ]]; then
|
||||
NickName[$1]="$tmp_NickName_2"
|
||||
else
|
||||
NickName[$1]=""
|
||||
fi
|
||||
[[ ! ${NickName[$1]} || ${NickName[$1]} = null ]] && UserName[$1]=${pin[$1]} || UserName[$1]=${NickName[$1]}
|
||||
ori_full_name[$1]="【${sn[$1]}】${UserName[$1]}${remarks_name[$1]}"
|
||||
full_name[$1]="${ori_full_name[$1]}"
|
||||
[[ $status[$1] = 1 ]] && unset ori_array[$1]
|
||||
}
|
||||
|
||||
redefine_JD_COOKIE(){
|
||||
array=(${ori_array[@]})
|
||||
user_sum=${#array[@]}
|
||||
jd_Cookie="$(echo ${array[@]} | sed 's# #\&#g')"
|
||||
[[ $jd_Cookie ]] && export JD_COOKIE="$jd_Cookie"
|
||||
}
|
||||
|
||||
## 临时禁止账号运行活动脚本
|
||||
TempBlock_CK(){
|
||||
## 按 Cookie 序号禁止账号
|
||||
TempBlock_JD_COOKIE(){
|
||||
## 导入基础 JD_COOKIE 变量
|
||||
local TempBlockCookie TempBlockPin TempDesiPin i j m n p q
|
||||
if [[ $3 ]]; then
|
||||
TempDesiPin="$(def_urldecode $3 | perl -pe "{s|,| |g;}")"
|
||||
i=0
|
||||
for j in $(def_pin_sub $TempDesiPin); do
|
||||
[[ ${status[j]} = 1 ]] && continue
|
||||
TempDesiCKArray[i]=${ori_array[j]}
|
||||
let i++
|
||||
done
|
||||
[[ ${TempDesiCKArray[@]} ]] && ori_array=(${TempDesiCKArray[@]})
|
||||
else
|
||||
[[ $(echo $1 | perl -pe "{s|\D||g;}") ]] && TempBlockCookie="$(eval echo $(echo $1 | perl -pe "{s|~\|-|_|g; s|\W+\|[A-Za-z]+| |g; s|(\d+)_(\d+)|{\1..\2}|g;}"))" || TempBlockCookie=""
|
||||
TempBlockPin="$(def_urldecode $2 | perl -pe "{s|,| |g;}")"
|
||||
for m in $TempBlockCookie; do
|
||||
n=$((m - 1))
|
||||
unset ori_array[n]
|
||||
done
|
||||
for k in $(def_pin_sub $TempBlockPin); do
|
||||
unset ori_array[k]
|
||||
done
|
||||
fi
|
||||
redefine_JD_COOKIE
|
||||
}
|
||||
|
||||
local i j k
|
||||
local initial_user_sum=$user_sum
|
||||
if [[ -n "$(echo $tempblock_ck_envs_num|sed -n "/^[0-9]\+$/p")" ]]; then
|
||||
for ((i = 1; i <= $tempblock_ck_envs_num; i++)); do
|
||||
if [ tempblock_ck_envs$i ]; then
|
||||
local tempblock_ck_array=($(eval echo "\$tempblock_ck_envs$i" | perl -pe "{s|&| |g}"))
|
||||
for j in "${tempblock_ck_array[@]}"; do
|
||||
local tmp_task_array=($(echo $j | perl -pe "{s|@| |g}"))
|
||||
local tmp_script_array=($(echo ${tmp_task_array[0]} | perl -pe "{s/\|/ /g}"))
|
||||
for k in ${tmp_script_array[@]}; do
|
||||
if [[ $local_scr == *$k* ]]; then
|
||||
TempBlockCookie="${tmp_task_array[1]}"
|
||||
TempBlockPin=${tmp_task_array[2]}
|
||||
TempDesiPin=${tmp_task_array[3]}
|
||||
break
|
||||
fi
|
||||
done
|
||||
done
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [[ $TempBlockCookie ]] || [[ $TempBlockPin ]] || [[ $TempDesiPin ]]; then
|
||||
TempBlock_JD_COOKIE $TempBlockCookie $TempBlockPin $TempDesiPin
|
||||
fi
|
||||
|
||||
#echo -n "# 当前总共 $ori_user_sum 个 JD_COOKIE"
|
||||
if [[ $ori_user_sum -gt $initial_user_sum ]] && [[ $initial_user_sum -gt $user_sum ]]; then
|
||||
echo -e "已通过环境变量禁用了 $((ori_user_sum - initial_user_sum)) 个 JD_COOKIE,已临时禁止了 $((initial_user_sum - user_sum)) 个 JD_COOKIE。"
|
||||
elif [[ $ori_user_sum -eq $initial_user_sum ]] && [[ $initial_user_sum -gt $user_sum ]]; then
|
||||
echo -e "已临时禁止了 $((initial_user_sum - user_sum)) 个 JD_COOKIE。"
|
||||
elif [[ $ori_user_sum -gt $initial_user_sum ]] && [[ $initial_user_sum -eq $user_sum ]]; then
|
||||
echo -e "已通过环境变量禁用了 $((ori_user_sum - initial_user_sum)) 个 JD_COOKIE。"
|
||||
fi
|
||||
#echo -e ""
|
||||
}
|
||||
|
||||
## 获取用户状态 API
|
||||
Get_CK_Status() {
|
||||
local cookie=$1
|
||||
local url="https://me-api.jd.com/user_new/info/GetJDUserInfoUnion"
|
||||
|
||||
local api=$(
|
||||
curl -s --connect-timeout 30 --retry 3 --noproxy "*" "$url" \
|
||||
-H "Cookie: $cookie" \
|
||||
-H "Referer: https://home.m.jd.com/myJd/home.action"
|
||||
)
|
||||
|
||||
retcode=$(echo $api | jq -r .retcode)
|
||||
if [[ ! $retcode || $retcode = null ]]; then
|
||||
return 2
|
||||
elif [[ $retcode == 0 ]]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 移除失效的 Cookie
|
||||
remove_void_ck(){
|
||||
if [[ $Remove_Void_CK = 1 ]]; then
|
||||
local i j void_ck_num
|
||||
local initial_user_sum=$user_sum
|
||||
local test_connect="$(curl -I -s --connect-timeout 20 --retry 3 --noproxy "*" https://bean.m.jd.com/bean/signIndex.action -w %{http_code} | tail -n1)"
|
||||
echo -e "# 开始检测 Cookie 的有效性,可能花费一定时间,请耐心等待 ..."
|
||||
echo -e "# 本次一共导入 $user_sum 个 Cookie ,其中:"
|
||||
for ((i=0; i < $ori_user_sum; i ++)); do
|
||||
gen_uesr_info $i
|
||||
Get_CK_Status ${value[i]}
|
||||
[[ $? = 0 ]] && echo -e "# ${full_name[i]} 状态正常"
|
||||
[[ $? = 1 ]] && echo -e "# ${full_name[i]} 已失效" && unset ori_array[i]
|
||||
[[ $? = 2 ]] && echo -e "# ${full_name[i]} 因 API 连接失败跳过检测"
|
||||
done
|
||||
redefine_JD_COOKIE
|
||||
void_ck_num=$((initial_user_sum - user_sum))
|
||||
[[ $void_ck_num = 0 ]] && echo -e "# 未检测到失效 Cookie 。" || echo -e "# 已剔除以上 $void_ck_num 个失效的 Cookie 。"
|
||||
echo -e ""
|
||||
fi
|
||||
}
|
||||
|
||||
## 重组 CK
|
||||
Recombin_CK(){
|
||||
local i j k m n
|
||||
if [[ -n "$(echo $recombin_ck_envs_num|sed -n "/^[0-9]\+$/p")" ]]; then
|
||||
for ((i = 1; i <= $recombin_ck_envs_num; i++)); do
|
||||
if [ recombin_ck_envs$i ]; then
|
||||
local recombin_ck_array=($(eval echo "\$recombin_ck_envs$i" | perl -pe "{s|&| |g}"))
|
||||
#[[ $DEBUG_MODE = 2 ]] &&]]&& echo ${recombin_ck_array[@]}
|
||||
for j in "${recombin_ck_array[@]}"; do
|
||||
local tmp_task_array=($(echo $j | perl -pe "{s|@| |g}"))
|
||||
local tmp_script_array=($(echo ${tmp_task_array[0]} | perl -pe "{s/\|/ /g}"))
|
||||
#[[ $DEBUG_MODE = 1 ]] && echo ${tmp_script_array[@]}
|
||||
for k in "${tmp_script_array[@]}"; do
|
||||
if [[ $local_scr == *$k* ]]; then
|
||||
[[ $DEBUG_MODE = 1 ]] && echo -n "${tmp_script_array[@]}" && echo -e "\n"
|
||||
Recombin_CK_Mode="${tmp_task_array[1]}"
|
||||
[[ $DEBUG_MODE = 1 ]] && eval echo "Recombin_CK_Mode$m : \$Recombin_CK_Mode$m"
|
||||
for ((m = 1; m <= 5; m++)); do
|
||||
n=$((m + 1))
|
||||
eval Recombin_CK_ARG$m="${tmp_task_array[n]}"
|
||||
[[ $DEBUG_MODE = 1 ]] && eval echo "Recombin_CK_ARG$m : \$Recombin_CK_ARG$m"
|
||||
done
|
||||
local temp_status=1
|
||||
[[ $Recombin_CK_Mode = 4 || $Recombin_CK_Mode = 5 ]] && Recombin_CK_cal && break 4 || Recombin_CK_cal
|
||||
fi
|
||||
done
|
||||
done
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
[[ ! $temp_status ]] && Recombin_CK_cal
|
||||
}
|
||||
|
||||
## 重组 CK 计算
|
||||
Recombin_CK_cal(){
|
||||
## 随机模式算法
|
||||
combine_random(){
|
||||
local combined_all ran_sub tmp i
|
||||
echo "# 正在应用 随机Cookie 模式..."
|
||||
[[ -n "$(echo $1|sed -n "/^[0-9]\+$/p")" && $1 -le $user_sum ]] && ran_num=$1 || ran_num=$user_sum
|
||||
echo -e "# 当前总共 $user_sum 个有效账号,本次随机抽取 $ran_num 个账号按随机顺序参加活动。"
|
||||
ran_sub="$(seq $user_sum | sort -R | head -$ran_num)"
|
||||
for i in $ran_sub; do
|
||||
j=$((i -1))
|
||||
[[ ! ${array[j]} ]] && continue
|
||||
tmp="${array[j]}"
|
||||
combined_all="$combined_all&$tmp"
|
||||
done
|
||||
jdCookie_4=$(echo $combined_all | sed 's/^&//g')
|
||||
[[ $jdCookie_4 ]] && export JD_COOKIE="$jdCookie_4"
|
||||
#[[ $DEBUG_MODE = 1 ]] && echo $jdCookie_4
|
||||
}
|
||||
|
||||
## 优先模式算法
|
||||
combine_priority(){
|
||||
local combined_all ran_sub jdCookie_priority jdCookie_random m n
|
||||
if [ $1 ]; then
|
||||
# 固定区账号数量
|
||||
[[ -n "$(echo $1|sed -n "/^[0-9]\+$/p")" ]] && fixed_num=$1 || fixed_num="0"
|
||||
if [[ $fixed_num -ge $user_sum ]]; then
|
||||
echo "# 优先固定账号数量不得大于或等于有效账号总量,本次暂不重组 Cookie ..."
|
||||
export JD_COOKIE="$JD_COOKIE"
|
||||
elif [[ $fixed_num -eq 0 ]]; then
|
||||
echo "# 未设定优先固定数量,本次暂不重组 Cookie ..."
|
||||
export JD_COOKIE="$JD_COOKIE"
|
||||
else
|
||||
echo "# 正在应用 优先Cookie 模式..."
|
||||
echo -e "# 当前总共 $user_sum 个有效账号,其中前 $fixed_num 个账号为固定顺序。\n# 本次从第 $((fixed_num + 1)) 个账号开始按随机顺序参加活动。"
|
||||
ran_sub=$(seq $fixed_num $((ori_user_sum-1)) | sort -R)
|
||||
for ((m = 0; m < $fixed_num; m++)); do
|
||||
[[ ! ${ori_array[m]} ]] && continue
|
||||
tmp="${ori_array[m]}"
|
||||
jdCookie_priority="$jdCookie_priority&$tmp"
|
||||
done
|
||||
for n in $ran_sub; do
|
||||
[[ ! ${ori_array[n]} ]] && continue
|
||||
tmp="${ori_array[n]}"
|
||||
jdCookie_random="$jdCookie_random&$tmp"
|
||||
done
|
||||
combined_all="$jdCookie_priority$jdCookie_random"
|
||||
jdCookie_4=$(echo $combined_all | perl -pe "{s|^&||}")
|
||||
[[ $jdCookie_4 ]] && export JD_COOKIE="$jdCookie_4"
|
||||
#[[ $DEBUG_MODE = 1 ]] && echo $jdCookie_4
|
||||
fi
|
||||
else
|
||||
echo "# 由于参数缺失,本次暂不重组 Cookie ..."
|
||||
export JD_COOKIE="$JD_COOKIE"
|
||||
fi
|
||||
}
|
||||
|
||||
## 轮换模式算法
|
||||
combine_rotation(){
|
||||
# 当月总天数
|
||||
local total_days=$(cal | grep ^[0-9] | tail -1 | awk -F " " '{print $NF}')
|
||||
# 今天几号
|
||||
local today_day=$(date +%-d)
|
||||
local combined_all rot_num rot_start_num jdCookie_priority jdCookie_rot_head jdCookie_rot_mid tmp_1 tmp_2 tmp_3 a b c
|
||||
# 固定区账号数量
|
||||
[[ -n "$(echo $1|sed -n "/^[0-9]\+$/p")" ]] && fixed_num=$1 || fixed_num="0"
|
||||
if [[ $fixed_num -ge $ori_user_sum ]]; then
|
||||
echo "# 优先固定账号数量不得大于或等于有效账号总量,本次暂不重组 Cookie ..."
|
||||
export JD_COOKIE="$JD_COOKIE"
|
||||
elif [[ $today_day -gt 1 ]]; then
|
||||
echo "# 正在应用 轮换Cookie 模式..."
|
||||
# 轮换区的账号数量
|
||||
local rot_total_num=$((ori_user_sum - fixed_num))
|
||||
if [[ $rot_total_num -gt 2 ]]; then
|
||||
combine_bottom
|
||||
# 每日轮换的账号数量
|
||||
rot_num=$2
|
||||
[[ -z "$(echo $rot_num|sed -n "/^[0-9]\+$/p")" || ! $rot_num || $rot_num -lt 1 || $rot_total_num -lt $rot_num ]] && rot_num=$(((rot_total_num + total_days -1)/total_days)) && [[ $rot_num -lt 1 ]] && rot_num="1"
|
||||
rot_start_num=$((fixed_num + rot_num * ((today_day - 1))))
|
||||
while [[ $ori_user_sum -lt $((rot_start_num + 1)) ]]; do rot_start_num=$((rot_start_num - rot_total_num)); done
|
||||
echo -n "# 当前总共 $user_sum 个有效账号"
|
||||
[[ $fixed_num -gt 0 ]] && echo -n ",其中前 $fixed_num 个账号为固定顺序" || echo -n ",所有账号参与轮换"
|
||||
[[ $user_bottom_sum -gt 0 ]] && echo -e ",有 $user_bottom_sum 个账号固定在末尾。" || echo -e "。"
|
||||
echo -e "# 今天从第 $((rot_start_num + 1)) 位账号开始轮换,轮换频次为:$rot_num 个账号/天。"
|
||||
for ((a = 0; a < fixed_num; a++)); do
|
||||
[[ ! ${ori_array[a]} ]] && continue
|
||||
tmp_1="${ori_array[a]}"
|
||||
jdCookie_priority="$jdCookie_priority&$tmp_1"
|
||||
done
|
||||
for ((b = $rot_start_num; b < $ori_user_sum; b++)); do
|
||||
[[ ! ${ori_array[b]} ]] && continue
|
||||
tmp_2="${ori_array[b]}"
|
||||
jdCookie_rot_head="$jdCookie_rot_head&$tmp_2"
|
||||
done
|
||||
for ((c = $fixed_num; c < $((rot_start_num)); c++)); do
|
||||
[[ ! ${ori_array[c]} ]] && continue
|
||||
tmp_3="${ori_array[c]}"
|
||||
jdCookie_rot_mid="$jdCookie_rot_mid&$tmp_3"
|
||||
done
|
||||
combined_all="$jdCookie_priority$jdCookie_rot_head$jdCookie_rot_mid$jdCookie_bottom"
|
||||
jdCookie_4=$(echo $combined_all | perl -pe "{s|^&||; s|&$||}")
|
||||
[[ $jdCookie_4 ]] && export JD_COOKIE="$jdCookie_4"
|
||||
#[[ $DEBUG_MODE = 1 ]] && echo $jdCookie_4 | sed 's/&/\n/g' > /ql/config/2.txt
|
||||
else
|
||||
echo "# 由于参加轮换的账号数量不足 2 个,本次暂不重组 Cookie ..."
|
||||
export JD_COOKIE="$JD_COOKIE"
|
||||
fi
|
||||
elif [[ $today_day -eq 1 ]]; then
|
||||
echo "# 今天是 1 号,不应用轮换模式,全部 Cookie 按正常顺序参加活动..."
|
||||
export JD_COOKIE="$JD_COOKIE"
|
||||
fi
|
||||
}
|
||||
|
||||
## 组队模式算法
|
||||
combine_team(){
|
||||
team_ck(){
|
||||
local tmp combined_tmp combined_all i j k m n
|
||||
for ((i = 0; i < $team_num_total; i++)); do
|
||||
#当前队伍是第几组
|
||||
j=$((i + 1))
|
||||
#发起组队的账号在Cookie数组中的序号
|
||||
k=$((i/team_num))
|
||||
tmp=""
|
||||
combined_tmp=""
|
||||
combined_all=""
|
||||
if [ $i -ne $team_num ]; then
|
||||
for ((m = 1; m < $teamer_num; m++)); do
|
||||
#当前组队的第二账号所在Cookie数组的序号
|
||||
n=$(((teamer_num -1)*i + m)) && [[ $n -ge $ori_user_sum ]] && continue
|
||||
tmp="${array[n]}"
|
||||
combined_tmp="$combined_tmp&$tmp"
|
||||
done
|
||||
combined_all="${array[k]}$combined_tmp"
|
||||
elif [ $i -eq $team_num ]; then
|
||||
for ((m = 1; m < $((teamer_num - 1)); m++)); do
|
||||
#第二账号发起的第一支组队,该队伍中的第三账号所在Cookie数组的序号
|
||||
n=$(((teamer_num -1)*i + m)) && [[ $n -ge $ori_user_sum ]] && continue
|
||||
tmp="${array[n]}"
|
||||
combined_tmp="$combined_tmp&$tmp"
|
||||
done
|
||||
combined_all="${array[k]}&${array[0]}$combined_tmp"
|
||||
fi
|
||||
jdCookie_4=$combined_all
|
||||
if [[ $jdCookie_4 ]]; then
|
||||
export JD_COOKIE="$jdCookie_4"
|
||||
#[[ $DEBUG_MODE = 1 ]] && echo $jdCookie_4
|
||||
echo -e "\n# 本次提交的是第 $j 组账号。"
|
||||
define_program "$local_scr"
|
||||
if [ $temp_status = 3 ]; then
|
||||
$which_program $local_scr_dir/$local_scr_name
|
||||
[[ $interval_time != "0" ]] && echo -e "# 等待 $interval_time 秒后开始进行下一组队任务 ..."
|
||||
sleep $interval_time
|
||||
else
|
||||
$which_program $local_scr_dir/$local_scr_name &
|
||||
sleep $delay_time
|
||||
fi
|
||||
fi
|
||||
done
|
||||
exit
|
||||
}
|
||||
|
||||
run_js_in_team(){
|
||||
if [[ $teamer_num -ge $user_sum ]]; then
|
||||
echo "# 每组队伍的成员数量不得大于或等于有效账号总数量,本次暂不重组 Cookie ..."
|
||||
export JD_COOKIE="$JD_COOKIE"
|
||||
elif [[ $((teamer_num * team_num)) -ge $user_sum ]]; then
|
||||
echo "# 参与组队的总成员数量不得大于或等于有效账号总数量,本次暂不重组 Cookie ..."
|
||||
export JD_COOKIE="$JD_COOKIE"
|
||||
else
|
||||
echo "# 正在应用 组队Cookie 模式..."
|
||||
#总组队数量
|
||||
team_num_total=$(((user_sum + teamer_num - 2)/(teamer_num - 1)))
|
||||
#前几个账号发起组队
|
||||
team_num_launch=$(((team_num_total + team_num - 1)/team_num))
|
||||
[[ $team_num -ge $team_num_total ]] && team_num=$team_num_total && [[ $team_num -lt 1 ]] && team_num=1
|
||||
echo -n "# 当前总共 $user_sum 个有效账号,其中前 $team_num_launch 个账号发起组队,每个账号最多可以发起 $team_num 次组队,一共组 $team_num_total 队,每支队伍最多包含 $teamer_num 个账号。"
|
||||
if [[ -n "$(echo $1|perl -pe "{s|\.\|s\|m\|h\|d||g}"|sed -n "/^[0-9]\+$/p")" ]]; then
|
||||
temp_status="1"
|
||||
delay_time="$(echo $1|perl -pe "{s|([a-z])(\d)+|\1 \2|g;}")"
|
||||
echo -e "各支队伍启动脚本的延隔时间为`format_time $1`。"
|
||||
elif [[ $1 = 0 ]]; then
|
||||
temp_status="2"
|
||||
delay_time="0"
|
||||
echo -e "所有队伍并发启动脚本,可能会占用较高的系统资源导致卡顿。"
|
||||
elif [[ $1 = "-" ]] && [[ -n "$(echo $2|perl -pe "{s|\.\|s\|m\|h\|d||g}"|sed -n "/^[0-9]\+$/p")" ]] ; then
|
||||
temp_status="3"
|
||||
interval_time="$(echo $2|perl -pe "{s|([a-z])(\d)|\1 \2|g;}")"
|
||||
echo -e "各支队伍启动脚本的间隔时间为`format_time $2`。"
|
||||
else
|
||||
temp_status="3"
|
||||
delay_time="0"
|
||||
interval_time="0"
|
||||
echo -e ""
|
||||
fi
|
||||
team_ck
|
||||
fi
|
||||
}
|
||||
local p q
|
||||
if [[ $1 ]] && [[ $2 ]]; then
|
||||
if [[ $1 = "-" ]] && [[ $2 = "-" ]] && [[ -n "$(echo $5|sed -n "/^[0-9]\+$/p")" ]]; then
|
||||
if [[ $5 = 0 ]]; then
|
||||
for p in ${activity_env[@]}; do
|
||||
activity_array=($(echo $p | perl -pe "{s|@| |g}"))
|
||||
teamer_num=${activity_array[0]}
|
||||
team_num=${activity_array[1]}
|
||||
export jd_zdjr_activityId=${activity_array[2]}
|
||||
export jd_zdjr_activityUrl=${activity_array[3]}
|
||||
echo -e "活动 ID (activityId) : $jd_zdjr_activityId"
|
||||
echo -e "活动链接(activityUrl): $jd_zdjr_activityUrl"
|
||||
run_js_in_team $3 $4
|
||||
done
|
||||
elif [[ $5 -gt 0 ]]; then
|
||||
q=$(($5 - 1))
|
||||
activity_array=($(echo ${activity_env[q]} | perl -pe "{s|@| |g}"))
|
||||
teamer_num=${activity_array[0]}
|
||||
team_num=${activity_array[1]}
|
||||
export jd_zdjr_activityId=${activity_array[2]}
|
||||
export jd_zdjr_activityUrl=${activity_array[3]}
|
||||
echo -e "活动 ID (activityId) : $jd_zdjr_activityId"
|
||||
echo -e "活动链接(activityUrl): $jd_zdjr_activityUrl"
|
||||
run_js_in_team $3 $4
|
||||
fi
|
||||
elif [[ -n "$(echo $1|sed -n "/^[0-9]\+$/p")" ]] && [[ -n "$(echo $2|sed -n "/^[0-9]\+$/p")" ]]; then
|
||||
# 每组队伍的成员数量
|
||||
teamer_num=$1
|
||||
# 单个账号最多发起的组队数量
|
||||
team_num=$2
|
||||
else
|
||||
# 每组队伍的成员数量
|
||||
teamer_num=$user_sum
|
||||
# 单个账号最多发起的组队数量
|
||||
team_num=1
|
||||
fi
|
||||
run_js_in_team $3 $4
|
||||
else
|
||||
echo "# 由于参数缺失,切换回 正常 Cookie 模式..."
|
||||
export JD_COOKIE="$JD_COOKIE"
|
||||
fi
|
||||
}
|
||||
|
||||
## 分段模式算法
|
||||
combine_segmentation(){
|
||||
local delay_time="$3"
|
||||
local interval_time="$4"
|
||||
local jdCookie_priority jdCookie_team_part i j k m n
|
||||
if [[ $1 ]] && [[ $2 ]]; then
|
||||
# 固定区账号数量
|
||||
[[ -n "$(echo $1|sed -n "/^[0-9]\+$/p")" ]] && fixed_num=$1 || fixed_num="0"
|
||||
# 每段账号总数量
|
||||
[[ -n "$(echo $2|sed -n "/^[0-9]\+$/p")" ]] && teamer_total_num=$2 || teamer_total_num=$ori_user_sum
|
||||
if [[ $fixed_num -ge $teamer_total_num ]]; then
|
||||
echo "# 固定账号数量不得大于或等于每段账号总数量,本次暂不重组 Cookie ..."
|
||||
export JD_COOKIE="$JD_COOKIE"
|
||||
elif [[ $teamer_total_num -ge $ori_user_sum ]]; then
|
||||
echo "# 分段账号数量不得大于或等于有效账号总数量,本次暂不重组 Cookie ..."
|
||||
export JD_COOKIE="$JD_COOKIE"
|
||||
elif [[ $fixed_num -lt $teamer_total_num ]]; then
|
||||
echo "# 正在应用 分段Cookie 模式..."
|
||||
local teamer_num="$((teamer_total_num - fixed_num))"
|
||||
local team_total_num=$(((ori_user_sum - fixed_num + teamer_num -1)/teamer_num)) && [[ $team_total_num -lt 1 ]] && team_total_num=1
|
||||
echo -n "# 当前总共 $user_sum 个有效账号"
|
||||
[[ $fixed_num -ne 0 ]] && echo -n ",其中前 $fixed_num 个账号为固定顺序"
|
||||
echo -n "。每 $teamer_total_num 个账号分一段,一共分 $team_total_num 段。"
|
||||
if [[ -n "$(echo $3|perl -pe "{s|\.\|s\|m\|h\|d||g}"|sed -n "/^[0-9]\+$/p")" ]]; then
|
||||
temp_status="1"
|
||||
delay_time="$(echo $3|perl -pe "{s|([a-z])(\d)+|\1 \2|g;}")"
|
||||
echo -e "各分段启动脚本的延隔时间为`format_time $3`。"
|
||||
echo -e "# 注意:如果每段的运行时间较长且延隔时间设定较短,运行日志可能会显示混乱,此为正常现象。"
|
||||
elif [[ $3 = 0 ]]; then
|
||||
temp_status="2"
|
||||
delay_time="0"
|
||||
echo -e "所有分段并发启动脚本,可能会占用较高的系统资源导致卡顿。"
|
||||
echo -e "# 注意:运行日志会显示混乱,此为正常现象。"
|
||||
elif [[ $3 = "-" ]] && [[ -n "$(echo $4|perl -pe "{s|\.\|s\|m\|h\|d||g}"|sed -n "/^[0-9]\+$/p")" ]] ; then
|
||||
temp_status="3"
|
||||
interval_time="$(echo $4|perl -pe "{s|([a-z])(\d)|\1 \2|g;}")"
|
||||
echo -e ""
|
||||
else
|
||||
temp_status="3"
|
||||
delay_time="0"
|
||||
interval_time="0"
|
||||
echo -e ""
|
||||
fi
|
||||
for ((m = 0; m < $fixed_num; m++)); do
|
||||
[[ ! ${ori_array[m]} ]] && continue
|
||||
tmp="${ori_array[m]}"
|
||||
jdCookie_priority="$jdCookie_priority&$tmp"
|
||||
done
|
||||
for ((i = 0; i < $team_total_num; i++)); do
|
||||
j=$((i + 1))
|
||||
m=$((teamer_num * i + fixed_num))
|
||||
n=$((teamer_num * j + fixed_num))
|
||||
[[ $n -gt $ori_user_sum ]] && n=$ori_user_sum
|
||||
t=$n && [[ $user_sum -lt $t ]] && t=$user_sum
|
||||
jdCookie_team_part=""
|
||||
for ((k = m; k < $t; k++)); do
|
||||
[[ ! ${ori_array[k]} ]] && continue
|
||||
tmp="${ori_array[k]}"
|
||||
jdCookie_team_part="$jdCookie_team_part&$tmp"
|
||||
done
|
||||
jdCookie_4=$(echo $jdCookie_priority$jdCookie_team_part | perl -pe "{s|^&+\|&+$||g}")
|
||||
if [[ $jdCookie_4 ]]; then
|
||||
export JD_COOKIE="$jdCookie_4"
|
||||
#[[ $DEBUG_MODE = 1 ]] && echo $jdCookie_4
|
||||
if [ $fixed_num -ne 0 ]; then
|
||||
if [ $teamer_num -gt 1 ]; then
|
||||
echo -e "\n# 本次提交的是前 $fixed_num 位账号及第 $((m + 1)) - $n 位账号。"
|
||||
elif [ $teamer_num -eq 1 ]; then
|
||||
echo -e "\n# 本次提交的是前 $fixed_num 位账号及第 $((m + 1)) 位账号。"
|
||||
fi
|
||||
elif [ $fixed_num -eq 0 ]; then
|
||||
if [ $teamer_num -gt 1 ]; then
|
||||
echo -e "\n# 本次提交的是第 $((m + 1)) - $n 位账号。"
|
||||
elif [ $teamer_num -eq 1 ]; then
|
||||
echo -e "\n# 本次提交的是第 $((m + 1)) 位账号。"
|
||||
fi
|
||||
fi
|
||||
define_program "$local_scr"
|
||||
if [ $temp_status = 3 ]; then
|
||||
$which_program $local_scr_dir/$local_scr_name
|
||||
[[ $interval_time != "0" ]] && echo -e "# 等待`format_time $interval_time`后开始进行下一段任务 ..."
|
||||
sleep $interval_time
|
||||
else
|
||||
$which_program $local_scr_dir/$local_scr_name &
|
||||
sleep $delay_time
|
||||
fi
|
||||
fi
|
||||
done
|
||||
exit
|
||||
fi
|
||||
else
|
||||
echo "# 由于参数缺失,本次暂不重组 Cookie ..."
|
||||
export JD_COOKIE="$JD_COOKIE"
|
||||
fi
|
||||
}
|
||||
|
||||
## 末尾Cookie
|
||||
combine_bottom(){
|
||||
local array_bottom i
|
||||
if [[ $Bottom_CK && ! $jdCookie_bottom ]]; then
|
||||
bottom_ck="$(def_urldecode $Bottom_CK | perl -pe "{s|,| |g;}")"
|
||||
i=0
|
||||
for j in $(def_pin_sub $bottom_ck); do
|
||||
[[ ! ${ori_array[j]} ]] && continue
|
||||
array_bottom[i]=${ori_array[j]}
|
||||
unset ori_array[j]
|
||||
let i++
|
||||
done
|
||||
jdCookie_bottom="&$(echo ${array_bottom[@]} | sed 's# #\&#g')"
|
||||
user_bottom_sum=${#array_bottom[*]}
|
||||
fi
|
||||
}
|
||||
|
||||
# 格式化时间
|
||||
format_time(){
|
||||
for i in $@; do
|
||||
if [[ -n "$(echo $i|perl -pe "{s|\.||g}"|sed -n "/^[0-9]\+$/p")" ]]; then
|
||||
time_text=" $i 秒"
|
||||
elif [[ -n "$(echo $i|perl -pe "{s|\.\|s\|m\|h\|d||g}"|sed -n "/^[0-9]\+$/p")" ]]; then
|
||||
time_text="$(echo $i|perl -pe "{s|([a-z])(\d)+|\1 \2|g; s|s| 秒|g; s|m| 分|g; s|h| 小时|g; s|d| 天|g; s|^| |g; s|(\d+)$|\1 秒|g;}")"
|
||||
fi
|
||||
echo -n "$time_text"
|
||||
done
|
||||
}
|
||||
|
||||
# Cookie 环境变量迭代导入
|
||||
[[ $jdCookie_4 ]] && array=($(echo $jdCookie_4 | sed 's/&/ /g')) && user_sum=${#array[*]}
|
||||
|
||||
case $Recombin_CK_Mode in
|
||||
1)
|
||||
combine_random $Recombin_CK_ARG1
|
||||
;;
|
||||
2)
|
||||
combine_priority $Recombin_CK_ARG1
|
||||
;;
|
||||
3)
|
||||
combine_rotation $Recombin_CK_ARG1 $Recombin_CK_ARG2
|
||||
;;
|
||||
4)
|
||||
combine_team $Recombin_CK_ARG1 $Recombin_CK_ARG2 $Recombin_CK_ARG3 $Recombin_CK_ARG4 $Recombin_CK_ARG5
|
||||
;;
|
||||
5)
|
||||
combine_segmentation $Recombin_CK_ARG1 $Recombin_CK_ARG2 $Recombin_CK_ARG3 $Recombin_CK_ARG4
|
||||
;;
|
||||
*)
|
||||
export JD_COOKIE="$JD_COOKIE"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
## 组合互助码格式化为全局变量的函数
|
||||
combine_sub() {
|
||||
#source $file_env
|
||||
local what_combine=$1
|
||||
local combined_all=""
|
||||
local tmp1 tmp2
|
||||
local TempBlockCookieInterval="$(echo $TempBlockCookie | perl -pe "{s|~|-|; s|_|-|}" | sed 's/\(\d\+\)-\(\d\+\)/{\1..\2}/g')"
|
||||
local TempBlockCookieArray=($(eval echo $TempBlockCookieInterval))
|
||||
local envs=$(eval echo "\$JD_COOKIE")
|
||||
local array=($(echo $envs | sed 's/&/ /g'))
|
||||
local user_sum=${#array[*]}
|
||||
local a b i j t sum combined_all
|
||||
for ((i=1; i <= $user_sum; i++)); do
|
||||
local tmp1=$what_combine$i
|
||||
local tmp2=${!tmp1}
|
||||
[[ ${tmp2} ]] && sum=$i || break
|
||||
done
|
||||
[[ ! $sum ]] && sum=$user_sum
|
||||
for ((j = 1; j <= $sum; j++)); do
|
||||
a=$temp_user_sum
|
||||
b=$sum
|
||||
if [[ $a -ne $b ]]; then
|
||||
for ((t = 0; t < ${#TempBlockCookieArray[*]}; t++)); do
|
||||
[[ "${TempBlockCookieArray[t]}" = "$j" ]] && continue 2
|
||||
done
|
||||
fi
|
||||
local tmp1=$what_combine$j
|
||||
local tmp2=${!tmp1}
|
||||
combined_all="$combined_all&$tmp2"
|
||||
done
|
||||
echo $combined_all | perl -pe "{s|^&||; s|^@+||; s|&@|&|g; s|@+&|&|g; s|@+|@|g; s|@+$||}"
|
||||
}
|
||||
|
||||
## 正常依次运行时,组合互助码格式化为全局变量
|
||||
combine_all() {
|
||||
for ((i = 0; i < ${#env_name[*]}; i++)); do
|
||||
result=$(combine_sub ${var_name[i]})
|
||||
if [[ $result ]]; then
|
||||
export ${env_name[i]}="$result"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
## 正常依次运行时,组合互助码格式化为全局变量
|
||||
combine_only() {
|
||||
for ((i = 0; i < ${#env_name[*]}; i++)); do
|
||||
case $local_scr in
|
||||
*${name_js[i]}*.js | *${name_js[i]}*.ts)
|
||||
if [[ -f $dir_log/.ShareCode/${name_config[i]}.log ]]; then
|
||||
. $dir_log/.ShareCode/${name_config[i]}.log
|
||||
result=$(combine_sub ${var_name[i]})
|
||||
if [[ $result ]]; then
|
||||
export ShareCodeConfigChineseName=${name_chinese[i]}
|
||||
export ShareCodeConfigName=${name_config[i]}
|
||||
export ShareCodeEnvName=${env_name[i]}
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
export ${env_name[i]}=""
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
## 提前替换js基础依赖
|
||||
JS_Deps_Replace() {
|
||||
if [ $js_deps_replace_envs ]; then
|
||||
local js_deps_replace_array=($(echo $js_deps_replace_envs | perl -pe "{s|&| |g}"))
|
||||
for i in "${js_deps_replace_array[@]}"; do
|
||||
local tmp_task_array=($(echo $i | perl -pe "{s|@| |g}"))
|
||||
local tmp_script_array=($(echo ${tmp_task_array[0]} | perl -pe "{s/\|/ /g}"))
|
||||
local tmp_skip_repo=($(echo ${tmp_task_array[1]} | perl -pe "{s/\|/ /g}"))
|
||||
for j in "${tmp_script_array[@]}"; do
|
||||
[[ ! $repo_dir ]] || [[ $repo_dir && ! ${tmp_skip_repo[@]} =~ $repo_dir ]] && [[ -f $dir_config/$j.js && $local_scr_dir ]] && cp -rf $dir_config/$j.js $local_scr_dir/$j.js
|
||||
done
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
[[ -f $dir_scripts/CK_WxPusherUid.json && $local_scr_dir && $local_scr_dir != $dir_scripts ]] && cp -rf $dir_scripts/CK_WxPusherUid.json $local_scr_dir/CK_WxPusherUid.json
|
||||
#source $file_env
|
||||
gen_pt_pin_array
|
||||
#JS_Deps_Replace
|
||||
TempBlock_CK
|
||||
#remove_void_ck
|
||||
if [[ -z $cookieStr ]];then
|
||||
Recombin_CK
|
||||
fi
|
||||
combine_only
|
||||
@@ -0,0 +1,539 @@
|
||||
const https = require('https');
|
||||
const http = require('http');
|
||||
const stream = require('stream');
|
||||
const zlib = require('zlib');
|
||||
const vm = require('vm');
|
||||
const PNG = require('png-js');
|
||||
let UA = `jdapp;iPhone;10.1.0;14.3;${randomString(40)};network/wifi;model/iPhone12,1;addressid/4199175193;appBuild/167774;jdSupportDarkMode/0;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1`;
|
||||
const validatorCount = process.env.JDJR_validator_Count ? process.env.JDJR_validator_Count : 100
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
console.log('JDJR验证用时: %fs', (Date.now() - this.t) / 1000);
|
||||
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: '',
|
||||
};
|
||||
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}, ...extraData, ...data}).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",
|
||||
'Proxy-Connection': 'keep-alive',
|
||||
'Referer': 'https://h5.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 injectToRequest(fn,scene = 'cww', ua = '') {
|
||||
if(ua) UA = ua
|
||||
return (opts, cb) => {
|
||||
fn(opts, async (err, resp, data) => {
|
||||
if (err) {
|
||||
console.error(JSON.stringify(err));
|
||||
return;
|
||||
}
|
||||
if (data.search('验证') > -1) {
|
||||
console.log('JDJR验证中......');
|
||||
let arr = opts.url.split("&")
|
||||
let eid = ''
|
||||
for(let i of arr){
|
||||
if(i.indexOf("eid=")>-1){
|
||||
eid = i.split("=") && i.split("=")[1] || ''
|
||||
}
|
||||
}
|
||||
const res = await new JDJRValidator().run(scene, eid);
|
||||
|
||||
opts.url += `&validate=${res.validate}`;
|
||||
fn(opts, cb);
|
||||
} else {
|
||||
cb(err, resp, data);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
exports.injectToRequest = injectToRequest;
|
||||
Vendored
+1
File diff suppressed because one or more lines are too long
@@ -0,0 +1,270 @@
|
||||
let request = require('request');
|
||||
let CryptoJS = require('crypto-js');
|
||||
let qs = require('querystring');
|
||||
let urls = require('url');
|
||||
let path = require('path');
|
||||
let notify = require('./sendNotify');
|
||||
let mainEval = require("./eval");
|
||||
let assert = require('assert');
|
||||
let jxAlgo = require("./jxAlgo");
|
||||
let config = require("./config");
|
||||
let user = {}
|
||||
try {
|
||||
user = require("./user")
|
||||
} catch (e) {}
|
||||
class env {
|
||||
constructor(name) {
|
||||
this.config = { ...config,
|
||||
...process.env,
|
||||
...user,
|
||||
};
|
||||
this.name = name;
|
||||
this.message = [];
|
||||
this.sharecode = [];
|
||||
this.code = [];
|
||||
this.timestamp = new Date().getTime();
|
||||
this.time = this.start = parseInt(this.timestamp / 1000);
|
||||
this.options = {
|
||||
'headers': {}
|
||||
};
|
||||
console.log(`\n🔔${this.name}, 开始!\n`)
|
||||
console.log(`=========== 脚本执行-北京时间(UTC+8):${new Date(new Date().getTime() + new Date().getTimezoneOffset()*60*1000 + 8*60*60*1000).toLocaleString()} ===========\n`)
|
||||
}
|
||||
done() {
|
||||
let timestamp = new Date().getTime();
|
||||
let work = ((timestamp - this.timestamp) / 1000).toFixed(2)
|
||||
console.log(`=========================脚本执行完成,耗时${work}s============================\n`)
|
||||
console.log(`🔔${this.name}, 结束!\n`)
|
||||
}
|
||||
notify(array) {
|
||||
let text = '';
|
||||
for (let i of array) {
|
||||
text += `${i.user} -- ${i.msg}\n`
|
||||
}
|
||||
console.log(`\n=============================开始发送提醒消息=============================`)
|
||||
notify.sendNotify(this.name + "消息提醒", text)
|
||||
}
|
||||
wait(t) {
|
||||
return new Promise(e => setTimeout(e, t))
|
||||
}
|
||||
setOptions(params) {
|
||||
this.options = params;
|
||||
}
|
||||
setCookie(cookie) {
|
||||
this.options.headers.cookie = cookie
|
||||
}
|
||||
jsonParse(str) {
|
||||
try {
|
||||
return JSON.parse(str);
|
||||
} catch (e) {
|
||||
try {
|
||||
let data = this.match([/try\s*\{\w+\s*\(([^\)]+)/, /\w+\s*\(([^\)]+)/], str)
|
||||
return JSON.parse(data);
|
||||
} catch (ee) {
|
||||
try {
|
||||
let cb = this.match(/try\s*\{\s*(\w+)/, str)
|
||||
if (cb) {
|
||||
let func = "";
|
||||
let data = str.replace(cb, `func=`)
|
||||
eval(data);
|
||||
return func
|
||||
}
|
||||
} catch (eee) {
|
||||
return str
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
curl(params, extra = '') {
|
||||
if (typeof(params) != 'object') {
|
||||
params = {
|
||||
'url': params
|
||||
}
|
||||
}
|
||||
params = Object.assign({ ...this.options
|
||||
}, params);
|
||||
params.method = params.body ? 'POST' : 'GET';
|
||||
if (params.hasOwnProperty('cookie')) {
|
||||
params.headers.cookie = params.cookie
|
||||
}
|
||||
if (params.hasOwnProperty('ua') || params.hasOwnProperty('useragent')) {
|
||||
params.headers['user-agent'] = params.ua
|
||||
}
|
||||
if (params.hasOwnProperty('referer')) {
|
||||
params.headers.referer = params.referer
|
||||
}
|
||||
if (params.hasOwnProperty('params')) {
|
||||
params.url += '?' + qs.stringify(params.params)
|
||||
}
|
||||
if (params.hasOwnProperty('form')) {
|
||||
params.method = 'POST'
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
request(params, async (err, resp, data) => {
|
||||
try {
|
||||
if (params.console) {
|
||||
console.log(data)
|
||||
}
|
||||
this.source = this.jsonParse(data);
|
||||
if (extra) {
|
||||
this[extra] = this.source
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e, resp)
|
||||
} finally {
|
||||
resolve(data);
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
dumps(dict) {
|
||||
return JSON.stringify(dict)
|
||||
}
|
||||
loads(str) {
|
||||
return JSON.parse(str)
|
||||
}
|
||||
notice(msg) {
|
||||
this.message.push({
|
||||
'index': this.index,
|
||||
'user': this.user,
|
||||
'msg': msg
|
||||
})
|
||||
}
|
||||
notices(msg, user, index = '') {
|
||||
this.message.push({
|
||||
'user': user,
|
||||
'msg': msg,
|
||||
'index': index
|
||||
})
|
||||
}
|
||||
urlparse(url) {
|
||||
return urls.parse(url, true, true)
|
||||
}
|
||||
md5(encryptString) {
|
||||
return CryptoJS.MD5(encryptString).toString()
|
||||
}
|
||||
haskey(data, key, value) {
|
||||
value = typeof value !== 'undefined' ? value : '';
|
||||
var spl = key.split('.');
|
||||
for (var i of spl) {
|
||||
i = !isNaN(i) ? parseInt(i) : i;
|
||||
try {
|
||||
data = data[i];
|
||||
} catch (error) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
if (data == undefined) {
|
||||
return ''
|
||||
}
|
||||
if (value !== '') {
|
||||
return data === value ? true : false;
|
||||
} else {
|
||||
return data
|
||||
}
|
||||
}
|
||||
match(pattern, string) {
|
||||
pattern = (pattern instanceof Array) ? pattern : [pattern];
|
||||
for (let pat of pattern) {
|
||||
// var match = string.match(pat);
|
||||
var match = pat.exec(string)
|
||||
if (match) {
|
||||
var len = match.length;
|
||||
if (len == 1) {
|
||||
return match;
|
||||
} else if (len == 2) {
|
||||
return match[1];
|
||||
} else {
|
||||
var r = [];
|
||||
for (let i = 1; i < len; i++) {
|
||||
r.push(match[i])
|
||||
}
|
||||
return r;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// console.log(pat.exec(string))
|
||||
}
|
||||
return '';
|
||||
}
|
||||
matchall(pattern, string) {
|
||||
pattern = (pattern instanceof Array) ? pattern : [pattern];
|
||||
var match;
|
||||
var result = [];
|
||||
for (var pat of pattern) {
|
||||
while ((match = pat.exec(string)) != null) {
|
||||
var len = match.length;
|
||||
if (len == 1) {
|
||||
result.push(match);
|
||||
} else if (len == 2) {
|
||||
result.push(match[1]);
|
||||
} else {
|
||||
var r = [];
|
||||
for (let i = 1; i < len; i++) {
|
||||
r.push(match[i])
|
||||
}
|
||||
result.push(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
compare(property) {
|
||||
return function(a, b) {
|
||||
var value1 = a[property];
|
||||
var value2 = b[property];
|
||||
return value1 - value2;
|
||||
}
|
||||
}
|
||||
filename(file, rename = '') {
|
||||
if (!this.runfile) {
|
||||
this.runfile = path.basename(file).replace(".js", '').replace(/-/g, '_')
|
||||
}
|
||||
if (rename) {
|
||||
rename = `_${rename}`;
|
||||
}
|
||||
return path.basename(file).replace(".js", rename).replace(/-/g, '_');
|
||||
}
|
||||
rand(n, m) {
|
||||
var random = Math.floor(Math.random() * (m - n + 1) + n);
|
||||
return random;
|
||||
}
|
||||
random(arr, num) {
|
||||
var temp_array = new Array();
|
||||
for (var index in arr) {
|
||||
temp_array.push(arr[index]);
|
||||
}
|
||||
var return_array = new Array();
|
||||
for (var i = 0; i < num; i++) {
|
||||
if (temp_array.length > 0) {
|
||||
var arrIndex = Math.floor(Math.random() * temp_array.length);
|
||||
return_array[i] = temp_array[arrIndex];
|
||||
temp_array.splice(arrIndex, 1);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return return_array;
|
||||
}
|
||||
compact(lists, keys) {
|
||||
let array = {};
|
||||
for (let i of keys) {
|
||||
if (lists[i]) {
|
||||
array[i] = lists[i];
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
unique(arr) {
|
||||
return Array.from(new Set(arr));
|
||||
}
|
||||
end(args) {
|
||||
return args[args.length - 1]
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
env,
|
||||
eval: mainEval,
|
||||
assert,
|
||||
jxAlgo,
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = {"ThreadJs":[],"invokeKey":"RtKLB8euDo7KwsO0"}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,83 @@
|
||||
function mainEval($) {
|
||||
return `
|
||||
!(async () => {
|
||||
jdcookie = process.env.JD_COOKIE ? process.env.JD_COOKIE.split("&") : require("./function/jdcookie").cookie;
|
||||
cookies={
|
||||
'all':jdcookie,
|
||||
'help': typeof(help) != 'undefined' ? [...jdcookie].splice(0,parseInt(help)):[]
|
||||
}
|
||||
$.sleep=cookies['all'].length * 500
|
||||
taskCookie=cookies['all']
|
||||
jxAlgo = new common.jxAlgo();
|
||||
if ($.readme) {
|
||||
console.log(\`使用说明:\\n\${$.readme}\\n以上内容仅供参考,有需求自行添加\\n\`,)
|
||||
}
|
||||
console.log(\`======================本次任务共\${taskCookie.length}个京东账户Cookie======================\\n\`)
|
||||
try{
|
||||
await prepare();
|
||||
|
||||
if ($.sharecode.length > 0) {
|
||||
$.sharecode = $.sharecode.filter(d=>d && JSON.stringify(d)!='{}')
|
||||
console.log('助力码', $.sharecode )
|
||||
}
|
||||
}catch(e1){console.log("初始函数不存在,将继续执行主函数Main\\n")}
|
||||
if (typeof(main) != 'undefined') {
|
||||
try{
|
||||
for (let i = 0; i < taskCookie.filter(d => d).length; i++) {
|
||||
$.cookie = taskCookie[i];
|
||||
$.user = decodeURIComponent($.cookie.match(/pt_pin=([^;]+)/)[1])
|
||||
$.index = parseInt(i) + 1;
|
||||
let info = {
|
||||
'index': $.index,
|
||||
'user': $.user,
|
||||
'cookie': $.cookie
|
||||
}
|
||||
if (!$.thread) {
|
||||
console.log(\`\n******开始【京东账号\${$.index}】\${$.user} 任务*********\n\`);
|
||||
}
|
||||
if ($.config[\`\${$.runfile}_except\`] && $.config[\`\${$.runfile}_except\`].includes(\$.user)) {
|
||||
console.log(\`全局变量\${$.runfile}_except中配置了该账号pt_pin,跳过此次任务\`)
|
||||
}else{
|
||||
$.setCookie($.cookie)
|
||||
try{
|
||||
if ($.sharecode.length > 0) {
|
||||
for (let smp of $.sharecode) {
|
||||
smp = Object.assign({ ...info}, smp);
|
||||
$.thread ? main(smp) : await main(smp);
|
||||
}
|
||||
}else{
|
||||
$.thread ? main(info) : await main(info);
|
||||
}
|
||||
}
|
||||
catch(em){
|
||||
console.log(em.message)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}catch(em){console.log(em.message)}
|
||||
if ($.thread) {
|
||||
await $.wait($.sleep)
|
||||
}
|
||||
}
|
||||
if (typeof(extra) != 'undefined') {
|
||||
console.log(\`============================开始运行额外任务============================\`)
|
||||
try{
|
||||
await extra();
|
||||
}catch(e4){console.log(e4.message)}
|
||||
}
|
||||
})().catch((e) => {
|
||||
console.log(e.message)
|
||||
}).finally(() => {
|
||||
if ($.message.length > 0) {
|
||||
$.notify($.message)
|
||||
}
|
||||
$.done();
|
||||
});
|
||||
|
||||
`
|
||||
}
|
||||
module.exports = {
|
||||
mainEval
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import axios from "axios"
|
||||
import {format} from "date-fns"
|
||||
import * as CryptoJS from 'crypto-js'
|
||||
|
||||
class H5ST {
|
||||
tk: string;
|
||||
timestamp: string;
|
||||
rd: string;
|
||||
appId: string;
|
||||
fp: string;
|
||||
time: number;
|
||||
ua: string
|
||||
enc: string;
|
||||
|
||||
constructor(appId: string, ua: string, fp: string) {
|
||||
this.appId = appId
|
||||
this.ua = ua
|
||||
this.fp = fp || this.__genFp()
|
||||
}
|
||||
|
||||
__genFp() {
|
||||
let e = "0123456789";
|
||||
let a = 13;
|
||||
let i = '';
|
||||
for (; a--;)
|
||||
i += e[Math.random() * e.length | 0];
|
||||
return (i + Date.now()).slice(0, 16)
|
||||
}
|
||||
|
||||
async __genAlgo() {
|
||||
this.time = Date.now()
|
||||
this.timestamp = format(this.time, "yyyyMMddHHmmssSSS")
|
||||
let {data} = await axios.post(`https://cactus.jd.com/request_algo?g_ty=ajax`, {
|
||||
'version': '3.0',
|
||||
'fp': this.fp,
|
||||
'appId': this.appId.toString(),
|
||||
'timestamp': this.time,
|
||||
'platform': 'web',
|
||||
'expandParams': ''
|
||||
}, {
|
||||
headers: {
|
||||
'Host': 'cactus.jd.com',
|
||||
'accept': 'application/json',
|
||||
'content-type': 'application/json',
|
||||
'user-agent': this.ua,
|
||||
}
|
||||
})
|
||||
this.tk = data.data.result.tk
|
||||
this.rd = data.data.result.algo.match(/rd='(.*)'/)[1]
|
||||
this.enc = data.data.result.algo.match(/algo\.(.*)\(/)[1]
|
||||
}
|
||||
|
||||
__genKey(tk: string, fp: string, ts: string, ai: string, algo: object) {
|
||||
let str = `${tk}${fp}${ts}${ai}${this.rd}`;
|
||||
return algo[this.enc](str, tk)
|
||||
}
|
||||
|
||||
__genH5st(body: object) {
|
||||
let y = this.__genKey(this.tk, this.fp, this.timestamp, this.appId, CryptoJS).toString(CryptoJS.enc.Hex)
|
||||
let s = ''
|
||||
for (let key of Object.keys(body)) {
|
||||
key === 'body' ? s += `${key}:${CryptoJS.SHA256(body[key]).toString(CryptoJS.enc.Hex)}&` : s += `${key}:${body[key]}&`
|
||||
}
|
||||
s = s.slice(0, -1)
|
||||
s = CryptoJS.HmacSHA256(s, y).toString(CryptoJS.enc.Hex)
|
||||
return encodeURIComponent(`${this.timestamp};${this.fp};${this.appId.toString()};${this.tk};${s};3.0;${this.time.toString()}`)
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
H5ST
|
||||
}
|
||||
@@ -0,0 +1,466 @@
|
||||
const https = require('https');
|
||||
const http = require('http');
|
||||
const stream = require('stream');
|
||||
const zlib = require('zlib');
|
||||
const vm = require('vm');
|
||||
const PNG = require('png-js');
|
||||
const UA = 'jdapp;iPhone;9.4.6;14.2;965af808880443e4c1306a54afdd5d5ae771de46;network/wifi;supportApplePay/0;hasUPPay/0;hasOCPay/0;model/iPhone8,4;addressid/;supportBestPay/0;appBuild/167618;jdSupportDarkMode/0;Mozilla/5.0 (iPhone; CPU iPhone OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1';
|
||||
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;
|
||||
}
|
||||
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",
|
||||
"scene": "cww",
|
||||
"product": "embed",
|
||||
"lang": "zh_CN",
|
||||
};
|
||||
let SERVER = 'iv.jd.com';
|
||||
if (process.env.JDJR_SERVER) {
|
||||
SERVER = process.env.JDJR_SERVER
|
||||
}
|
||||
class JDJRValidator {
|
||||
constructor() {
|
||||
this.data = {};
|
||||
this.x = 0;
|
||||
this.t = Date.now();
|
||||
this.n = 0;
|
||||
}
|
||||
async run() {
|
||||
const tryRecognize = async () => {
|
||||
const x = await this.recognize();
|
||||
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(3000);
|
||||
//await sleep(pos[pos.length - 1][2] - Date.now());
|
||||
const result = await JDJRValidator.jsonp('/slide/s.html', {
|
||||
d,
|
||||
...this.data
|
||||
});
|
||||
if (result.message === 'success') {
|
||||
// console.log(result);
|
||||
// console.log('JDJRValidator: %fs', (Date.now() - this.t) / 1000);
|
||||
return result;
|
||||
} else {
|
||||
if (this.n > 60) {
|
||||
return;
|
||||
}
|
||||
this.n++;
|
||||
return await this.run();
|
||||
}
|
||||
}
|
||||
async recognize() {
|
||||
const data = await JDJRValidator.jsonp('/slide/g.html', {
|
||||
e: ''
|
||||
});
|
||||
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);
|
||||
const puzzleX = await re.run();
|
||||
if (puzzleX > 0) {
|
||||
this.data = {
|
||||
c: data.challenge,
|
||||
w: re.w,
|
||||
e: '',
|
||||
s: '',
|
||||
o: '',
|
||||
};
|
||||
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('successful: %f\%', (count / n) * 100);
|
||||
console.timeEnd('PuzzleRecognizer');
|
||||
}
|
||||
static jsonp(api, data = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const fnId = `jsonp_${String(Math.random()).replace('.', '')}`;
|
||||
const extraData = {
|
||||
callback: fnId
|
||||
};
|
||||
const query = new URLSearchParams({ ...DATA,
|
||||
...extraData,
|
||||
...data
|
||||
}).toString();
|
||||
const url = `http://${SERVER}${api}?${query}`;
|
||||
const headers = {
|
||||
'Accept': '*/*',
|
||||
'Accept-Encoding': 'gzip,deflate,br',
|
||||
'Accept-Language': 'zh-CN,en-US',
|
||||
'Connection': 'keep-alive',
|
||||
'Host': SERVER,
|
||||
'Proxy-Connection': 'keep-alive',
|
||||
'Referer': 'https://h5.m.jd.com/babelDiy/Zeus/2wuqXrZrhygTQzYA7VufBEpj4amH/index.html',
|
||||
'User-Agent': UA,
|
||||
};
|
||||
const req = http.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 = 32;
|
||||
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 + 12, 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: 100,
|
||||
});
|
||||
}
|
||||
}
|
||||
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 + 20, 10);
|
||||
const currY = parseInt(this.y + 20, 10);
|
||||
const currT = this.t + movedT;
|
||||
this.pos.push([currX, currY, currT]);
|
||||
}
|
||||
this.x += x;
|
||||
this.y += y;
|
||||
this.t += Math.max(duration, movedT);
|
||||
}
|
||||
}
|
||||
exports.JDJRValidator = JDJRValidator
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
此文件为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(`============脚本执行时间:${new Date(new Date().getTime() + new Date().getTimezoneOffset()*60*1000 + 8*60*60*1000).toLocaleString('chinese',{hour12:false})}=============\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();
|
||||
}
|
||||
console.log('>>>>>>>>>>>>>>6Dylan6 提示:任务正常运行中>>>>>>>>>>>>>>>\n')
|
||||
@@ -0,0 +1,204 @@
|
||||
let request = require("request");
|
||||
let CryptoJS = require('crypto-js');
|
||||
let qs = require("querystring");
|
||||
Date.prototype.Format = function(fmt) {
|
||||
var e,
|
||||
n = this,
|
||||
d = fmt,
|
||||
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)));
|
||||
for (var k in l) {
|
||||
if (new RegExp("(".concat(k, ")")).test(d)) {
|
||||
var t, a = "S+" === k ? "000" : "00";
|
||||
d = d.replace(RegExp.$1, 1 == RegExp.$1.length ? l[k] : ("".concat(a) + l[k]).substr("".concat(l[k]).length))
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
function generateFp() {
|
||||
let e = "0123456789";
|
||||
let a = 13;
|
||||
let i = '';
|
||||
for (; a--;) i += e[Math.random() * e.length | 0];
|
||||
return (i + Date.now()).slice(0, 16)
|
||||
}
|
||||
|
||||
function getUrlData(url, name) {
|
||||
if (typeof URL !== "undefined") {
|
||||
let urls = new URL(url);
|
||||
let data = urls.searchParams.get(name);
|
||||
return data ? data : '';
|
||||
} else {
|
||||
const query = url.match(/\?.*/)[0].substring(1)
|
||||
const vars = query.split('&')
|
||||
for (let i = 0; i < vars.length; i++) {
|
||||
const pair = vars[i].split('=')
|
||||
if (pair[0] === name) {
|
||||
return vars[i].substr(vars[i].indexOf('=') + 1);
|
||||
}
|
||||
}
|
||||
return ''
|
||||
}
|
||||
}
|
||||
class jxAlgo {
|
||||
constructor(params = {}) {
|
||||
this.appId = 10001
|
||||
this.result = {}
|
||||
this.timestamp = Date.now();
|
||||
for (let i in params) {
|
||||
this[i] = params[i]
|
||||
}
|
||||
}
|
||||
set(params = {}) {
|
||||
for (let i in params) {
|
||||
this[i] = params[i]
|
||||
}
|
||||
}
|
||||
get(key) {
|
||||
return this[key]
|
||||
}
|
||||
async dec(url) {
|
||||
if (!this.tk) {
|
||||
this.fingerprint = generateFp();
|
||||
await this.requestAlgo()
|
||||
}
|
||||
let obj = qs.parse(url.split("?")[1]);
|
||||
let stk = obj['_stk'];
|
||||
return this.h5st(this.timestamp, stk, url)
|
||||
}
|
||||
h5st(time, stk, url) {
|
||||
stk = stk || (url ? getUrlData(url, '_stk') : '')
|
||||
const timestamp = new Date(time).Format("yyyyMMddhhmmssSSS");
|
||||
let hash1 = this.enCryptMethodJD(this.tk, this.fingerprint.toString(), timestamp.toString(), this.appId.toString(), CryptoJS).toString(CryptoJS.enc.Hex);
|
||||
let st = '';
|
||||
stk.split(',').map((item, index) => {
|
||||
st += `${item}:${getUrlData(url, item)}${index === stk.split(',').length - 1 ? '' : '&'}`;
|
||||
})
|
||||
const hash2 = CryptoJS.HmacSHA256(st, hash1.toString()).toString(CryptoJS.enc.Hex);
|
||||
const enc = (["".concat(timestamp.toString()), "".concat(this.fingerprint.toString()), "".concat(this.appId.toString()), "".concat(this.tk), "".concat(hash2)].join(";"))
|
||||
this.result['fingerprint'] = this.fingerprint;
|
||||
this.result['timestamp'] = this.timestamp
|
||||
this.result['stk'] = stk;
|
||||
this.result['h5st'] = enc
|
||||
let sp = url.split("?");
|
||||
let obj = qs.parse(sp[1])
|
||||
if (obj.callback) {
|
||||
delete obj.callback
|
||||
}
|
||||
let params = Object.assign(obj, {
|
||||
'_time': this.timestamp,
|
||||
'_': this.timestamp,
|
||||
'timestamp': this.timestamp,
|
||||
'sceneval': 2,
|
||||
'g_login_type': 1,
|
||||
'h5st': enc,
|
||||
})
|
||||
this.result['url'] = `${sp[0]}?${qs.stringify(params)}`
|
||||
return this.result
|
||||
}
|
||||
token(user) {
|
||||
let nickname = user.includes('pt_pin') ? user.match(/pt_pin=([^;]+)/)[1] : user;
|
||||
let phoneId = this.createuuid(40, 'lc');
|
||||
|
||||
let token = this.md5(decodeURIComponent(nickname) + this.timestamp + phoneId + 'tPOamqCuk9NLgVPAljUyIHcPRmKlVxDy');
|
||||
return {
|
||||
'strPgtimestamp': this.timestamp,
|
||||
'strPhoneID': phoneId,
|
||||
'strPgUUNum': token
|
||||
}
|
||||
}
|
||||
md5(encryptString) {
|
||||
return CryptoJS.MD5(encryptString).toString()
|
||||
}
|
||||
createuuid(a, c) {
|
||||
switch (c) {
|
||||
case "a":
|
||||
c = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
break;
|
||||
case "n":
|
||||
c = "0123456789";
|
||||
break;
|
||||
case "c":
|
||||
c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
break;
|
||||
case "l":
|
||||
c = "abcdefghijklmnopqrstuvwxyz";
|
||||
break;
|
||||
case 'cn':
|
||||
case 'nc':
|
||||
c = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
|
||||
break;
|
||||
case "lc":
|
||||
case "cl":
|
||||
c = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
break;
|
||||
default:
|
||||
c = "0123456789abcdef"
|
||||
}
|
||||
var e = "";
|
||||
for (var g = 0; g < a; g++) e += c[Math.ceil(1E8 * Math.random()) % c.length];
|
||||
return e
|
||||
}
|
||||
async requestAlgo() {
|
||||
const options = {
|
||||
"url": `https://cactus.jd.com/request_algo?g_ty=ajax`,
|
||||
"headers": {
|
||||
'Authority': 'cactus.jd.com',
|
||||
'Pragma': 'no-cache',
|
||||
'Cache-Control': 'no-cache',
|
||||
'Accept': 'application/json',
|
||||
'User-Agent': 'jdpingou;iPhone;4.9.4;12.4;ae49fae72d0a8976f5155267f56ec3a5b0da75c3;network/wifi;model/iPhone8,4;appBuild/100579;ADID/00000000-0000-0000-0000-000000000000;supportApplePay/1;hasUPPay/0;pushNoticeIsOpen/0;hasOCPay/0;supportBestPay/0;session/1;pap/JA2019_3111789;brand/apple;supportJDSHWK/1;Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
|
||||
'Content-Type': 'application/json',
|
||||
'Origin': 'https://st.jingxi.com',
|
||||
'Sec-Fetch-Site': 'cross-site',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
'Referer': 'https://st.jingxi.com/pingou/dream_factory/index.html?ptag=7155.9.4',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.9,zh-TW;q=0.8,en;q=0.7'
|
||||
},
|
||||
'body': JSON.stringify({
|
||||
"version": "1.0",
|
||||
"fp": this.fingerprint,
|
||||
"appId": this.appId.toString(),
|
||||
"timestamp": this.timestamp,
|
||||
"platform": "web",
|
||||
"expandParams": ""
|
||||
})
|
||||
}
|
||||
return new Promise(async resolve => {
|
||||
request.post(options, (err, resp, data) => {
|
||||
try {
|
||||
if (data) {
|
||||
data = JSON.parse(data);
|
||||
if (data['status'] === 200) {
|
||||
let result = data.data.result
|
||||
this.tk = result.tk;
|
||||
let enCryptMethodJDString = result.algo;
|
||||
if (enCryptMethodJDString) {
|
||||
this.enCryptMethodJD = new Function(`return ${enCryptMethodJDString}`)();
|
||||
}
|
||||
this.result = result
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
} finally {
|
||||
resolve(this.result);
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
module.exports = jxAlgo
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1004
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
+204
@@ -0,0 +1,204 @@
|
||||
'use strict';
|
||||
|
||||
const got = require('got');
|
||||
require('dotenv').config();
|
||||
const { readFile } = require('fs/promises');
|
||||
const path = require('path');
|
||||
|
||||
const qlDir = '/ql';
|
||||
const fs = require('fs');
|
||||
let Fileexists = fs.existsSync('/ql/data/config/auth.json');
|
||||
let authFile="";
|
||||
if (Fileexists)
|
||||
authFile="/ql/data/config/auth.json"
|
||||
else
|
||||
authFile="/ql/config/auth.json"
|
||||
//const authFile = path.join(qlDir, 'config/auth.json');
|
||||
|
||||
const api = got.extend({
|
||||
prefixUrl: 'http://127.0.0.1:5600',
|
||||
retry: { limit: 0 },
|
||||
});
|
||||
|
||||
async function getToken() {
|
||||
const authConfig = JSON.parse(await readFile(authFile));
|
||||
return authConfig.token;
|
||||
}
|
||||
|
||||
module.exports.getEnvs = async () => {
|
||||
const token = await getToken();
|
||||
const body = await api({
|
||||
url: 'api/envs',
|
||||
searchParams: {
|
||||
searchValue: 'JD_COOKIE',
|
||||
t: Date.now(),
|
||||
},
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
authorization: `Bearer ${token}`,
|
||||
},
|
||||
}).json();
|
||||
return body.data;
|
||||
};
|
||||
|
||||
module.exports.getEnvsCount = async () => {
|
||||
const data = await this.getEnvs();
|
||||
return data.length;
|
||||
};
|
||||
|
||||
module.exports.addEnv = async (cookie, remarks) => {
|
||||
const token = await getToken();
|
||||
const body = await api({
|
||||
method: 'post',
|
||||
url: 'api/envs',
|
||||
params: { t: Date.now() },
|
||||
json: [{
|
||||
name: 'JD_COOKIE',
|
||||
value: cookie,
|
||||
remarks,
|
||||
}],
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json;charset=UTF-8',
|
||||
},
|
||||
}).json();
|
||||
return body;
|
||||
};
|
||||
|
||||
module.exports.updateEnv = async (cookie, eid, remarks) => {
|
||||
const token = await getToken();
|
||||
const body = await api({
|
||||
method: 'put',
|
||||
url: 'api/envs',
|
||||
params: { t: Date.now() },
|
||||
json: {
|
||||
name: 'JD_COOKIE',
|
||||
value: cookie,
|
||||
_id: eid,
|
||||
remarks,
|
||||
},
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json;charset=UTF-8',
|
||||
},
|
||||
}).json();
|
||||
return body;
|
||||
};
|
||||
|
||||
module.exports.updateEnv11 = async (cookie, eid, remarks) => {
|
||||
const token = await getToken();
|
||||
const body = await api({
|
||||
method: 'put',
|
||||
url: 'api/envs',
|
||||
params: { t: Date.now() },
|
||||
json: {
|
||||
name: 'JD_COOKIE',
|
||||
value: cookie,
|
||||
id: eid,
|
||||
remarks,
|
||||
},
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json;charset=UTF-8',
|
||||
},
|
||||
}).json();
|
||||
return body;
|
||||
};
|
||||
|
||||
module.exports.DisableCk = async (eid) => {
|
||||
const token = await getToken();
|
||||
const body = await api({
|
||||
method: 'put',
|
||||
url: 'api/envs/disable',
|
||||
params: { t: Date.now() },
|
||||
body: JSON.stringify([eid]),
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json;charset=UTF-8',
|
||||
},
|
||||
}).json();
|
||||
return body;
|
||||
};
|
||||
|
||||
module.exports.EnableCk = async (eid) => {
|
||||
const token = await getToken();
|
||||
const body = await api({
|
||||
method: 'put',
|
||||
url: 'api/envs/enable',
|
||||
params: { t: Date.now() },
|
||||
body: JSON.stringify([eid]),
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json;charset=UTF-8',
|
||||
},
|
||||
}).json();
|
||||
return body;
|
||||
};
|
||||
|
||||
module.exports.getstatus = async(eid) => {
|
||||
const envs = await this.getEnvs();
|
||||
var tempid = 0;
|
||||
for (let i = 0; i < envs.length; i++) {
|
||||
tempid = 0;
|
||||
if (envs[i]._id) {
|
||||
tempid = envs[i]._id;
|
||||
}
|
||||
if (envs[i].id) {
|
||||
tempid = envs[i].id;
|
||||
}
|
||||
if (tempid == eid) {
|
||||
return envs[i].status;
|
||||
}
|
||||
}
|
||||
return 99;
|
||||
};
|
||||
|
||||
module.exports.getEnvById = async(eid) => {
|
||||
const envs = await this.getEnvs();
|
||||
var tempid = 0;
|
||||
for (let i = 0; i < envs.length; i++) {
|
||||
tempid = 0;
|
||||
if (envs[i]._id) {
|
||||
tempid = envs[i]._id;
|
||||
}
|
||||
if (envs[i].id) {
|
||||
tempid = envs[i].id;
|
||||
}
|
||||
if (tempid == eid) {
|
||||
return envs[i].value;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
module.exports.getEnvByPtPin = async (Ptpin) => {
|
||||
const envs = await this.getEnvs();
|
||||
for (let i = 0; i < envs.length; i++) {
|
||||
var tempptpin = decodeURIComponent(envs[i].value.match(/pt_pin=([^; ]+)(?=;?)/) && envs[i].value.match(/pt_pin=([^; ]+)(?=;?)/)[1]);
|
||||
if(tempptpin==Ptpin){
|
||||
return envs[i];
|
||||
}
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
module.exports.delEnv = async (eid) => {
|
||||
const token = await getToken();
|
||||
const body = await api({
|
||||
method: 'delete',
|
||||
url: 'api/envs',
|
||||
params: { t: Date.now() },
|
||||
body: JSON.stringify([eid]),
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json;charset=UTF-8',
|
||||
},
|
||||
}).json();
|
||||
return body;
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+5130
File diff suppressed because one or more lines are too long
+169
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
此文件为Node.js专用。其他用户请忽略
|
||||
*/
|
||||
//此处填写京东账号cookie。
|
||||
let CookieJDs = [
|
||||
'',//账号一ck,例:pt_key=XXX;pt_pin=XXX;
|
||||
'',//账号二ck,例:pt_key=XXX;pt_pin=XXX;如有更多,依次类推
|
||||
]
|
||||
let IP='';
|
||||
// 判断环境变量里面是否有京东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);
|
||||
})()
|
||||
}
|
||||
//!(async () => {
|
||||
// IP = await getIP();
|
||||
// try {
|
||||
// IP = IP.match(/((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}/)[0];
|
||||
// console.log(`\n当前公网IP: ${IP}`);
|
||||
// } catch (e) { }
|
||||
//})()
|
||||
CookieJDs = [...new Set(CookieJDs.filter(item => !!item))]
|
||||
if (process.env.JD_DEBUG && process.env.JD_DEBUG === 'false') console.log = () => {};
|
||||
console.log(`\n====================共${CookieJDs.length}个京东账号Cookie=================\n`);
|
||||
console.log(`============脚本执行时间:${new Date(new Date().getTime() + new Date().getTimezoneOffset()*60*1000 + 8*60*60*1000).toLocaleString('chinese',{hour12:false})}=============\n`)
|
||||
console.log('>>>>>>>>>>>>>>6Dylan6 提示:任务正常运行中>>>>>>>>>>>>>>>\n')
|
||||
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`);
|
||||
CookieJDs[i] = CookieJDs[i].replace(/[\u4e00-\u9fa5]/g, (str) => encodeURI(str));
|
||||
const index = (i + 1 === 1) ? '' : (i + 1);
|
||||
exports['CookieJD' + index] = CookieJDs[i].trim();
|
||||
}
|
||||
|
||||
|
||||
function getIP() {
|
||||
const https = require('https');
|
||||
return new Promise((resolve, reject) => {
|
||||
let opt = {
|
||||
hostname: "www.cip.cc",
|
||||
port: 443,
|
||||
path: "/",
|
||||
method: "GET",
|
||||
headers: {
|
||||
"User-Agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36',
|
||||
},
|
||||
timeout: 5000
|
||||
}
|
||||
const req = https.request(opt, (res) => {
|
||||
res.setEncoding('utf-8');
|
||||
let tmp = '';
|
||||
res.on('error', reject);
|
||||
res.on('data', d => tmp += d);
|
||||
res.on('end',() => resolve(tmp));
|
||||
});
|
||||
|
||||
req.on('error', reject);
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
// 以下为注入互助码环境变量(仅nodejs内起效)的代码
|
||||
function SetShareCodesEnv(nameChinese = "", nameConfig = "", envName = "") {
|
||||
let rawCodeConfig = {}
|
||||
let fs = require('fs')
|
||||
// 读取互助码
|
||||
let shareCodeLogPath = fs.existsSync(`${process.env.QL_DIR}/data`) ? `${process.env.QL_DIR}/data/log/.ShareCode/${nameConfig}.log` : `${process.env.QL_DIR}/log/.ShareCode/${nameConfig}.log`;
|
||||
if (fs.existsSync(shareCodeLogPath)) {
|
||||
// 因为faker2目前没有自带ini,改用已有的dotenv来解析
|
||||
// // 利用ini模块读取原始互助码和互助组信息
|
||||
// let ini = require('ini')
|
||||
// rawCodeConfig = ini.parse(fs.readFileSync(shareCodeLogPath, 'utf-8'))
|
||||
|
||||
// 使用env模块
|
||||
require('dotenv').config({path: shareCodeLogPath})
|
||||
rawCodeConfig = process.env
|
||||
}
|
||||
|
||||
// 解析每个用户的互助码
|
||||
let codes = {}
|
||||
Object.keys(rawCodeConfig).forEach(function (key) {
|
||||
if (key.startsWith(`My${nameConfig}`)) {
|
||||
codes[key] = rawCodeConfig[key]
|
||||
}
|
||||
});
|
||||
|
||||
// 解析每个用户要帮助的互助码组,将用户实际的互助码填充进去
|
||||
let helpOtherCodes = {}
|
||||
Object.keys(rawCodeConfig).forEach(function (key) {
|
||||
if (key.startsWith(`ForOther${nameConfig}`)) {
|
||||
let helpCode = rawCodeConfig[key]
|
||||
for (const [codeEnv, codeVal] of Object.entries(codes)) {
|
||||
helpCode = helpCode.replace("${" + codeEnv + "}", codeVal)
|
||||
}
|
||||
|
||||
helpOtherCodes[key] = helpCode
|
||||
}
|
||||
});
|
||||
|
||||
// 按顺序用&拼凑到一起,并放入环境变量,供目标脚本使用
|
||||
let shareCodes = []
|
||||
let leftIndex = 1, rightIndex = Object.keys(helpOtherCodes).length
|
||||
|
||||
// 判断是否是ptask并行触发,若是,则修改实际需要设置的互助码范围
|
||||
let ptaskLeft = process.env.PTASK_LEFT
|
||||
let ptaskRight = process.env.PTASK_RIGHT
|
||||
if (ptaskLeft && ptaskRight) {
|
||||
leftIndex = Number(ptaskLeft)
|
||||
rightIndex = Number(ptaskRight)
|
||||
}
|
||||
|
||||
for (let idx = leftIndex; idx <= rightIndex; idx++) {
|
||||
shareCodes.push(helpOtherCodes[`ForOther${nameConfig}${idx}`])
|
||||
}
|
||||
let shareCodesStr = shareCodes.join('&')
|
||||
process.env[envName] = shareCodesStr
|
||||
|
||||
let totalCodeCount = rightIndex - leftIndex + 1
|
||||
//console.info(`${nameChinese}的 互助码环境变量 ${envName},共计 ${totalCodeCount} 组互助码,总大小为 ${shareCodesStr.length} 字节`)
|
||||
}
|
||||
|
||||
// 判断当前活动脚本是否在互助脚本列表中
|
||||
function IsShareJsFile() {
|
||||
// 尝试获取在task_before.sh中设置的 互助活动的脚本文件名的关键部分 列表
|
||||
let rawJsNameList = process.env.ShareCodeJSNameList
|
||||
if (!rawJsNameList) {
|
||||
return false
|
||||
}
|
||||
|
||||
// 转换为list
|
||||
let jsNameList = process.env.ShareCodeJSNameList.split(" ")
|
||||
|
||||
// 判断当前
|
||||
let currentActivityScriptFileName = GetCurrentActivityScriptFileName()
|
||||
|
||||
let isShareJsFile = false
|
||||
for (let idx = 0; idx < jsNameList.length; idx++) {
|
||||
if (currentActivityScriptFileName.includes(jsNameList[idx])) {
|
||||
isShareJsFile = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return isShareJsFile
|
||||
}
|
||||
|
||||
// 获取当前活动脚本的文件名
|
||||
function GetCurrentActivityScriptFileName() {
|
||||
const path = require('path')
|
||||
return path.basename(process.argv[1])
|
||||
}
|
||||
|
||||
// 若在task_before.sh 中设置了要设置互助码环境变量的活动名称和环境变量名称信息,则在nodejs中处理,供活动使用
|
||||
let nameChinese = process.env.ShareCodeConfigChineseName
|
||||
let nameConfig = process.env.ShareCodeConfigName
|
||||
let envName = process.env.ShareCodeEnvName
|
||||
if (nameChinese && nameConfig && envName) {
|
||||
SetShareCodesEnv(nameChinese, nameConfig, envName)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
京喜工厂互助码
|
||||
此文件为Node.js专用。其他用户请忽略
|
||||
支持京东N个账号
|
||||
*/
|
||||
//云服务器腾讯云函数等NOde.js用户在此处填写东东萌宠的好友码。
|
||||
// 同一个京东账号的好友互助码用@符号隔开,不同京东账号之间用&符号或者换行隔开,下面给一个示例
|
||||
// 如: 京东账号1的shareCode1@京东账号1的shareCode2&京东账号2的shareCode1@京东账号2的shareCode2
|
||||
let shareCodes = [
|
||||
]
|
||||
|
||||
// 从日志获取互助码
|
||||
// const logShareCodes = require('./utils/jdShareCodes');
|
||||
// if (logShareCodes.DREAM_FACTORY_SHARE_CODES.length > 0 && !process.env.DREAM_FACTORY_SHARE_CODES) {
|
||||
// process.env.DREAM_FACTORY_SHARE_CODES = logShareCodes.DREAM_FACTORY_SHARE_CODES.join('&');
|
||||
// }
|
||||
|
||||
// 判断环境变量里面是否有京喜工厂互助码
|
||||
if (process.env.DREAM_FACTORY_SHARE_CODES) {
|
||||
if (process.env.DREAM_FACTORY_SHARE_CODES.indexOf('&') > -1) {
|
||||
console.log(`您的互助码选择的是用&隔开\n`)
|
||||
shareCodes = process.env.DREAM_FACTORY_SHARE_CODES.split('&');
|
||||
} else if (process.env.DREAM_FACTORY_SHARE_CODES.indexOf('\n') > -1) {
|
||||
console.log(`您的互助码选择的是用换行隔开\n`)
|
||||
shareCodes = process.env.DREAM_FACTORY_SHARE_CODES.split('\n');
|
||||
} else {
|
||||
shareCodes = process.env.DREAM_FACTORY_SHARE_CODES.split();
|
||||
}
|
||||
} else {
|
||||
console.log(`由于您环境变量(DREAM_FACTORY_SHARE_CODES)里面未提供助力码,故此处运行将会给脚本内置的码进行助力,请知晓!`)
|
||||
}
|
||||
for (let i = 0; i < shareCodes.length; i++) {
|
||||
const index = (i + 1 === 1) ? '' : (i + 1);
|
||||
exports['shareCodes' + index] = shareCodes[i];
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
京喜农场助力码
|
||||
此助力码要求种子 active 相同才能助力,多个账号的话可以种植同样的种子,如果种子不同的话,会自动跳过使用云端助力
|
||||
此文件为Node.js专用。其他用户请忽略
|
||||
支持京东N个账号
|
||||
*/
|
||||
//云服务器腾讯云函数等NOde.js用户在此处填写京京喜农场的好友码。
|
||||
// 同一个京东账号的好友助力码用@符号隔开,不同京东账号之间用&符号或者换行隔开,下面给一个示例
|
||||
// 如: 京东账号1的shareCode1@京东账号1的shareCode2&京东账号2的shareCode1@京东账号2的shareCode2
|
||||
// 注意:京喜农场 种植种子发生变化的时候,互助码也会变!!
|
||||
// 注意:京喜农场 种植种子发生变化的时候,互助码也会变!!
|
||||
// 注意:京喜农场 种植种子发生变化的时候,互助码也会变!!
|
||||
// 每个账号 shareCdoe 是一个 json,示例如下
|
||||
// {"smp":"22bdadsfaadsfadse8a","active":"jdnc_1_btorange210113_2","joinnum":"1"}
|
||||
let JxncShareCodes = [
|
||||
'',//账号一的好友shareCode,不同好友中间用@符号隔开
|
||||
'',//账号二的好友shareCode,不同好友中间用@符号隔开
|
||||
]
|
||||
// 判断github action里面是否有京喜农场助力码
|
||||
if (process.env.JXNC_SHARECODES) {
|
||||
if (process.env.JXNC_SHARECODES.indexOf('&') > -1) {
|
||||
console.log(`您的京喜农场助力码选择的是用&隔开\n`)
|
||||
JxncShareCodes = process.env.JXNC_SHARECODES.split('&');
|
||||
} else if (process.env.JXNC_SHARECODES.indexOf('\n') > -1) {
|
||||
console.log(`您的京喜农场助力码选择的是用换行隔开\n`)
|
||||
JxncShareCodes = process.env.JXNC_SHARECODES.split('\n');
|
||||
} else {
|
||||
JxncShareCodes = process.env.JXNC_SHARECODES.split();
|
||||
}
|
||||
} else {
|
||||
console.log(`由于您环境变量里面(JXNC_SHARECODES)未提供助力码,故此处运行将会给脚本内置的码进行助力,请知晓!`)
|
||||
}
|
||||
JxncShareCodes = JxncShareCodes.filter(item => !!item);
|
||||
for (let i = 0; i < JxncShareCodes.length; i++) {
|
||||
const index = (i + 1 === 1) ? '' : (i + 1);
|
||||
exports['JxncShareCode' + index] = JxncShareCodes[i];
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
东东萌宠互助码
|
||||
此文件为Node.js专用。其他用户请忽略
|
||||
支持京东N个账号
|
||||
*/
|
||||
//云服务器腾讯云函数等NOde.js用户在此处填写东东萌宠的好友码。
|
||||
// 同一个京东账号的好友互助码用@符号隔开,不同京东账号之间用&符号或者换行隔开,下面给一个示例
|
||||
// 如: 京东账号1的shareCode1@京东账号1的shareCode2&京东账号2的shareCode1@京东账号2的shareCode2
|
||||
let PetShareCodes = [
|
||||
'',//账号二的好友shareCode,不同好友中间用@符号隔开
|
||||
]
|
||||
|
||||
// 从日志获取互助码
|
||||
// const logShareCodes = require('./utils/jdShareCodes');
|
||||
// if (logShareCodes.PETSHARECODES.length > 0 && !process.env.PETSHARECODES) {
|
||||
// process.env.PETSHARECODES = logShareCodes.PETSHARECODES.join('&');
|
||||
// }
|
||||
|
||||
// 判断github action里面是否有东东萌宠互助码
|
||||
if (process.env.PETSHARECODES) {
|
||||
if (process.env.PETSHARECODES.indexOf('&') > -1) {
|
||||
console.log(`您的东东萌宠互助码选择的是用&隔开\n`)
|
||||
PetShareCodes = process.env.PETSHARECODES.split('&');
|
||||
} else if (process.env.PETSHARECODES.indexOf('\n') > -1) {
|
||||
console.log(`您的东东萌宠互助码选择的是用换行隔开\n`)
|
||||
PetShareCodes = process.env.PETSHARECODES.split('\n');
|
||||
} else {
|
||||
PetShareCodes = process.env.PETSHARECODES.split();
|
||||
}
|
||||
} else {
|
||||
console.log(`由于您环境变量(PETSHARECODES)里面未提供助力码,故此处运行将会给脚本内置的码进行助力,请知晓!`)
|
||||
}
|
||||
for (let i = 0; i < PetShareCodes.length; i++) {
|
||||
const index = (i + 1 === 1) ? '' : (i + 1);
|
||||
exports['PetShareCode' + index] = PetShareCodes[i];
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
京东种豆得豆互助码
|
||||
此文件为Node.js专用。其他用户请忽略
|
||||
支持京东N个账号
|
||||
*/
|
||||
//云服务器腾讯云函数等NOde.js用户在此处填写东东萌宠的好友码。
|
||||
// 同一个京东账号的好友互助码用@符号隔开,不同京东账号之间用&符号或者换行隔开,下面给一个示例
|
||||
// 如: 京东账号1的shareCode1@京东账号1的shareCode2&京东账号2的shareCode1@京东账号2的shareCode2
|
||||
let PlantBeanShareCodes = [
|
||||
//账号二的好友shareCode,不同好友中间用@符号隔开
|
||||
]
|
||||
|
||||
// 从日志获取互助码
|
||||
// const logShareCodes = require('./utils/jdShareCodes');
|
||||
// if (logShareCodes.PLANT_BEAN_SHARECODES.length > 0 && !process.env.PLANT_BEAN_SHARECODES) {
|
||||
// process.env.PLANT_BEAN_SHARECODES = logShareCodes.PLANT_BEAN_SHARECODES.join('&');
|
||||
// }
|
||||
|
||||
// 判断github action里面是否有种豆得豆互助码
|
||||
if (process.env.PLANT_BEAN_SHARECODES) {
|
||||
if (process.env.PLANT_BEAN_SHARECODES.indexOf('&') > -1) {
|
||||
console.log(`您的种豆互助码选择的是用&隔开\n`)
|
||||
PlantBeanShareCodes = process.env.PLANT_BEAN_SHARECODES.split('&');
|
||||
} else if (process.env.PLANT_BEAN_SHARECODES.indexOf('\n') > -1) {
|
||||
console.log(`您的种豆互助码选择的是用换行隔开\n`)
|
||||
PlantBeanShareCodes = process.env.PLANT_BEAN_SHARECODES.split('\n');
|
||||
} else {
|
||||
PlantBeanShareCodes = process.env.PLANT_BEAN_SHARECODES.split();
|
||||
}
|
||||
} else {
|
||||
console.log(`由于您环境变量(PLANT_BEAN_SHARECODES)里面未提供助力码,故此处运行将会给脚本内置的码进行助力,请知晓!`)
|
||||
}
|
||||
for (let i = 0; i < PlantBeanShareCodes.length; i++) {
|
||||
const index = (i + 1 === 1) ? '' : (i + 1);
|
||||
exports['PlantBeanShareCodes' + index] = PlantBeanShareCodes[i];
|
||||
}
|
||||
+298
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+33
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2603
File diff suppressed because it is too large
Load Diff
+769
File diff suppressed because one or more lines are too long
+290
File diff suppressed because one or more lines are too long
@@ -0,0 +1,263 @@
|
||||
# !/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# Modify : 2022/9/30
|
||||
# 京豆近7天输出表格统计
|
||||
# 用不着每天跑,定时自行设置吧,配合desi可指定账号
|
||||
# https://raw.githubusercontent.com/6dylan6/jdpro/main/jd_beans_7days.py
|
||||
'''
|
||||
new Env('豆子7天统计');
|
||||
8 8 30 9 * jd_beans_7days.py
|
||||
'''
|
||||
|
||||
import requests
|
||||
import datetime
|
||||
import os,re,sys,json,time
|
||||
from urllib.parse import unquote
|
||||
from datetime import timedelta
|
||||
from datetime import timezone
|
||||
|
||||
try:
|
||||
from prettytable import PrettyTable
|
||||
except:
|
||||
os.system('pip3 install prettytable &> /dev/null')
|
||||
from prettytable import PrettyTable
|
||||
|
||||
SHA_TZ = timezone(
|
||||
timedelta(hours=8),
|
||||
name='Asia/Shanghai',
|
||||
)
|
||||
requests.adapters.DEFAULT_RETRIES = 5
|
||||
session = requests.session()
|
||||
session.keep_alive = False
|
||||
|
||||
url = "https://api.m.jd.com/api"
|
||||
|
||||
def gen_body(page):
|
||||
body = {
|
||||
"beginDate": datetime.datetime.utcnow().replace(tzinfo=timezone.utc).astimezone(SHA_TZ).strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"endDate": datetime.datetime.utcnow().replace(tzinfo=timezone.utc).astimezone(SHA_TZ).strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"pageNo": page,
|
||||
"pageSize": 20,
|
||||
}
|
||||
return body
|
||||
|
||||
def printf(text):
|
||||
print(text)
|
||||
sys.stdout.flush()
|
||||
|
||||
def column_pad(*columns):
|
||||
max_len = max([len(x) for x in columns])
|
||||
for y in columns:
|
||||
y.extend(['NaN']*(max_len-len(y)))
|
||||
|
||||
class getJDCookie(object):
|
||||
|
||||
# 获取cookie
|
||||
def getCookie(self):
|
||||
global cookies
|
||||
cookies = []
|
||||
try:
|
||||
if "JD_COOKIE" in os.environ:
|
||||
if len(os.environ["JD_COOKIE"]) > 10:
|
||||
cookies = os.environ["JD_COOKIE"]
|
||||
printf("\n当前从环境变量获取CK\n")
|
||||
return
|
||||
except Exception as e:
|
||||
printf(f"【getCookie Error】{e}")
|
||||
|
||||
# 检测cookie格式是否正确
|
||||
|
||||
def getUserInfo(self, ck, pinName, userNum):
|
||||
url = 'https://me-api.jd.com/user_new/info/GetJDUserInfoUnion?orgFlag=JD_PinGou_New&callSource=mainorder&channel=4&isHomewhite=0&sceneval=2&sceneval=2&callback='
|
||||
headers = {
|
||||
'Cookie': ck,
|
||||
'Accept': '*/*',
|
||||
'Connection': 'close',
|
||||
'Referer': 'https://home.m.jd.com/myJd/home.action',
|
||||
'Accept-Encoding': 'gzip, deflate, br',
|
||||
'Host': 'me-api.jd.com',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Mobile/15E148 Safari/604.1',
|
||||
'Accept-Language': 'zh-cn'
|
||||
}
|
||||
try:
|
||||
if sys.platform == 'ios':
|
||||
resp = requests.get(url=url, verify=False, headers=headers, timeout=60).json()
|
||||
else:
|
||||
resp = requests.get(url=url, headers=headers, timeout=60).json()
|
||||
if resp['retcode'] == "0":
|
||||
nickname = resp['data']['userInfo']['baseInfo']['nickname']
|
||||
if not nickname:
|
||||
nickname = resp['data']['userInfo']['baseInfo']['curPin']
|
||||
return ck, nickname
|
||||
else:
|
||||
context = f"账号{userNum}【{pinName}】Cookie 已失效!请重新获取\n。"
|
||||
printf(context)
|
||||
return ck, False
|
||||
except Exception:
|
||||
context = f"账号{userNum}【{pinName}】Cookie 已失效!请重新获取\n。"
|
||||
printf(context)
|
||||
return ck, False
|
||||
|
||||
def iscookie(self):
|
||||
"""
|
||||
:return: cookiesList,userNameList,pinNameList
|
||||
"""
|
||||
cookiesList = []
|
||||
userNameList = []
|
||||
pinNameList = []
|
||||
if 'pt_key=' in cookies and 'pt_pin=' in cookies:
|
||||
r = re.compile(r"pt_key=.*?pt_pin=.*?;", re.M | re.S | re.I)
|
||||
result = r.findall(cookies)
|
||||
if len(result) >= 1:
|
||||
printf("您有{}个账号".format(len(result)))
|
||||
u = 1
|
||||
for i in result:
|
||||
r = re.compile(r"pt_pin=(.*?);")
|
||||
pinName = r.findall(i)
|
||||
pinName = unquote(pinName[0])
|
||||
# 获取账号名
|
||||
ck, nickname = self.getUserInfo(i, pinName, u)
|
||||
if nickname:
|
||||
cookiesList.append(ck)
|
||||
userNameList.append(nickname)
|
||||
pinNameList.append(pinName)
|
||||
else:
|
||||
u += 1
|
||||
continue
|
||||
u += 1
|
||||
if len(cookiesList) > 0 and len(userNameList) > 0:
|
||||
return cookiesList, userNameList, pinNameList
|
||||
else:
|
||||
printf("没有可用CK,已退出\n")
|
||||
exit(3)
|
||||
else:
|
||||
printf("CK格式错误!...本次运行退出\n")
|
||||
exit(4)
|
||||
else:
|
||||
printf("CK格式错误或无CK!...请检查\n")
|
||||
exit(4)
|
||||
|
||||
|
||||
getCk = getJDCookie()
|
||||
getCk.getCookie()
|
||||
|
||||
|
||||
def gen_params(page):
|
||||
body = gen_body(page)
|
||||
params = {
|
||||
"functionId": "jposTradeQuery",
|
||||
"appid": "swat_miniprogram",
|
||||
"client": "tjj_m",
|
||||
"sdkName": "orderDetail",
|
||||
"sdkVersion": "1.0.0",
|
||||
"clientVersion": "3.1.3",
|
||||
"timestamp": int(round(time.time() * 1000)),
|
||||
"body": json.dumps(body)
|
||||
}
|
||||
return params
|
||||
|
||||
def creat_bean_count(date, beansin, beansout, beanstotal):
|
||||
tb = PrettyTable()
|
||||
tb.add_column('DATE', date)
|
||||
tb.add_column('BEANSIN', beansin)
|
||||
tb.add_column('BEANSOUT', beansout)
|
||||
tb.add_column('TOTAL', beanstotal)
|
||||
printf(tb)
|
||||
|
||||
|
||||
def get_beans_7days(ck):
|
||||
try:
|
||||
day_7 = True
|
||||
page = 0
|
||||
headers = {
|
||||
"Host": "api.m.jd.com",
|
||||
"User-Agent": "Mozilla/5.0 (Linux; Android 10; MI 9 Build/QKQ1.190825.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.62 XWEB/2797 MMWEBSDK/201201 Mobile Safari/537.36 MMWEBID/7986 MicroMessenger/8.0.1840(0x2800003B) Process/appbrand4 WeChat/arm64 Weixin NetType/4G Language/zh_CN ABI/arm64 MiniProgramEnv/android",
|
||||
"Content-Type": "application/x-www-form-urlencoded;",
|
||||
"Cookie": ck,
|
||||
}
|
||||
days = []
|
||||
for i in range(0, 7):
|
||||
days.append((datetime.date.today() - datetime.timedelta(days=i)).strftime("%Y-%m-%d"))
|
||||
beans_in = {key: 0 for key in days}
|
||||
beans_out = {key: 0 for key in days}
|
||||
while day_7:
|
||||
page = page + 1
|
||||
url="https://api.m.jd.com/client.action?functionId=getJingBeanBalanceDetail&body=%7B%22pageSize%22%3A%2220%22%2C%22page%22%3A%22"+str(page)+"%22%7D&appid=ld"
|
||||
resp = session.get(url, headers=headers, timeout=1000).text
|
||||
res = json.loads(resp)
|
||||
if res['code'] == '0' :
|
||||
for i in res['detailList']:
|
||||
for date in days:
|
||||
if str(date) in i['date'] and int(i['amount']) > 0:
|
||||
beans_in[str(date)] = beans_in[str(date)] + int(i['amount'])
|
||||
break
|
||||
elif str(date) in i['date'] and int(i['amount']) < 0:
|
||||
beans_out[str(date)] = beans_out[str(date)] + int(i['amount'])
|
||||
break
|
||||
if i['date'].split(' ')[0] not in str(days):
|
||||
day_7 = False
|
||||
else:
|
||||
print("未获取到数据,原因未知!!\n")
|
||||
return {'code': 400, 'data': res}
|
||||
return {'code': 200, 'data': [beans_in, beans_out, days]}
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
return {'code': 400, 'data': str(e)}
|
||||
|
||||
|
||||
def get_total_beans(ck):
|
||||
try:
|
||||
headers = {
|
||||
"Host": "wq.jd.com",
|
||||
"User-Agent": "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",
|
||||
"Content-Type": "application/x-www-form-urlencoded;",
|
||||
"Cookie": ck,
|
||||
"Referer": 'https://wqs.jd.com/my/jingdou/my.shtml?sceneval=2'
|
||||
}
|
||||
jurl = "https://wq.jd.com/user/info/QueryJDUserInfo?sceneval=2"
|
||||
resp = requests.post(jurl, headers=headers).text
|
||||
res = json.loads(resp)
|
||||
return res['base']['jdNum']
|
||||
except Exception as e:
|
||||
printf(str(e))
|
||||
|
||||
|
||||
def get_bean_data(i,ck):
|
||||
try:
|
||||
if ck:
|
||||
#ck = cookies[i-1]
|
||||
beans_res = get_beans_7days(ck)
|
||||
beantotal = get_total_beans(ck)
|
||||
if beans_res['code'] != 200:
|
||||
return beans_res
|
||||
else:
|
||||
beans_in, beans_out = [], []
|
||||
beanstotal = [int(beantotal), ]
|
||||
for i in beans_res['data'][0]:
|
||||
beantotal = int(beantotal) - int(beans_res['data'][0][i]) - int(beans_res['data'][1][i])
|
||||
beans_in.append(int(beans_res['data'][0][i]))
|
||||
beans_out.append(int(str(beans_res['data'][1][i]).replace('-', '')))
|
||||
beanstotal.append(beantotal)
|
||||
return {'code': 200, 'data': [beans_in[::-1], beans_out[::-1], beanstotal[::-1], beans_res['data'][2][::-1]]}
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
|
||||
def query():
|
||||
try:
|
||||
global cookiesList, userNameList, pinNameList, ckNum, beanCount, userCount
|
||||
cookiesList, userNameList, pinNameList = getCk.iscookie()
|
||||
for i,ck,user,pin in zip(range(1,len(cookiesList)+1),cookiesList,userNameList,pinNameList):
|
||||
printf(f"\n****** [账号{i}]-{user} ******")
|
||||
res=get_bean_data(i,ck)
|
||||
if res['code'] != 200:
|
||||
printf(res['data'])
|
||||
continue
|
||||
if res['data'][2][1:] != []:
|
||||
creat_bean_count(res['data'][3], res['data'][0], res['data'][1], res['data'][2][1:])
|
||||
time.sleep(2)
|
||||
except Exception as e:
|
||||
printf(str(e))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
query()
|
||||
+782
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+399
@@ -0,0 +1,399 @@
|
||||
/*
|
||||
京东超级盒子
|
||||
更新时间:2022-1-9
|
||||
活动入口:京东APP-搜索-超级盒子
|
||||
脚本兼容: QuantumultX, Surge, Loon, JSBox, Node.js
|
||||
============Quantumultx===============
|
||||
[task_local]
|
||||
#京东超级盒子
|
||||
24 3,13 * * * https://raw.githubusercontent.com/msechen/script/main/jd_cjhz.js, tag=京东超级盒子, img-url=https://github.com/58xinian/icon/raw/master/jdgc.png, enabled=true
|
||||
================Loon==============
|
||||
[Script]
|
||||
cron "24 3,13 * * *" script-path=https://raw.githubusercontent.com/msechen/script/main/jd_cjhz.js,tag=京东超级盒子
|
||||
===============Surge=================
|
||||
京东超级盒子 = type=cron,cronexp="24 3,13 * * *",wake-system=1,timeout=3600,script-path=https://raw.githubusercontent.com/msechen/script/main/jd_cjhz.js
|
||||
============小火箭=========
|
||||
京东超级盒子 = type=cron,script-path=https://raw.githubusercontent.com/msechen/script/main/jd_cjhz.js, cronexpr="24 3,13 * * *", timeout=3600, enable=true
|
||||
*/
|
||||
|
||||
const $ = new Env('京东超级盒子');
|
||||
//Node.js用户请在jdCookie.js处填写京东ck;
|
||||
const jdCookieNode = $.isNode() ? require('./jdCookie.js') : '';
|
||||
//IOS等用户直接用NobyDa的jd cookie
|
||||
let cookiesArr = [],
|
||||
cookie = '',
|
||||
secretp = '',
|
||||
joyToken = "";
|
||||
$.shareCoseList = [];
|
||||
if ($.isNode()) {
|
||||
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 JD_API_HOST = `https://api.m.jd.com/client.action`;
|
||||
!(async () => {
|
||||
console.log('活动入口:京东APP-搜索-超级盒子')
|
||||
console.log('开箱目前结果为空气和红包,没发现豆子')
|
||||
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;
|
||||
}
|
||||
await getToken();
|
||||
cookiesArr = cookiesArr.map(ck => ck + `joyytoken=50084${joyToken};`)
|
||||
$.CryptoJS = $.isNode() ? require('crypto-js') : CryptoJS
|
||||
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;
|
||||
$.isLogin = true;
|
||||
$.nickName = '';
|
||||
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" });
|
||||
continue
|
||||
}
|
||||
console.log(`\n******开始【京东账号${$.index}】${$.nickName || $.UserName}*********\n`);
|
||||
console.log(`\n入口:app主页搜超级盒子\n`);
|
||||
await main()
|
||||
}
|
||||
};
|
||||
$.shareCoseList = [...new Set([...$.shareCoseList])]
|
||||
//去助力与开箱
|
||||
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;
|
||||
$.isLogin = true;
|
||||
$.nickName = '';
|
||||
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" });
|
||||
continue
|
||||
}
|
||||
if ($.shareCoseList.length >= 2) {
|
||||
for (let y = 0; y < $.shareCoseList.length; y++) {
|
||||
console.log(`京东账号${$.index} ${$.nickName || $.UserName}去助力${$.shareCoseList[y]}`)
|
||||
await helpShare({ "taskId": $.helpId, "linkId": "Ll3Qb2mhCXSEWxruhv8qIw", "encryptPin": $.shareCoseList[y] });
|
||||
await $.wait(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
$.isLogin = true;
|
||||
$.nickName = '';
|
||||
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" });
|
||||
continue
|
||||
}
|
||||
//开箱
|
||||
console.log(`京东账号${$.index}去开箱`)
|
||||
for (let y = 0; y < $.lotteryNumber; y++) {
|
||||
console.log(`可以开箱${$.lotteryNumber}次 ==>>第${y+1}次开箱`)
|
||||
await openBox({ "linkId": "Ll3Qb2mhCXSEWxruhv8qIw", "encryptPin": "" });
|
||||
await $.wait(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
})()
|
||||
.catch((e) => $.logErr(e))
|
||||
.finally(() => $.done())
|
||||
|
||||
async function main() {
|
||||
await superboxSupBoxHomePage({ "taskId": "", "linkId": "Ll3Qb2mhCXSEWxruhv8qIw", "encryptPin": "" })
|
||||
console.log(`【京东账号${$.index}】${$.nickName || $.UserName}互助码:${$.encryptPin}`)
|
||||
await $.wait(1000);
|
||||
await apTaskList({ "linkId": "Ll3Qb2mhCXSEWxruhv8qIw", "encryptPin": $.encryptPin });
|
||||
if ($.allList) {
|
||||
for (let i = 0; i < $.allList.length; i++) {
|
||||
$.oneTask = $.allList[i];
|
||||
if (["SHARE_INVITE"].includes($.oneTask.taskType)) {
|
||||
$.helpId = $.oneTask.id;
|
||||
$.helpLimit = $.oneTask.taskLimitTimes;
|
||||
};
|
||||
if (["BROWSE_SHOP"].includes($.oneTask.taskType) && $.oneTask.taskFinished === false) {
|
||||
await apTaskDetail({ "taskId": $.oneTask.id, "taskType": $.oneTask.taskType, "channel": 4, "linkId": "Ll3Qb2mhCXSEWxruhv8qIw", "encryptPin": "7pcfSWHrAG9MKu3RKLl127VL5L4aIE1sZ1eRRdphpl8" });
|
||||
await $.wait(1000)
|
||||
for (let y = 0; y < ($.doList.status.finishNeed - $.doList.status.userFinishedTimes); y++) {
|
||||
$.startList = $.doList.taskItemList[y];
|
||||
$.itemName = $.doList.taskItemList[y].itemName;
|
||||
console.log(`去浏览${$.itemName}`)
|
||||
await apDoTask({ "taskId": $.allList[i].id, "taskType": $.allList[i].taskType, "channel": 4, "itemId": $.startList.itemId, "linkId": "Ll3Qb2mhCXSEWxruhv8qIw", "encryptPin": "7pcfSWHrAG9MKu3RKLl127VL5L4aIE1sZ1eRRdphpl8" })
|
||||
await $.wait(1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log(`任务全部完成`)
|
||||
}
|
||||
}
|
||||
|
||||
//活动主页
|
||||
function superboxSupBoxHomePage(body) {
|
||||
return new Promise((resolve) => {
|
||||
$.get(taskGetUrl('superboxSupBoxHomePage', body), (err, resp, data) => {
|
||||
try {
|
||||
if (err) {
|
||||
console.log(`${JSON.stringify(err)}`)
|
||||
console.log(`${$.name} superboxSupBoxHomePage API请求失败,请检查网路重试`)
|
||||
} else {
|
||||
data = JSON.parse(data);
|
||||
if (data.code === 0) {
|
||||
$.encryptPin = data.data.encryptPin;
|
||||
$.shareCoseList.push($.encryptPin)
|
||||
$.lotteryNumber = data.data.lotteryNumber
|
||||
} else {
|
||||
console.log(`superboxSupBoxHomePage:${JSON.stringify(data)}\n`);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
$.logErr(e, resp);
|
||||
} finally {
|
||||
resolve();
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//获取任务列表
|
||||
function apTaskList(body) {
|
||||
return new Promise((resolve) => {
|
||||
$.get(taskGetUrl('apTaskList', body), (err, resp, data) => {
|
||||
try {
|
||||
if (err) {
|
||||
console.log(`${JSON.stringify(err)}`)
|
||||
console.log(`${$.name} apTaskList API请求失败,请检查网路重试`)
|
||||
} else {
|
||||
data = JSON.parse(data);
|
||||
if (data.code === 0) {
|
||||
$.allList = data.data
|
||||
//console.log(JSON.stringify($.allList[1]));
|
||||
} else {
|
||||
console.log(`apTaskList错误:${JSON.stringify(data)}\n`);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
$.logErr(e, resp);
|
||||
} finally {
|
||||
resolve();
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
//获取任务分表
|
||||
function apTaskDetail(body) {
|
||||
return new Promise((resolve) => {
|
||||
$.get(taskGetUrl('apTaskDetail', body), (err, resp, data) => {
|
||||
try {
|
||||
if (err) {
|
||||
console.log(`${JSON.stringify(err)}`)
|
||||
console.log(`${$.name} apTaskDetail API请求失败,请检查网路重试`)
|
||||
} else {
|
||||
data = JSON.parse(data);
|
||||
if (data.code === 0) {
|
||||
$.doList = data.data
|
||||
//console.log(JSON.stringify($.doList));
|
||||
} else {
|
||||
console.log(`apTaskDetail错误:${JSON.stringify(data)}\n`);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
$.logErr(e, resp);
|
||||
} finally {
|
||||
resolve();
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
//做任务
|
||||
function apDoTask(body) {
|
||||
return new Promise((resolve) => {
|
||||
$.post(taskPostUrl('apDoTask', body), (err, resp, data) => {
|
||||
try {
|
||||
if (err) {
|
||||
console.log(`${JSON.stringify(err)}`)
|
||||
console.log(`${$.name} apDoTask API请求失败,请检查网路重试`)
|
||||
} else {
|
||||
data = JSON.parse(data);
|
||||
//console.log(JSON.stringify(data));
|
||||
if (data.success === true && data.code === 0) {
|
||||
console.log(`浏览${$.itemName}完成\n已完成${data.data.userFinishedTimes}次\n`)
|
||||
} else if (data.success === false && data.code === 2005) {
|
||||
console.log(`${data.data.errMsg}${data.data.userFinishedTimes}次`)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
$.logErr(e, resp);
|
||||
} finally {
|
||||
resolve();
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
//助力
|
||||
function helpShare(body) {
|
||||
return new Promise((resolve) => {
|
||||
$.get(taskGetUrl('superboxSupBoxHomePage', body), (err, resp, data) => {
|
||||
try {
|
||||
if (err) {
|
||||
console.log(`${JSON.stringify(err)}`)
|
||||
console.log(`${$.name} superboxSupBoxHomePage API请求失败,请检查网路重试`)
|
||||
} else {
|
||||
data = JSON.parse(data);
|
||||
//console.log(JSON.stringify(data));
|
||||
if (data.success === true && data.code === 0) {
|
||||
console.log(`助力成功\n\n`)
|
||||
} else {
|
||||
console.log(`助力失败:${JSON.stringify(data)}\n\n`)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
$.logErr(e, resp);
|
||||
} finally {
|
||||
resolve();
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
//开盲盒
|
||||
function openBox(body) {
|
||||
return new Promise((resolve) => {
|
||||
$.get(taskGetUrl('superboxOrdinaryLottery', body), (err, resp, data) => {
|
||||
try {
|
||||
if (err) {
|
||||
console.log(`${JSON.stringify(err)}`)
|
||||
console.log(`${$.name} superboxOrdinaryLottery API请求失败,请检查网路重试`)
|
||||
} else {
|
||||
data = JSON.parse(data);
|
||||
//console.log(JSON.stringify(data));
|
||||
if (data.success === true && data.code === 0 && data.data.rewardType === 2) {
|
||||
console.log(`开箱成功获得${data.data.discount}元红包\n\n`)
|
||||
} else if (data.success === true && data.code === 0 && data.data.rewardType !== 2) {
|
||||
console.log(`开箱成功应该获得了空气${JSON.stringify(data.data)}\n\n`)
|
||||
} else {
|
||||
console.log(`失败:${JSON.stringify(data)}\n\n`)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
$.logErr(e, resp);
|
||||
} finally {
|
||||
resolve();
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function getToken(timeout = 0) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
let url = {
|
||||
url: `https://bh.m.jd.com/gettoken`,
|
||||
headers: {
|
||||
'Content-Type': `text/plain;charset=UTF-8`
|
||||
},
|
||||
body: `content={"appname":"50084","whwswswws":"","jdkey":"","body":{"platform":"1"}}`
|
||||
}
|
||||
$.post(url, async (err, resp, data) => {
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
joyToken = data.joyytoken;
|
||||
console.log(`joyToken = ${data.joyytoken}`)
|
||||
} catch (e) {
|
||||
$.logErr(e, resp);
|
||||
} finally {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
}, timeout)
|
||||
})
|
||||
}
|
||||
|
||||
function taskGetUrl(functionId, body = {}) {
|
||||
return {
|
||||
url: `${JD_API_HOST}?functionId=${functionId}&body=${JSON.stringify(body)}&_t=${Date.now()}&appid=activities_platform&client=wh5&clientVersion=1.0.0`,
|
||||
//body: `functionId=${functionId}&body=${JSON.stringify(body)}&client=wh5&clientVersion=1.0.0&uuid=ef746bc0663f7ca06cdd1fa724c15451900039cf`,
|
||||
headers: {
|
||||
'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"),
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Host': 'api.m.jd.com',
|
||||
'Cookie': cookie,
|
||||
'Origin': 'https://prodev.m.jd.com',
|
||||
'Referer': 'https://pro.m.jd.com/mall/active/j8U2SMhmw3aKgfWwYQfoRR4idTT/index.html?',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function taskPostUrl(functionId, body = {}) {
|
||||
return {
|
||||
url: `${JD_API_HOST}?functionId=${functionId}`,
|
||||
body: `functionId=${functionId}&body=${JSON.stringify(body)}&_t=${Date.now()}&appid=activities_platform&client=wh5&clientVersion=1.0.0`,
|
||||
headers: {
|
||||
'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"),
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Host': 'api.m.jd.com',
|
||||
'Cookie': cookie,
|
||||
'Origin': 'https://prodev.m.jd.com',
|
||||
'Referer': 'https://pro.m.jd.com/mall/active/j8U2SMhmw3aKgfWwYQfoRR4idTT/index.html?',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function jsonParse(str) {
|
||||
if (typeof str == "string") {
|
||||
try {
|
||||
return JSON.parse(str);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
$.msg($.name, '', '请勿随意在BoxJs输入框修改内容\n建议通过脚本去获取cookie')
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
// prettier-ignore
|
||||
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) }
|
||||
+302
File diff suppressed because one or more lines are too long
+1288
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+207
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+261
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+20
File diff suppressed because one or more lines are too long
@@ -0,0 +1,82 @@
|
||||
//20 8 10 4 * jd_farm_automation.js
|
||||
|
||||
console.log('默认种2级,如需调整请设置变量 M_JD_FARM_LEVEL\n使用率不高,指定(desi)账号运行\n')
|
||||
const {Env} = require('./function/magic');
|
||||
const $ = new Env('农场自动种植兑换');
|
||||
let level = process.env.M_JD_FARM_LEVEL ? process.env.M_JD_FARM_LEVEL * 1 : 2
|
||||
$.logic = async function () {
|
||||
let info = await api('initForFarm',
|
||||
{"version": 11, "channel": 3, "babelChannel": 0});
|
||||
if (info.code !== '0') {
|
||||
$.log('可能没开通农场或者黑透了!!!')
|
||||
return
|
||||
}
|
||||
if (info.farmUserPro.treeState === 1) {
|
||||
return
|
||||
}
|
||||
if (info.farmUserPro.treeState === 2) {
|
||||
await $.wait(1000, 3000)
|
||||
$.log(`${info.farmUserPro.name},种植时间:${$.formatDate(
|
||||
info.farmUserPro.createTime)}`);
|
||||
//成熟了
|
||||
let coupon = await api('gotCouponForFarm',
|
||||
{"version": 11, "channel": 3, "babelChannel": 0});
|
||||
$.log(coupon)
|
||||
info = await api('initForFarm',
|
||||
{"version": 11, "channel": 3, "babelChannel": 0});
|
||||
}
|
||||
if (info.farmUserPro.treeState === 3) {
|
||||
let hongBao = info.myHongBaoInfo.hongBao;
|
||||
$.putMsg(`已兑换${hongBao.discount}红包,${$.formatDate(hongBao.endTime)}过期`)
|
||||
}
|
||||
|
||||
let element = info.farmLevelWinGoods[level][0] || 0;
|
||||
await $.wait(1000, 3000)
|
||||
if (element) {
|
||||
info = await api('choiceGoodsForFarm', {
|
||||
"imageUrl": '',
|
||||
"nickName": '',
|
||||
"shareCode": '',
|
||||
"goodsType": element.type,
|
||||
"type": "0",
|
||||
"version": 11,
|
||||
"channel": 3,
|
||||
"babelChannel": 0
|
||||
});
|
||||
if (info.code * 1 === 0) {
|
||||
$.putMsg(`\n再次种植【${info.farmUserPro.name}】`)
|
||||
}
|
||||
let a = await api('gotStageAwardForFarm',
|
||||
{"type": "4", "version": 11, "channel": 3, "babelChannel": 0});
|
||||
let b = await api('waterGoodForFarm',
|
||||
{"type": "", "version": 11, "channel": 3, "babelChannel": 0});
|
||||
let c = await api('gotStageAwardForFarm',
|
||||
{"type": "1", "version": 11, "channel": 3, "babelChannel": 0});
|
||||
}else{
|
||||
$.log('种子已抢完,下次在来!!!\n')
|
||||
}
|
||||
};
|
||||
|
||||
$.run({wait: [2000, 3000]}).catch(reason => $.log(reason));
|
||||
|
||||
// noinspection DuplicatedCode
|
||||
async function api(fn, body) {
|
||||
let url = `https://api.m.jd.com/client.action?functionId=${fn}&body=${JSON.stringify(
|
||||
body)}&client=apple&clientVersion=10.0.4&osVersion=13.7&appid=wh5&loginType=2&loginWQBiz=interact`
|
||||
//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓请求头↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
|
||||
let headers = {
|
||||
"Cookie": $.cookie,
|
||||
"Connection": "keep-alive",
|
||||
"Accept": "*/*",
|
||||
"Host": "api.m.jd.com",
|
||||
'User-Agent': `Mozilla/5.0 (iPhone; CPU iPhone OS 14_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.4(0x1800042c) NetType/4G Language/zh_CN miniProgram`,
|
||||
"Accept-Encoding": "gzip, deflate, br",
|
||||
"Accept-Language": "zh-cn"
|
||||
}
|
||||
let {data} = await $.request(url, headers)
|
||||
await $.wait(1000, 3000)
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1277
File diff suppressed because one or more lines are too long
+1286
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
#15 3 * * 3 jd_fixpull_.sh
|
||||
#new Env('拉库失败修复');
|
||||
## Build 20230429
|
||||
echo -e '\n开始修复。。。\n'
|
||||
DIR="$( cd "$( dirname $0 )" >/dev/null 2>&1 && pwd )"
|
||||
#echo $DIR
|
||||
function fix(){
|
||||
if [[ -z "$(echo "$DIR"|grep 'main')" ]];then
|
||||
if [[ -d /ql/repo/6dylan6_jdpro ]];then
|
||||
rm -rf /ql/repo/6dylan6_jdpro
|
||||
#ql repo https://ghproxy.com/https://github.com/6dylan6/jdpro.git "jd_|jx_|jddj_" "backUp" "^jd[^_]|USER|JD|function|sendNotify"
|
||||
elif [[ -d /ql/data/repo/6dylan6_jdpro ]];then
|
||||
rm -rf /ql/data/repo/6dylan6_jdpro
|
||||
#ql repo https://ghproxy.com/https://github.com/6dylan6/jdpro.git "jd_|jx_|jddj_" "backUp" "^jd[^_]|USER|JD|function|sendNotify"
|
||||
else
|
||||
echo -e '修复失败!\n将下面目录结构截图提问'
|
||||
find /ql -maxdepth 2 -type d
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
if [[ -d /ql/repo/6dylan6_jdpro_main ]];then
|
||||
rm -rf /ql/repo/6dylan6_jdpro_main
|
||||
#ql repo https://ghproxy.com/https://github.com/6dylan6/jdpro.git "jd_|jx_|jddj_" "backUp" "^jd[^_]|USER|JD|function|sendNotify" "main"
|
||||
elif [[ -d /ql/data/repo/6dylan6_jdpro_main ]];then
|
||||
rm -rf /ql/data/repo/6dylan6_jdpro_main
|
||||
#ql repo https://ghproxy.com/https://github.com/6dylan6/jdpro.git "jd_|jx_|jddj_" "backUp" "^jd[^_]|USER|JD|function|sendNotify" "main"
|
||||
else
|
||||
echo -e '修复失败!将下面目录结构截图提问\n'
|
||||
find /ql -maxdepth 2 -type d
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
fix
|
||||
|
||||
[[ $(echo $?) -eq 0 ]] && echo -e '修复完成,再拉库试试!,如果还不行是网络问题了!!!'
|
||||
|
||||
+1546
File diff suppressed because one or more lines are too long
+148
File diff suppressed because one or more lines are too long
+10
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,98 @@
|
||||
"""
|
||||
1 9 11 11 * jd_hbCount.py
|
||||
const $ = new Env("历史红包统计");
|
||||
历史红包统计,不用定时跑,想看手动运行
|
||||
"""
|
||||
|
||||
import requests
|
||||
import sys
|
||||
import re
|
||||
import time
|
||||
import os
|
||||
|
||||
|
||||
def gettimestamp():
|
||||
return str(int(time.time() * 1000))
|
||||
|
||||
|
||||
def printf(text):
|
||||
print(text)
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def getinfo(ck):
|
||||
isNext = True
|
||||
page = 1
|
||||
sum = 0
|
||||
usedsum = 0
|
||||
jxsum = 0
|
||||
usedjx = 0
|
||||
litesum = 0
|
||||
usedlite = 0
|
||||
healthsum = 0
|
||||
usedhealth = 0
|
||||
jdsum = 0
|
||||
usedjd = 0
|
||||
tysum = 0
|
||||
usedty = 0
|
||||
count = 0
|
||||
while isNext:
|
||||
url = "https://wq.jd.com/user/info/QueryUserRedEnvelopesV2?type=2&orgFlag=JD_PinGou_New&page=%s&cashRedType=1&redBalanceFlag=0&channel=3&_=%s&sceneval=2&g_login_type=1&g_ty=ls" % (
|
||||
page, gettimestamp())
|
||||
headers = {
|
||||
'accept': '*/*',
|
||||
'accept-encoding': 'gzip, deflate, br',
|
||||
'accept-language': 'zh-CN,zh;q=0.9',
|
||||
'dnt': '1',
|
||||
'referer': 'https://wqs.jd.com/',
|
||||
'sec-fetch-dest': 'script',
|
||||
'sec-fetch-mode': 'no-cors',
|
||||
'sec-fetch-site': 'same-site',
|
||||
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1',
|
||||
'cookie': ck
|
||||
}
|
||||
r = requests.get(url, headers=headers).json()
|
||||
if r['data']['unUseRedInfo']['redList'] == None:
|
||||
print('\n【六个月红包总数】', count, '\n【累计红包总额】%.2f' % sum, '\n【已用红包总额】%.2f' % usedsum)
|
||||
print(
|
||||
'\n ↓↓↓↓↓↓明细↓↓↓↓↓↓\n【京东】总额: %.2f, 已用: %.2f\n【京喜】总额: %.2f, 已用: %.2f\n【极速】总额: %.2f, 已用: %.2f\n【健康】总额: %.2f, 已用: %.2f\n【通用】总额: %.2f, 已用: %.2f\n' % (
|
||||
jdsum, usedjd, jxsum, usedjx, litesum, usedlite, healthsum, usedhealth, tysum, usedty))
|
||||
isNext = False
|
||||
else:
|
||||
page += 1
|
||||
count = r['data']['unUseRedInfo']['count']
|
||||
for i in r['data']['unUseRedInfo']['redList']:
|
||||
sum += float(i['discount'])
|
||||
usedsum += (float(i['discount']) - float(i['balance']))
|
||||
if "京喜" in i['orgLimitStr']:
|
||||
jxsum += float(i['discount'])
|
||||
usedjx += (float(i['discount']) - float(i['balance']))
|
||||
elif "极速" in i['orgLimitStr']:
|
||||
litesum += float(i['discount'])
|
||||
usedlite += (float(i['discount']) - float(i['balance']))
|
||||
elif "健康" in i['orgLimitStr']:
|
||||
healthsum += float(i['discount'])
|
||||
usedhealth += (float(i['discount']) - float(i['balance']))
|
||||
elif "京东商城" in i['orgLimitStr']:
|
||||
jdsum += float(i['discount'])
|
||||
usedjd += (float(i['discount']) - float(i['balance']))
|
||||
else:
|
||||
tysum += float(i['discount'])
|
||||
usedty += (float(i['discount']) - float(i['balance']))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
printf('🔔历史红包统计, 开始!\n')
|
||||
try:
|
||||
cks = os.environ["JD_COOKIE"].split("&")
|
||||
except:
|
||||
f = open("/jd/config/config.sh", "r", encoding='utf-8')
|
||||
cks = re.findall(r'Cookie[0-9]*="(pt_key=.*?;pt_pin=.*?;)"', f.read())
|
||||
f.close()
|
||||
for ck in cks:
|
||||
ptpin = re.findall(r"pt_pin=(.*?);", ck)[0]
|
||||
printf("********开始京东账号" + ptpin + "********")
|
||||
try:
|
||||
getinfo(ck)
|
||||
except:
|
||||
print("发生异常错误")
|
||||
File diff suppressed because one or more lines are too long
+427
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,443 @@
|
||||
#!/bin/env python3
|
||||
# -*- coding: utf-8 -*
|
||||
'''
|
||||
Date: 2022-03-04
|
||||
cron: 5 0 0 * * * jd_health_exchange.py
|
||||
new Env('健康社区兑换京豆');
|
||||
'''
|
||||
#如果不想兑换京豆,ENV设置: export heath_noexchage='x'
|
||||
# x填写数字,x对应cookies中第几个账号,如果中间有黑号,黑号不算。多个账号不兑换用&隔开,例如2&3&4
|
||||
heath_noexchage=''
|
||||
|
||||
##############默认保留20W积分,18W积分才兑换20京豆############
|
||||
###想保留其他分数,ENV设置: export least='xxx'
|
||||
least = 200000
|
||||
|
||||
# 20京豆id为4
|
||||
id = '4'
|
||||
|
||||
|
||||
#每秒点击兑换次数...适当调整,手机会发烫
|
||||
#ENV设置: export dd_thread=30
|
||||
dd_thread = '10'
|
||||
|
||||
UserAgent = ''
|
||||
|
||||
import requests
|
||||
import time,datetime
|
||||
import requests,re,os,sys,random,json
|
||||
from urllib.parse import quote, unquote
|
||||
import threading
|
||||
import urllib3
|
||||
#urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
|
||||
|
||||
|
||||
|
||||
today = datetime.datetime.now().strftime('%Y-%m-%d')
|
||||
tomorrow=(datetime.datetime.now() + datetime.timedelta(days=1)).strftime('%Y-%m-%d')
|
||||
starttime = '23:59:58.00000000'
|
||||
|
||||
pwd = os.path.dirname(os.path.abspath(__file__)) + os.sep
|
||||
path = pwd + "env.sh"
|
||||
|
||||
script_name = '健康社区兑换-Python'
|
||||
|
||||
jd_host='https://api.m.jd.com/'
|
||||
|
||||
functionId=''
|
||||
|
||||
body = '{}'
|
||||
|
||||
uuid = ''
|
||||
|
||||
|
||||
def printT(s):
|
||||
print("[{0}]: {1}".format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), s))
|
||||
sys.stdout.flush()
|
||||
|
||||
def getEnvs(label):
|
||||
try:
|
||||
if label == 'True' or label == 'yes' or label == 'true' or label == 'Yes':
|
||||
return True
|
||||
elif label == 'False' or label == 'no' or label == 'false' or label == 'No':
|
||||
return False
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
if '.' in label:
|
||||
return float(label)
|
||||
elif '&' in label:
|
||||
return label.split('&')
|
||||
elif '@' in label:
|
||||
return label.split('@')
|
||||
else:
|
||||
return int(label)
|
||||
except:
|
||||
return label
|
||||
|
||||
|
||||
|
||||
class getJDCookie(object):
|
||||
|
||||
|
||||
# 检测cookie格式是否正确
|
||||
def getUserInfo(self, ck, pinName, userNum):
|
||||
url = 'https://me-api.jd.com/user_new/info/GetJDUserInfoUnion?orgFlag=JD_PinGou_New&callSource=mainorder&channel=4&isHomewhite=0&sceneval=2&sceneval=2&callback=GetJDUserInfoUnion'
|
||||
headers = {
|
||||
'Cookie': ck,
|
||||
'Accept': '*/*',
|
||||
'Connection': 'close',
|
||||
'Referer': 'https://home.m.jd.com/myJd/home.action',
|
||||
'Accept-Encoding': 'gzip, deflate, br',
|
||||
'Host': 'me-api.jd.com',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Mobile/15E148 Safari/604.1',
|
||||
'Accept-Language': 'zh-cn'
|
||||
}
|
||||
try:
|
||||
resp = requests.get(url=url, verify=False, headers=headers, timeout=60).text
|
||||
r = re.compile(r'GetJDUserInfoUnion.*?\((.*?)\)')
|
||||
result = r.findall(resp)
|
||||
userInfo = json.loads(result[0])
|
||||
nickname = userInfo['data']['userInfo']['baseInfo']['nickname']
|
||||
return ck, nickname
|
||||
except Exception:
|
||||
context = f"账号{userNum}【{pinName}】Cookie 已失效!请重新获取。"
|
||||
printT(context)
|
||||
return ck, False
|
||||
|
||||
def iscookie(self):
|
||||
"""
|
||||
:return: cookiesList,userNameList,pinNameList
|
||||
"""
|
||||
cookiesList = []
|
||||
userNameList = []
|
||||
pinNameList = []
|
||||
if 'pt_key=' in cookies and 'pt_pin=' in cookies:
|
||||
r = re.compile(r"pt_key=.*?pt_pin=.*?;", re.M | re.S | re.I)
|
||||
result = r.findall(cookies)
|
||||
if len(result) >= 1:
|
||||
printT("您已配置{}个账号".format(len(result)))
|
||||
u = 1
|
||||
for i in result:
|
||||
r = re.compile(r"pt_pin=(.*?);")
|
||||
pinName = r.findall(i)
|
||||
pinName = unquote(pinName[0])
|
||||
# 获取账号名
|
||||
#ck, nickname = self.getUserInfo(i, pinName, u)
|
||||
#if nickname != False:
|
||||
cookiesList.append(i)
|
||||
#userNameList.append(nickname)
|
||||
pinNameList.append(pinName)
|
||||
#else:
|
||||
# u += 1
|
||||
# continue
|
||||
#u += 1
|
||||
if len(cookiesList) > 0:
|
||||
return cookiesList, userNameList, pinNameList
|
||||
else:
|
||||
printT("没有可用Cookie,已退出")
|
||||
exit(3)
|
||||
else:
|
||||
printT("cookie 格式错误!...本次操作已退出")
|
||||
exit(4)
|
||||
else:
|
||||
printT("cookie 格式错误!...本次操作已退出")
|
||||
exit(4)
|
||||
getCk = getJDCookie()
|
||||
#getCk.getCookie()
|
||||
|
||||
# 获取v4环境 特殊处理
|
||||
try:
|
||||
with open(v4f, 'r', encoding='utf-8') as v4f:
|
||||
v4Env = v4f.read()
|
||||
r = re.compile(r'^export\s(.*?)=[\'\"]?([\w\.\-@#&=_,\[\]\{\}\(\)]{1,})+[\'\"]{0,1}$',
|
||||
re.M | re.S | re.I)
|
||||
r = r.findall(v4Env)
|
||||
curenv = locals()
|
||||
for i in r:
|
||||
if i[0] != 'JD_COOKIE':
|
||||
curenv[i[0]] = getEnvs(i[1])
|
||||
except:
|
||||
pass
|
||||
|
||||
############## 在pycharm测试ql环境用,实际用下面的代码运行 #########
|
||||
# with open(path, "r+", encoding="utf-8") as f:
|
||||
# ck = f.read()
|
||||
# if "JD_COOKIE" in ck:
|
||||
# # r = re.compile (r"pt_key=.*?pt_pin=.*?;", re.M | re.S | re.I)
|
||||
# # cookies = r.findall (ck)
|
||||
# # cookies = cookies[0]
|
||||
# # print(cookies)
|
||||
# cookies = ck
|
||||
# printT ("已获取并使用ck环境 Cookie")
|
||||
########################################################################
|
||||
|
||||
|
||||
if "JD_COOKIE" in os.environ:
|
||||
if len (os.environ["JD_COOKIE"]) > 1:
|
||||
cookies = os.environ["JD_COOKIE"]
|
||||
# temporary = cookies.split ('&')
|
||||
# cookies = temporary[0]
|
||||
printT ("已获取并使用Env环境 Cookie")
|
||||
|
||||
if "heath_noexchage" in os.environ:
|
||||
heath_noexchage = os.environ["heath_noexchage"]
|
||||
printT(f"已获取并使用Env环境 heath_noexchage:{heath_noexchage}")
|
||||
|
||||
if "least" in os.environ:
|
||||
least = getEnvs(os.environ["least"])
|
||||
printT(f"已获取并使用Env环境 least:{least}")
|
||||
|
||||
|
||||
heath_noexchage_list = heath_noexchage.split('&')
|
||||
|
||||
def userAgent():
|
||||
"""
|
||||
随机生成一个UA
|
||||
:return: jdapp;iPhone;9.4.8;14.3;xxxx;network/wifi;ADID/201EDE7F-5111-49E8-9F0D-CCF9677CD6FE;supportApplePay/0;hasUPPay/0;hasOCPay/0;model/iPhone13,4;addressid/2455696156;supportBestPay/0;appBuild/167629;jdSupportDarkMode/0;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1
|
||||
"""
|
||||
if not UserAgent:
|
||||
uuid = ''.join(random.sample('123456789abcdef123456789abcdef123456789abcdef123456789abcdef', 40))
|
||||
addressid = ''.join(random.sample('1234567898647', 10))
|
||||
iosVer = ''.join(
|
||||
random.sample(["14.5.1", "14.4", "14.3", "14.2", "14.1", "14.0.1", "13.7", "13.1.2", "13.1.1"], 1))
|
||||
iosV = iosVer.replace('.', '_')
|
||||
iPhone = ''.join(random.sample(["8", "9", "10", "11", "12", "13"], 1))
|
||||
ADID = ''.join(random.sample('0987654321ABCDEF', 8)) + '-' + ''.join(
|
||||
random.sample('0987654321ABCDEF', 4)) + '-' + ''.join(random.sample('0987654321ABCDEF', 4)) + '-' + ''.join(
|
||||
random.sample('0987654321ABCDEF', 4)) + '-' + ''.join(random.sample('0987654321ABCDEF', 12))
|
||||
return f'jdapp;iPhone;10.0.4;{iosVer};{uuid};network/wifi;ADID/{ADID};supportApplePay/0;hasUPPay/0;hasOCPay/0;model/iPhone{iPhone},1;addressid/{addressid};supportBestPay/0;appBuild/167629;jdSupportDarkMode/0;Mozilla/5.0 (iPhone; CPU iPhone OS {iosV} like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1'
|
||||
else:
|
||||
return UserAgent
|
||||
def difftime():
|
||||
heard={
|
||||
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
|
||||
}
|
||||
url="https://wq.jd.com/mcoss/servertime/getservertime?_=1664872855968&sceneval=2&g_login_type=1&callback=cb8216634&g_ty=ls&appCode=msc588d6d5"
|
||||
resp=requests.get(url,headers=heard).text
|
||||
res=re.match('.*\"serverTime\":\"(.*)\".*',resp).group(1)
|
||||
sertime=int(time.mktime(time.strptime(res, '%Y/%m/%d %H:%M:%S'))*1000)
|
||||
loctime=int(time.time()*1000)
|
||||
return loctime-sertime
|
||||
## 获取通知服务
|
||||
class msg(object):
|
||||
def __init__(self, m=''):
|
||||
self.str_msg = m
|
||||
self.message()
|
||||
def message(self):
|
||||
global msg_info
|
||||
printT(self.str_msg)
|
||||
try:
|
||||
msg_info = "{}\n{}".format(msg_info, self.str_msg)
|
||||
except:
|
||||
msg_info = "{}".format(self.str_msg)
|
||||
sys.stdout.flush() #这代码的作用就是刷新缓冲区。
|
||||
# 当我们打印一些字符时,并不是调用print函数后就立即打印的。一般会先将字符送到缓冲区,然后再打印。
|
||||
# 这就存在一个问题,如果你想等时间间隔的打印一些字符,但由于缓冲区没满,不会打印。就需要采取一些手段。如每次打印后强行刷新缓冲区。
|
||||
def getsendNotify(self, a=0):
|
||||
if a == 0:
|
||||
a += 1
|
||||
try:
|
||||
url = 'https://gitee.com/curtinlv/Public/raw/master/sendNotify.py'
|
||||
response = requests.get(url)
|
||||
if 'curtinlv' in response.text:
|
||||
with open('sendNotify.py', "w+", encoding="utf-8") as f:
|
||||
f.write(response.text)
|
||||
else:
|
||||
if a < 5:
|
||||
a += 1
|
||||
return self.getsendNotify(a)
|
||||
else:
|
||||
pass
|
||||
except:
|
||||
if a < 5:
|
||||
a += 1
|
||||
return self.getsendNotify(a)
|
||||
else:
|
||||
pass
|
||||
def main(self):
|
||||
global send
|
||||
cur_path = os.path.abspath(os.path.dirname(__file__))
|
||||
sys.path.append(cur_path)
|
||||
if os.path.exists(cur_path + "/sendNotify.py"):
|
||||
try:
|
||||
from sendNotify import send
|
||||
except:
|
||||
self.getsendNotify()
|
||||
try:
|
||||
from sendNotify import send
|
||||
except:
|
||||
printT("加载通知服务失败~")
|
||||
else:
|
||||
self.getsendNotify()
|
||||
try:
|
||||
from sendNotify import send
|
||||
except:
|
||||
printT("加载通知服务失败~")
|
||||
###################
|
||||
msg().main()
|
||||
|
||||
|
||||
def listcookie(): #将JDCookies.txt的cookies变成list[]
|
||||
if 'pt_key=' in cookies and 'pt_pin=' in cookies:
|
||||
r = re.compile(r"pt_key=.*?pt_pin=.*?;" , re.M | re.S | re.I) #r"" 的作用是去除转义字符.
|
||||
result = r.findall(cookies) #输出为list列表
|
||||
if len(result) == 1:
|
||||
return result
|
||||
elif len(result)>1:
|
||||
return result
|
||||
else:
|
||||
print("cookie 格式错误!...本次操作已退出")
|
||||
exit(1)
|
||||
else:
|
||||
print("cookie 格式错误!...本次操作已退出")
|
||||
exit(9)
|
||||
|
||||
def setHeaders(cookie):
|
||||
try:
|
||||
r = re.compile(r"pt_pin=(.*?);") #指定一个规则:查找pt_pin=与;之前的所有字符,但pt_pin=与;不复制。r"" 的作用是去除转义字符.
|
||||
userName = r.findall(cookie) #查找pt_pin=与;之前的所有字符,并复制给r,其中pt_pin=与;不复制。
|
||||
#print (userName)
|
||||
userName = unquote(userName[0]) #r.findall(cookie)赋值是list列表,这个赋值为字符串
|
||||
#print(userName)
|
||||
except Exception as e:
|
||||
print(e,"cookie格式有误!")
|
||||
exit(2)
|
||||
headers = {
|
||||
'Origin': 'https://h5.m.jd.com',
|
||||
'Cookie': cookie,
|
||||
'Connection': 'keep-alive',
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'Referer': 'https://h5.m.jd.com/',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'User-Agent': userAgent(),
|
||||
'Accept-Encoding': 'gzip, deflate',
|
||||
'Accept-Language': 'zh-cn'
|
||||
}
|
||||
return headers,userName
|
||||
|
||||
#返回符合条件的ck list
|
||||
def checkUser(cookies):
|
||||
global goodsid, mid_time,afternoon_time
|
||||
if isinstance(cookies,list): #isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。此方法为:判断cookies是否为list[]列表,是返回True,否返回False
|
||||
pass
|
||||
elif isinstance(cookies,str): #判断cookies是否为str字符串,是返回True,否返回False
|
||||
cookies = listcookie()
|
||||
else:
|
||||
print("cookie 类型有误")
|
||||
exit(2)
|
||||
cookieList=[]
|
||||
#print(cookies)
|
||||
user_num=1
|
||||
for i in cookies:
|
||||
headers,userName = setHeaders(i)
|
||||
try:
|
||||
total_exchangePoints = cheak_points('jdhealth_getHomeData','{}',headers)
|
||||
title,exchangePoints,bizMsg,bizCode = jdhealth_getCommodities('jdhealth_getCommodities','',headers)
|
||||
if user_num == 1:
|
||||
printT("您已设置兑换的商品:【{0}豆】 需要{1}积分".format(title, exchangePoints))
|
||||
print("********** 检测符合兑换要求的账号 ********** ")
|
||||
if int(total_exchangePoints) > least:
|
||||
total_exchangePoints = int(total_exchangePoints)
|
||||
if not str(user_num) in heath_noexchage_list:
|
||||
cookieList.append(i) #将够钱兑换的账号保存下来给cookieList[],其余不够钱的账号剔除在外,不执行兑换
|
||||
printT(f"账号{user_num}:【{userName}】积分:{total_exchangePoints}...yes")
|
||||
else:
|
||||
total_exchangePoints = int (total_exchangePoints)
|
||||
printT(f"账号{user_num}:【{userName}】积分:{total_exchangePoints}...no")
|
||||
except Exception as e:
|
||||
#printT(f"账号{user_num}:【{userName}】,该用户异常,查不到商品关键词【{Coupon}】,或者cookies已过期")
|
||||
msg(f"账号{user_num}:【{userName}】,该用户异常,查不到商品id【{id}】")
|
||||
# if '异常' in msg_info:
|
||||
# send (script_name, msg_info)
|
||||
# if len (cookies) == 1:
|
||||
#exit (0)
|
||||
user_num+=1
|
||||
if len (cookieList) > 0:
|
||||
printT ("共有{0}个账号符合兑换条件".format (len (cookieList)))
|
||||
return cookieList
|
||||
else:
|
||||
printT ("没有账号符合兑换要求,退出执行")
|
||||
exit(0)
|
||||
#查询总分
|
||||
def cheak_points(functionId,body,headers):
|
||||
url = jd_host + '?' +'functionId=' + functionId + '&body=' + body + '&client=wh5&clientVersion=1.0.0&' + 'uuid=' + uuid
|
||||
try:
|
||||
respon = requests.post(url=url, verify=False, headers=headers)
|
||||
result=respon.json()
|
||||
#print(result)
|
||||
total_exchangePoints = result['data']['result']['userScore'] #兑换所需分数
|
||||
return float(total_exchangePoints)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
#查询
|
||||
def jdhealth_getCommodities(functionId,body,headers):
|
||||
url = jd_host + '?' +'functionId=' + functionId + '&body=' + body + '&client=wh5&clientVersion=1.0.0&' + 'uuid=' + uuid
|
||||
try:
|
||||
respon = requests.post(url=url, verify=False, headers=headers)
|
||||
result=respon.json()
|
||||
title = result['data']['result']['jBeans'][3]['title']
|
||||
exchangePoints = result['data']['result']['jBeans'][3]['exchangePoints'] #兑换所需分数
|
||||
bizMsg = result['data']['bizMsg']
|
||||
bizCode = result['data']['bizCode']
|
||||
return title,exchangePoints,bizMsg,bizCode
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
#兑换
|
||||
def jdhealth_exchange(functionId,body,headers):
|
||||
url = jd_host + '?' +'functionId=' + functionId + '&body=' + body + '&client=wh5&clientVersion=1.0.0&' + 'uuid=' + uuid
|
||||
try:
|
||||
respon = requests.post(url=url, verify=False, headers=headers)
|
||||
result=respon.json()
|
||||
#title = result['data']['result']['jingBeanNum']
|
||||
#userScore = result['data']['result']['userScore'] #剩余积分
|
||||
bizMsg = result['data']['bizMsg']
|
||||
bizCode = result['data']['bizCode']
|
||||
success = result['data']['success']
|
||||
if bizMsg == 'success' or bizCode == '0' :
|
||||
printT("{0}...恭喜兑换成功!".format(bizMsg))
|
||||
return 0
|
||||
else:
|
||||
printT(f"\t{bizMsg}" + ',兑换失败') #f 表达式----可以解析任意的数据类型。 \t表示空4格,相当于tab。
|
||||
return 999
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
def start():
|
||||
print (f"############# 开始############ ")
|
||||
cookiesList, userNameList, pinNameList = getCk.iscookie ()
|
||||
cookies1 = checkUser (cookiesList) # 将够钱兑换的账号保存下来给cookies,其余不够钱的账号剔除在外,不执行兑换
|
||||
final = 1
|
||||
diff=difftime()
|
||||
tomorrow=datetime.date.today() + datetime.timedelta(days=1)
|
||||
tomorrow=int(time.mktime(time.strptime(str(tomorrow), '%Y-%m-%d'))*1000)
|
||||
print((tomorrow - int(time.time()*1000) + diff)/1000)
|
||||
time.sleep((tomorrow - int(time.time()*1000) + diff)/1000)
|
||||
while True:
|
||||
print (f"\n【准备开始...】\n")
|
||||
user_num = 1
|
||||
for i in cookies1:
|
||||
headers, userName = setHeaders (i)
|
||||
final = jdhealth_exchange ('jdhealth_exchange','{"commodityType":2,"commodityId":"4"}',headers)
|
||||
user_num += 1
|
||||
if final == 0:
|
||||
last_points = cheak_points ('jdhealth_getHomeData','',headers)
|
||||
title, exchangePoints, bizMsg, bizCode = jdhealth_getCommodities ('jdhealth_getCommodities', '{}',headers)
|
||||
# printT (f"账号{user_num}:【{userName}】剩余积分:{last_integration}...")
|
||||
msg (f"账号{user_num}:【{userName}】成功兑换【{title}豆】,剩余积分:{last_points}...")
|
||||
|
||||
elif final == 999:
|
||||
pass
|
||||
if user_num > len(cookies1):
|
||||
break
|
||||
if __name__ == '__main__':
|
||||
print("脚本默认兑换20豆,18W分以上才兑换,具体修改教程可看脚本开头注释")
|
||||
print ("\t\t【{}】".format (script_name))
|
||||
start ()
|
||||
if '成功兑换' in msg_info:
|
||||
send (script_name, msg_info)
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
#依赖安装,运行一次就好
|
||||
#0 8 5 5 * jd_indeps.sh
|
||||
#new Env('依赖安装');
|
||||
#
|
||||
|
||||
npm_ver=`pnpm -v|awk -F. '{print $1}'`
|
||||
if [[ $npm_ver -ge 7 ]];then
|
||||
export PNPM_HOME="/root/.local/share/pnpm"
|
||||
export PATH="$PNPM_HOME:$PATH"
|
||||
fi
|
||||
|
||||
echo -e "安装脚本所需依赖,不一定一次全部安装成功,请自己检查\n"
|
||||
echo -e "开始安装............\n"
|
||||
|
||||
#apk add g++ make pixman-dev pango-dev cairo-dev pkgconf --no-cache
|
||||
apk add g++ make --no-cache
|
||||
pnpm config set registry https://registry.npm.taobao.org
|
||||
pnpm install -g
|
||||
pnpm install -g ds
|
||||
pnpm install -g png-js
|
||||
pnpm install -g date-fns
|
||||
pnpm install -g axios@0.27.2
|
||||
pnpm install -g crypto-js
|
||||
pnpm install -g ts-md5
|
||||
pnpm install -g tslib
|
||||
pnpm install -g @types/node
|
||||
pnpm install -g request
|
||||
pnpm install -g jsdom
|
||||
pnpm install -g moment
|
||||
pnpm install -g cheerio
|
||||
pnpm install -g tough-cookie
|
||||
pnpm install -g https-proxy-agent
|
||||
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple/ jieba
|
||||
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple/ requests
|
||||
rm -rf /usr/local/pnpm-global/5/node_modules/.pnpm/canvas*
|
||||
rm -rf /root/.local/share/pnpm/global/5/.pnpm/canvas*
|
||||
echo -e "\n所需依赖安装完成,请检查有没有报错,可尝试再次运行"
|
||||
+172
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
汪汪赛跑-提现10元,周五9点
|
||||
59 59 8 * * 5 jd_joy_run_reward.ts
|
||||
new Env('汪汪赛跑提现')
|
||||
updateTime:2022-07-09
|
||||
**/
|
||||
|
||||
import { get, post, requireConfig, wait } from './TS_USER_AGENTS'
|
||||
import { H5ST } from "./function/h5st"
|
||||
|
||||
let cookie: string = '', res: any = '', UserName: string = '', fp_448de: string = '' || process.env.FP_448DE, fp_b6ac3: string = '' || process.env.FP_B6AC3
|
||||
let h5stTool: H5ST = null
|
||||
|
||||
!(async () => {
|
||||
let cookiesArr: string[] = await requireConfig()
|
||||
for (let [index, value] of cookiesArr.entries()) {
|
||||
cookie = value
|
||||
UserName = decodeURIComponent(cookie.match(/pt_pin=([^;]*)/)![1])
|
||||
console.log(`\n开始【京东账号${index + 1}】${UserName}\n`)
|
||||
let rewardAmount: number = 0
|
||||
try {
|
||||
h5stTool = new H5ST('448de', 'jdltapp;', fp_448de)
|
||||
await h5stTool.__genAlgo()
|
||||
res = await team('runningMyPrize', { "linkId": "L-sOanK_5RJCz7I314FpnQ", "pageSize": 20, "time": null, "ids": null })
|
||||
rewardAmount = res.data.rewardAmount
|
||||
if (res.data.runningCashStatus.currentEndTime) {
|
||||
console.log('可提现', rewardAmount)
|
||||
res = await api('runningPrizeDraw', { "linkId": "L-sOanK_5RJCz7I314FpnQ", "type": 2, "level": 3 })
|
||||
if (res.errMsg.indexOf("不足") > -1) {
|
||||
res = await api('runningPrizeDraw', { "linkId": "L-sOanK_5RJCz7I314FpnQ", "type": 2, "level": 2 })
|
||||
}
|
||||
await wait(1000)
|
||||
if (res.success) {
|
||||
console.log(res.data.message)
|
||||
} else {
|
||||
console.log('提现失败:', res.errMsg)
|
||||
}
|
||||
} else {
|
||||
console.log('还未到提现时间')
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('Error', e)
|
||||
await wait(1000)
|
||||
}
|
||||
}
|
||||
})()
|
||||
|
||||
async function api(fn: string, body: object) {
|
||||
let timestamp: number = Date.now(), h5st: string = ''
|
||||
if (fn === 'runningOpenBox') {
|
||||
h5st = h5stTool.__genH5st({
|
||||
appid: "activities_platform",
|
||||
body: JSON.stringify(body),
|
||||
client: "ios",
|
||||
clientVersion: "3.1.0",
|
||||
functionId: "runningOpenBox",
|
||||
t: timestamp.toString()
|
||||
})
|
||||
}
|
||||
let params: string = `functionId=${fn}&body=${JSON.stringify(body)}&t=${timestamp}&appid=activities_platform&client=ios&clientVersion=3.1.0&cthr=1`
|
||||
h5st && (params += `&h5st=${h5st}`)
|
||||
return await post('https://api.m.jd.com/', params, {
|
||||
'authority': 'api.m.jd.com',
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
'cookie': cookie,
|
||||
'origin': 'https://h5platform.jd.com',
|
||||
'referer': 'https://h5platform.jd.com/',
|
||||
'user-agent': 'jdltapp;'
|
||||
})
|
||||
}
|
||||
|
||||
async function team(fn: string, body: object) {
|
||||
let timestamp: number = Date.now(), h5st: string
|
||||
h5st = h5stTool.__genH5st({
|
||||
appid: "activities_platform",
|
||||
body: JSON.stringify(body),
|
||||
client: "ios",
|
||||
clientVersion: "3.1.0",
|
||||
functionId: fn,
|
||||
t: timestamp.toString()
|
||||
})
|
||||
return await get(`https://api.m.jd.com/?functionId=${fn}&body=${encodeURIComponent(JSON.stringify(body))}&t=${timestamp}&appid=activities_platform&client=ios&clientVersion=3.1.0&cthr=1&h5st=${h5st}`, {
|
||||
'Host': 'api.m.jd.com',
|
||||
'User-Agent': 'jdltapp;',
|
||||
'Origin': 'https://h5platform.jd.com',
|
||||
'X-Requested-With': 'com.jd.jdlite',
|
||||
'Referer': 'https://h5platform.jd.com/',
|
||||
'Cookie': cookie
|
||||
})
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+13
File diff suppressed because one or more lines are too long
+176
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
京东快递
|
||||
@Leaf
|
||||
|
||||
*/
|
||||
const $ = new Env('京东快递');
|
||||
const got = require('got');
|
||||
|
||||
const envSplitor = ['&','\n','@']
|
||||
const ckNames = ['JD_COOKIE']
|
||||
|
||||
const MAX_THREAD = parseInt(process.env['jd_jdkd_thread']) || 5
|
||||
const DEFAULT_TIMEOUT=8000, DEFAULT_RETRY=3;
|
||||
|
||||
const default_UA = 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.31(0x18001f2f) NetType/WIFI Language/zh_CN miniProgram/wx73247c7819d61796'
|
||||
const Referer = 'https://jingcai-h5.jd.com/'
|
||||
const Origin = 'https://jingcai-h5.jd.com'
|
||||
|
||||
const client = got.extend({
|
||||
headers:{
|
||||
Connection:'keep-alive',
|
||||
'User-Agent': default_UA,
|
||||
Referer,
|
||||
Origin,
|
||||
AppParams: JSON.stringify({"appid":158,"ticket_type":"m"}),
|
||||
ClientInfo: JSON.stringify({"appName":"jingcai","client":"m"}),
|
||||
'LOP-DN': 'jingcai.jd.com',
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
},
|
||||
retry: {limit:0},
|
||||
timeout: DEFAULT_TIMEOUT,
|
||||
followRedirect: false,
|
||||
})
|
||||
|
||||
class BasicClass{constructor(){this.index=$.userIdx++;this.name='';} log(msg,opt={}){var m='',n=$.userCount.toString().length;;if(this.index)m+=`账号[${$.padStr(this.index,n)}]`;if(this.name)m+=`[${this.name}]`;$.log(m+msg,opt);} async request(opt){var resp=null,count=0;var fn=opt.fn||opt.url;opt.method=opt?.method?.toUpperCase()||'GET';while(count++<DEFAULT_RETRY){try{await client(opt).then(t=>{resp=t},e=>{resp=e.response});if(((resp?.statusCode/100)|0)<=4)break;}catch(e){if(e.name=='TimeoutError'){this.log(`[${fn}]请求超时,重试第${count}次`);}else{this.log(`[${fn}]请求错误(${e.message}),重试第${count}次`);}};} if(resp==null)return Promise.resolve({statusCode:-1,headers:null,result:null});let{statusCode,headers,body}=resp;if(body)try{body=JSON.parse(body);}catch{};return Promise.resolve({statusCode,headers,result:body})}}
|
||||
let http = new BasicClass();
|
||||
|
||||
class UserClass extends BasicClass {
|
||||
constructor(ck) {
|
||||
super()
|
||||
this.cookie = ck
|
||||
this.pt_pin = ck.match(/pin=([\w\-\%]+)/) ? ck.match(/pin=([\w\-\%]+)/)[1] : ''
|
||||
this.name = decodeURIComponent(this.pt_pin)
|
||||
}
|
||||
|
||||
async queryTaskList() {
|
||||
try {
|
||||
let options = {
|
||||
fn: 'queryTaskList',
|
||||
method: 'post',
|
||||
url: 'https://lop-proxy.jd.com/ESGApi/queryTaskList',
|
||||
headers: {Cookie:this.cookie,'event-id':$.randomPattern('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx')},
|
||||
json: [{"pin":"$cooMrdGatewayUid$"}],
|
||||
}
|
||||
let {result} = await this.request(options)
|
||||
let code = result?.code
|
||||
if(code == 1) {
|
||||
for(let task of (result?.content?.taskInfoList||[]).filter(x => x.taskReachNum < x.taskNeedReachNum && x.triggerType==1)) {
|
||||
await this.reachTaskInfo(task);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
let errCode = code || result?.error_response?.code
|
||||
let errMsg = result?.msg || result?.error_response?.zh_desc
|
||||
this.log(`查询任务列表出错[${errCode}]: ${errMsg}`)
|
||||
}
|
||||
} catch (e) {
|
||||
$.log(e)
|
||||
} finally {
|
||||
return Promise.resolve()
|
||||
}
|
||||
}
|
||||
|
||||
async reachTaskInfo(task) {
|
||||
try {
|
||||
let options = {
|
||||
fn: 'reachTaskInfo',
|
||||
method: 'post',
|
||||
url: 'https://lop-proxy.jd.com/ESGApi/reachTaskInfo',
|
||||
headers: {Cookie:this.cookie,'event-id':$.randomPattern('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx')},
|
||||
json: [{
|
||||
taskNo: task.taskNo,
|
||||
childTaskId: task.childTaskId,
|
||||
pin: "$cooMrdGatewayUid$",
|
||||
}],
|
||||
}
|
||||
let {result} = await this.request(options)
|
||||
let code = result?.code
|
||||
if(code == 1) {
|
||||
this.log(`完成任务[${task.taskTitle}]成功`)
|
||||
await this.queryTaskList();
|
||||
} else {
|
||||
let errCode = code || result?.error_response?.code
|
||||
let errMsg = result?.msg || result?.error_response?.zh_desc
|
||||
this.log(`完成任务[${task.taskTitle}]失败[${errCode}]: ${errMsg}`)
|
||||
}
|
||||
} catch (e) {
|
||||
$.log(e)
|
||||
} finally {
|
||||
return Promise.resolve()
|
||||
}
|
||||
}
|
||||
|
||||
async queryCanGetRewardTaskList() {
|
||||
try {
|
||||
let options = {
|
||||
fn: 'queryCanGetRewardTaskList',
|
||||
method: 'post',
|
||||
url: 'https://lop-proxy.jd.com/ESGApi/queryCanGetRewardTaskList',
|
||||
headers: {Cookie:this.cookie,'event-id':$.randomPattern('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx')},
|
||||
json: [{"pin":"$cooMrdGatewayUid$"}],
|
||||
}
|
||||
let {result} = await this.request(options)
|
||||
let code = result?.code
|
||||
if(code == 1) {
|
||||
for(let item of (result?.content?.personalCarbonRewardRespDtoList||[])) {
|
||||
await this.operationPersonalCarbonIntegral(item)
|
||||
}
|
||||
} else {
|
||||
let errCode = code || result?.error_response?.code
|
||||
let errMsg = result?.msg || result?.error_response?.zh_desc
|
||||
this.log(`查询可领取奖励出错[${errCode}]: ${errMsg}`)
|
||||
}
|
||||
} catch (e) {
|
||||
$.log(e)
|
||||
} finally {
|
||||
return Promise.resolve()
|
||||
}
|
||||
}
|
||||
|
||||
async operationPersonalCarbonIntegral(item) {
|
||||
try {
|
||||
let options = {
|
||||
fn: 'operationPersonalCarbonIntegral',
|
||||
method: 'post',
|
||||
url: 'https://lop-proxy.jd.com/ESGApi/operationPersonalCarbonIntegral',
|
||||
headers: {Cookie:this.cookie,'event-id':$.randomPattern('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx')},
|
||||
json: [{
|
||||
type: 2,
|
||||
operationType: 1,
|
||||
rewardNo: item.rewardNo,
|
||||
taskNo: item.taskNo,
|
||||
pin: "$cooMrdGatewayUid$",
|
||||
}],
|
||||
}
|
||||
let {result} = await this.request(options)
|
||||
let code = result?.code
|
||||
if(code == 1) {
|
||||
this.log(`收取[${item.taskTitle}]奖励成功, 现在有${result?.content?.carbonIntegral}g能量`)
|
||||
} else {
|
||||
let errCode = code || result?.error_response?.code
|
||||
let errMsg = result?.msg || result?.error_response?.zh_desc
|
||||
this.log(`收取[${item.taskTitle}]奖励失败[${errCode}]: ${errMsg}`)
|
||||
}
|
||||
} catch (e) {
|
||||
$.log(e)
|
||||
} finally {
|
||||
return Promise.resolve()
|
||||
}
|
||||
}
|
||||
|
||||
async userTask() {
|
||||
await this.queryTaskList();
|
||||
await this.queryCanGetRewardTaskList();
|
||||
}
|
||||
}
|
||||
|
||||
!(async () => {
|
||||
$.read_env(UserClass);
|
||||
|
||||
await $.threadTask('userTask',MAX_THREAD)
|
||||
})()
|
||||
.catch((e) => $.log(e))
|
||||
.finally(() => $.exitNow())
|
||||
|
||||
function Env(name){return new class{constructor(name){this.name=name;this.startTime=Date.now();this.log(`[${this.name}]开始运行\n`,{time:true});this.notifyStr=[];this.notifyFlag=true;this.userIdx=0;this.userList=[];this.userCount=0;} log(msg,options={}){let opt={console:true};Object.assign(opt,options);if(opt.time){let fmt=opt.fmt||'hh:mm:ss';msg=`[${this.time(fmt)}]`+msg;} if(opt.notify)this.notifyStr.push(msg);if(opt.console)console.log(msg);} read_env(Class){let envStrList=ckNames.map(x=>process.env[x]);for(let env_str of envStrList.filter(x=>!!x)){let sp=envSplitor.filter(x=>env_str.includes(x));let splitor=sp.length>0?sp[0]:envSplitor[0];for(let ck of env_str.split(splitor).filter(x=>!!x)){this.userList.push(new Class(ck));}} this.userCount=this.userList.length;if(!this.userCount){this.log(`未找到变量,请检查变量${ckNames.map(x => '['+x+']').join('或')}`,{notify:true});return false;} this.log(`共找到${this.userCount}个账号`);return true;} async threads(taskName,conf,opt={}){while(conf.idx<$.userList.length){let user=$.userList[conf.idx++];await user[taskName](opt);}} async threadTask(taskName,thread){let taskAll=[];let taskConf={idx:0};while(thread--)taskAll.push(this.threads(taskName,taskConf));await Promise.all(taskAll);} time(t,x=null){let xt=x?new Date(x):new Date;let e={"M+":xt.getMonth()+1,"d+":xt.getDate(),"h+":xt.getHours(),"m+":xt.getMinutes(),"s+":xt.getSeconds(),"q+":Math.floor((xt.getMonth()+3)/3),S:this.padStr(xt.getMilliseconds(),3)};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(xt.getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t;} async showmsg(){if(!this.notifyFlag)return;if(!this.notifyStr.length)return;var notify=require('./sendNotify');this.log('\n============== 推送 ==============');await notify.sendNotify(this.name,this.notifyStr.join('\n'));} padStr(num,length,opt={}){let padding=opt.padding||'0';let mode=opt.mode||'l';let numStr=String(num);let numPad=(length>numStr.length)?(length-numStr.length):0;let pads='';for(let i=0;i<numPad;i++){pads+=padding;} if(mode=='r'){numStr=numStr+pads;}else{numStr=pads+numStr;} return numStr;} json2str(obj,c,encode=false){let ret=[];for(let keys of Object.keys(obj).sort()){let v=obj[keys];if(v&&encode)v=encodeURIComponent(v);ret.push(keys+'='+v);} return ret.join(c);} str2json(str,decode=false){let ret={};for(let item of str.split('&')){if(!item)continue;let idx=item.indexOf('=');if(idx==-1)continue;let k=item.substr(0,idx);let v=item.substr(idx+1);if(decode)v=decodeURIComponent(v);ret[k]=v;} return ret;} randomPattern(pattern,charset='abcdef0123456789'){let str='';for(let chars of pattern){if(chars=='x'){str+=charset.charAt(Math.floor(Math.random()*charset.length));}else if(chars=='X'){str+=charset.charAt(Math.floor(Math.random()*charset.length)).toUpperCase();}else{str+=chars;}} return str;} randomString(len,charset='abcdef0123456789'){let str='';for(let i=0;i<len;i++){str+=charset.charAt(Math.floor(Math.random()*charset.length));} return str;} randomList(a){let idx=Math.floor(Math.random()*a.length);return a[idx];} wait(t){return new Promise(e=>setTimeout(e,t));} async exitNow(){await this.showmsg();let e=Date.now();let s=(e-this.startTime)/1000;this.log('');this.log(`[${this.name}]运行结束,共运行了${s}秒`,{time:true});process.exit(0);}} (name)}
|
||||
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user