const config = {
"PATH_IMG_V2_PRO": "https://cdn-image.gandart.com/",
"RUN_TYPE": 1,
"BOTTOM_LOAD_MORE_THROTTLE": 100,
"BASE_API": "https://api.gandart.com/base",
"RESALE_API": "https://api.gandart.com/market",
"RESALE_API_V2": "https://api2.gandart.com/market/api/v2",
"RESALE_API_V3": "https://api2.gandart.com/market/api/v3",
"SALE_API": "https://api.gandart.com/read/api",
"ORDER_API": "https://api.gandart.com",
"WALLET_API": "https://api.gandart.com/api",
"HXT_API": "https://api.gandart.com/wallet",
"PATH_IMG_V2": "https://cdn-image.gandart.com/",
"SAND_RECHARGE_ACTION": "https://cap.sandpay.com.cn/v4/front-electrans/ceas.elec.trans.quick.deposit.apply",
"GAME_ElF_API": "https://elf.pentajam.cn/api",
"GAME_ELF_URL": "https://elf.pentajam.cn",
"CORECENTER_URL": "https://api.gandart.com/corecenter"
};
const lk = new ToolKit(`光予助手`, `GandartHelper`, `gandartHelper.js`);
const gandartTokenKey = 'lkGandartToken';
const gardartCollectionNameKey = 'lkGandartCollectionName';
const gardartCastingIdKey = 'lkGandartCastingId';
const gardartLimitPriceKey = 'lkGandartLimitPrice';
const gandartTransactionRecordIdKey = 'lkGandartTransactionRecordId';
const gandartCollectionCateLstKey = 'lkGandartCollectionCateLst';
let gandartToken = lk.getVal(gandartTokenKey, '');
const GCommonGandartHeads = {
'Accept': `application/json, text/plain, */*`,
'Origin': `https://www.gandart.com`,
'Accept-Encoding': `gzip, deflate, br`,
'Content-Type': `application/x-www-form-urlencoded;charset=UTF-8`,
'Connection': `keep-alive`,
'Host': `api2.gandart.com`,
'User-Agent': `Mozilla/5.0 (iPhone; CPU iPhone OS 16_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.3 Mobile/15E148 Safari/604.1`,
'Referer': `https://www.gandart.com/`,
'Accept-Language': `zh-CN,zh-Hans;q=0.9`,
'token': gandartToken
};
if (!lk.isExecComm) {
if (lk.isRequest()) {
checkHanldeRequest();
lk.done();
} else {
all();
}
}
function checkHanldeRequest() {
const url = $request.url;
const path = lk.getUrlPath(url);
lk.log(`请求url=${url}#${$request.method}`);
lk.log(`请求body=${$request.body}`);
if ($request && $request.method != 'OPTIONS') {
switch(path){
case `base/auth/verifyCodeLogin`:
handleVerifyCodeLogin();
break;
case `base/v2/resaleManage/resale/findAllIsOpenResale`:
handleFindAllIsOpenResale();
break;
case `base/v2/favorite/selectRecord`:
// handleSelectRecord();
break;
case `market/api/v3/resaleManage/resale/tradingMarket`:
handleTradingMarket();
break;
case `market/api/v2/resaleManage/resale/collectionDetailsByCastingId`:
handleCollectionDetailsByCastingId();
break;
default:
break;
}
}
}
function handleVerifyCodeLogin(){
lk.log(`开始获取Token`);
let data = lk.getResponseBody();
try {
data = JSON.parse(data);
if (data.success) {
let jwktoken = data.obj.token;
lk.setVal(gandartTokenKey, jwktoken);
lk.appendNotifyInfo('🎉成功获取光予token,可以关闭相应脚本');
} else {
lk.execFail();
lk.appendNotifyInfo('❌获取光予token失败,请稍后再试');
}
} catch (e) {
lk.execFail();
lk.appendNotifyInfo('❌获取光予token失败');
}
lk.msg('');
}
function handleFindAllIsOpenResale(){
lk.log(`获取最新产品开放在售列表`);
let data = lk.getResponseBody();
try {
data = JSON.parse(data);
if (data.success) {
let obj = data.obj;
let oldItemlst = JSON.parse(lk.getVal(gandartCollectionCateLstKey, '[]'));
let pageItemlst = obj;
let newLst = checkAppendCollectionItemsDiff(oldItemlst, pageItemlst);
let jsonStr = JSON.stringify(newLst);
lk.setVal(gandartCollectionCateLstKey, jsonStr);
lk.log(jsonStr);
}
} catch (e) {
lk.logErr(e);
lk.execFail();
}
lk.msg('');
}
function handleSelectRecord(){
lk.log(`获取收藏的产品列表`);
let data = lk.getResponseBody();
try {
data = JSON.parse(data);
if (data.success) {
let obj = data.obj;
let oldItemlst = JSON.parse(lk.getVal(gandartCollectionCateLstKey, '[]'));
let pageItemlst = obj;
let newLst = checkAppendCollectionItemsDiff(oldItemlst, pageItemlst);
let jsonStr = JSON.stringify(newLst);
lk.setVal(gandartCollectionCateLstKey, jsonStr);
lk.log(jsonStr);
}
} catch (e) {
lk.logErr(e);
lk.execFail();
}
lk.msg('');
}
function handleTradingMarket(){
lk.log(`获取最新Token并更新产品列表`);
if ($request.headers.token) {
let jwktoken = $request.headers.token;
lk.setVal(gandartTokenKey, jwktoken);
}
let data = lk.getResponseBody();
try {
data = JSON.parse(data);
if (data.success) {
let obj = data.obj;
let oldItemlst = JSON.parse(lk.getVal(gandartCollectionCateLstKey, '[]'));
let pageItemlst = obj.list;
let newLst = checkAppendCollectionItemsDiff(oldItemlst, pageItemlst);
let jsonStr = JSON.stringify(newLst);
lk.setVal(gandartCollectionCateLstKey, jsonStr);
lk.log(jsonStr);
}
} catch (e) {
lk.logErr(e);
lk.execFail();
}
lk.msg('');
}
function handleCollectionDetailsByCastingId(){
lk.log(`开始获取产品信息`);
let data = lk.getResponseBody();
try {
data = JSON.parse(data);
if (data["success"]) {
let obj = data["obj"];
let castingId = String(obj["castingId"]);
if (castingId == "") {
// 无法获取请求体
let body = $request.body;
}
if (castingId != "") {
lk.setVal(gardartCastingIdKey, castingId);
let collectionName = obj["collectionName"];
lk.setVal(gardartCollectionNameKey, collectionName);
lk.log(collectionName + " castingId=" + obj["castingId"]);
lk.appendNotifyInfo(`🎉成功获取[${collectionName}]信息`);
} else {
lk.appendNotifyInfo('❌获取产品信息失败');
}
} else {
lk.execFail();
lk.appendNotifyInfo('❌获取产品信息失败,请稍后再试');
}
} catch (e) {
lk.logErr(e);
lk.execFail();
lk.appendNotifyInfo('❌获取产品信息失败');
}
lk.msg('');
}
function checkAppendCollectionItemsDiff(cLst, pageLst) {
let dic = {};
for (const d of cLst) {
dic[d.castingId] = d;
}
for (const d of pageLst) {
dic[d.castingId] = Object.assign(d || {}, dic[d.castingId]);
}
let newLst = [];
for (let k in dic) {
let ele = {
castingId: dic[k].castingId,
collectionName: dic[k].collectionName,
resalePrice: dic[k].resalePrice || 0,
};
newLst.push(ele);
}
return newLst;
}
function getCollectionNameById(castingId) {
let name = '未获取';
let clst = JSON.parse(lk.getVal(gandartCollectionCateLstKey, "[]"));
for (const d of clst) {
if (d.castingId == castingId) {
name = d.collectionName;
break;
}
}
return name;
}
function getCurCollectionName() {
let collectionName = lk.setVal(gardartCollectionNameKey, "");
return collectionName;
}
async function all() {
let hasNeedSendNotify = true;
if (gandartToken == '') {
lk.execFail();
lk.appendNotifyInfo(`⚠️请先打开光予登录获取token`);
} else {
let castingId = lk.getVal(gardartCastingIdKey, 0);
castingId = Number(castingId);
let price = lk.getVal(gardartLimitPriceKey, 0);
price = Number(price);
if (castingId <= 0) {
lk.prependNotifyInfo('⚠️请设置产品品类');
hasNeedSendNotify = true;
} else if (price <= 0) {
lk.prependNotifyInfo('⚠️请设置监控价格');
hasNeedSendNotify = true;
} else {
let item = await refreshLstOnSale(castingId, price);
if (item) {
hasNeedSendNotify = await checkToBuy(item);
} else {
hasNeedSendNotify = false;
}
}
}
if (hasNeedSendNotify) {
lk.msg(``);
}
lk.done();
}
function refreshLstOnSale(castingId, price) {
return new Promise((resolve, _reject) => {
try {
const headers = GCommonGandartHeads;
headers.Host = "api2.gandart.com";
let signData = getSign();
signData.castingId = castingId;
signData.page = 1;
signData.pageSize = 15;
signData.sort = 2;// 1=编号,2=价格
signData.transactionStatus = 2;
let body = objToUrlParams(signData);
let url = {
url: `${config.RESALE_API_V2}/resaleManage/resale/onSale`,
headers: headers,
body: body
};
let collectionName = getCollectionNameById(castingId)
lk.log(`请求产品[${collectionName}(${castingId})]寄售列表:${body}`);
lk.post(url, async (error, _response, data) => {
let retItem;
try {
if (error) {
lk.log(`获取寄售列表信息发生错误`);
lk.execFail();
lk.appendNotifyInfo(`❌获取寄售列表失败,请稍后再试`);
} else {
let ret = JSON.parse(data);
let minPrice = 9999999;
if (ret.success) {
let obj = ret.obj;
let lst = obj.list;
for (let d of lst) {
if (d.transactionStatus == 2) {//2=可购买,4=支付中
const resalePrice = Number(d.resalePrice);
if (minPrice > resalePrice) {
minPrice = resalePrice;
}
if (price >= resalePrice) {
retItem = d;
lk.appendNotifyInfo(`🎉成功匹配产品[${d.collectionName}#${d.viewSort}],价格:${d.resalePrice}`);
break;
}
}
}
if (!retItem) {
lk.log(`无匹配的价格,当前[${collectionName}]最低价:${minPrice}`);
}
} else {
lk.execFail();
}
}
} catch (e) {
lk.log(`获取寄售列表信息失败`);
lk.logErr(e);
lk.execFail();
} finally {
resolve(retItem);
}
});
} catch (e) {
lk.log(`获取寄售列表信息发生错误`);
lk.logErr(e);
resolve();
}
});
}
function checkToBuy(item) {
return new Promise((resolve, _reject) => {
try {
const id = item.id;
const viewSort = item.viewSort || 0;
const headers = GCommonGandartHeads;
headers.Host = "api.gandart.com";
const body = `transactionRecordId=${id}`;
let url = {
url: `${config.BASE_API}/v2/resaleManage/resale/buy/v2`,
headers: headers,
body: body
};
lk.log(`请求购买产品[${item.collectionName}#${viewSort}]=${body}`);
// resolve(1);
const collectionName = item.collectionName;
lk.post(url, async (error, _response, data) => {
let retItem;
try {
if (error) {
lk.log(`无法下单产品[${collectionName}#${viewSort}]`);
lk.execFail();
lk.appendNotifyInfo(`❌购买失败,请稍后再试`);
} else {
lk.log(data);
let ret = JSON.parse(data);
if (ret.success) {
let obj = ret.obj;
let orderNum = obj.orderNum;
if (orderNum && orderNum.length > 0) {
retItem = ret;
lk.log(`成功下单产品[${obj.collectionName}#${viewSort}],订单号:${obj.orderNum}`);
lk.appendNotifyInfo(`🎉成功下单产品[${obj.collectionName}#${viewSort}],订单号:${obj.orderNum}`);
}
} else {
lk.log(`产品[${collectionName}#${viewSort}]下单失败`);
lk.execFail();
}
}
} catch (e) {
lk.log(`下单产品[${collectionName}#${viewSort}]发生错误`);
lk.logErr(e);
lk.execFail();
} finally {
resolve(retItem);
}
});
} catch (e) {
lk.log(`下单产品[${item.collectionName}#${item.viewSort}]发生错误`);
lk.logErr(e);
resolve();
}
});
}
function objToUrlParams(param, key, encode) {
let paramStr = urlEncode(param, key, encode);
let len = paramStr.length;
if (len > 0) {
paramStr = paramStr.substring(1, len);
}
return paramStr;
}
function urlEncode(param, key, encode) {
if (param == null) return '';
let paramStr = '';
let t = typeof (param);
if (t == 'string' || t == 'number' || t == 'boolean') {
paramStr += '&' + key + '=' + ((encode == null || encode) ? encodeURIComponent(param) : param);
} else {
for (let i in param) {
let k = key == null ? i : key + (param instanceof Array ? '[' + i + ']' : '.' + i);
paramStr += urlEncode(param[i], k, encode);
}
}
return paramStr;
}
function getSign() {
const now = new Date().getTime();
const s1 = now - 20000;
const s2 = now;
const s3 = now + 20000;
const s4 = now + 40000;
const sssfffeee = 'e9'; //localStorage.getItem('sssfffeee');
const aggaaa = '9'; //localStorage.getItem('aggaaa');
const yyhhhasdww = '0a';
let arr = [sssfffeee, yyhhhasdww, aggaaa, '29', 'e', 'c', 3];
let crypto = Crypto();
let s5 = crypto.md5(s3 + arr.join(''));
return {
's1': s1,
's2': s2,
's3': s3,
's4': s4,
's5': s5
};
}
// https://github.com/lowking/Scripts/blob/master/util/ToolKit.min.js
//ToolKit-start
function ToolKit(scriptName,scriptId,options){return new class{constructor(scriptName,scriptId,options){this.tgEscapeCharMapping={"&":"&","#":"#"},this.userAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.2 Safari/605.1.15",this.prefix="lk",this.name=scriptName,this.id=scriptId,this.data=null,this.dataFile=this.getRealPath(`${this.prefix}${this.id}.dat`),this.boxJsJsonFile=this.getRealPath(`${this.prefix}${this.id}.boxjs.json`),this.options=options,this.isExecComm=!1,this.isEnableLog=this.getVal(`${this.prefix}IsEnableLog${this.id}`),this.isEnableLog=!!this.isEmpty(this.isEnableLog)||JSON.parse(this.isEnableLog),this.isNotifyOnlyFail=this.getVal(`${this.prefix}NotifyOnlyFail${this.id}`),this.isNotifyOnlyFail=!this.isEmpty(this.isNotifyOnlyFail)&&JSON.parse(this.isNotifyOnlyFail),this.isEnableTgNotify=this.getVal(`${this.prefix}IsEnableTgNotify${this.id}`),this.isEnableTgNotify=!this.isEmpty(this.isEnableTgNotify)&&JSON.parse(this.isEnableTgNotify),this.tgNotifyUrl=this.getVal(`${this.prefix}TgNotifyUrl${this.id}`),this.isEnableTgNotify=this.isEnableTgNotify?!this.isEmpty(this.tgNotifyUrl):this.isEnableTgNotify,this.costTotalStringKey=`${this.prefix}CostTotalString${this.id}`,this.costTotalString=this.getVal(this.costTotalStringKey),this.costTotalString=this.isEmpty(this.costTotalString)?"0,0":this.costTotalString.replace('"',""),this.costTotalMs=this.costTotalString.split(",")[0],this.execCount=this.costTotalString.split(",")[1],this.costTotalMs=this.isEmpty(this.costTotalMs)?0:parseInt(this.costTotalMs),this.execCount=this.isEmpty(this.execCount)?0:parseInt(this.execCount),this.logSeparator="\n██",this.now=new Date,this.startTime=this.now.getTime(),this.node=(()=>{if(this.isNode()){const request=require("request");return{request:request}}return null})(),this.execStatus=!0,this.notifyInfo=[],this.log(`${this.name}, 开始执行!`),this.initCache(),this.execComm()}initCache(){const pKey=this.getPersistKey();if(this.isQuanX()&&(this.cache=JSON.parse($prefs.valueForKey(pKey)||"{}")),(this.isLoon()||isSurge)&&(this.cache=JSON.parse($persistentStore.read(pKey)||"{}")),this.isNode()){let fpath="root.json";this.node.fs.existsSync(fpath)||this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},err=>console.log(err)),this.root={},fpath=`${pKey}.json`,this.node.fs.existsSync(fpath)?this.cache=JSON.parse(this.node.fs.readFileSync(`${pKey}.json`)):(this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},err=>console.log(err)),this.cache={})}}getPersistKey(){return`private_${this.id}`}persistCache(){const pKey=this.getPersistKey(),data=JSON.stringify(this.cache,null,2);this.isQuanX()&&$prefs.setValueForKey(data,pKey),(this.isLoon()||this.isSurge())&&$persistentStore.write(data,pKey),this.isNode()&&(this.node.fs.writeFileSync(`${pKey}.json`,data,{flag:"w"},err=>console.log(err)),this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},err=>console.log(err)))}write(data,key){if(this.log(`SET ${key}`),-1!==key.indexOf("#")){if(key=key.substr(1),isSurge||this.isLoon())return $persistentStore.write(data,key);if(this.isQuanX())return $prefs.setValueForKey(data,key);this.isNode()&&(this.root[key]=data)}else this.cache[key]=data;this.persistCache()}read(key){return this.log(`READ ${key}`),-1===key.indexOf("#")?this.cache[key]:(key=key.substr(1),this.isSurge()||this.isLoon()?$persistentStore.read(key):this.isQuanX()?$prefs.valueForKey(key):this.isNode()?this.root[key]:void 0)}delete(key){if(this.log(`DELETE ${key}`),-1!==key.indexOf("#")){if(key=key.substr(1),this.isSurge()||this.isLoon())return $persistentStore.write(null,key);if(this.isQuanX())return $prefs.removeValueForKey(key);this.isNode()&&delete this.root[key]}else delete this.cache[key];this.persistCache()}getRealPath(fileName){if(this.isNode()){let targetPath=process.argv.slice(1,2)[0].split("/");return targetPath[targetPath.length-1]=fileName,targetPath.join("/")}return fileName}getUrlHost(url){return url.slice(0,url.indexOf("/",8))}getUrlPath(url){const end=url.lastIndexOf("/")===url.length-1?-1:void 0;return url.slice(url.indexOf("/",8),end)}async execComm(){if(this.isNode()){this.comm=process.argv.slice(1);let isHttpApiErr=!1;"p"==this.comm[1]&&(this.isExecComm=!0,this.log(`开始执行指令【${this.comm[1]}】=> 发送到手机测试脚本!`),this.isEmpty(this.options)||this.isEmpty(this.options.httpApi)?(this.log("未设置options,使用默认值"),this.isEmpty(this.options)&&(this.options={}),this.options.httpApi="ffff@10.0.0.9:6166"):/.*?@.*?:[0-9]+/.test(this.options.httpApi)||(isHttpApiErr=!0,this.log("❌httpApi格式错误!格式:ffff@3.3.3.18:6166"),this.done()),isHttpApiErr||this.callApi(this.comm[2]))}}callApi(timeout){let fname=this.comm[0];this.log(`获取【${fname}】内容传给手机`);let scriptStr="";this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const curDirDataFilePath=this.path.resolve(fname),rootDirDataFilePath=this.path.resolve(process.cwd(),fname),isCurDirDataFile=this.fs.existsSync(curDirDataFilePath),isRootDirDataFile=!isCurDirDataFile&&this.fs.existsSync(rootDirDataFilePath);if(isCurDirDataFile||isRootDirDataFile){const datPath=isCurDirDataFile?curDirDataFilePath:rootDirDataFilePath;try{scriptStr=this.fs.readFileSync(datPath)}catch(e){scriptStr=""}}else scriptStr="";let options={url:`http://${this.options.httpApi.split("@")[1]}/v1/scripting/evaluate`,headers:{"X-Key":`${this.options.httpApi.split("@")[0]}`},body:{script_text:`${scriptStr}`,mock_type:"cron",timeout:!this.isEmpty(timeout)&&timeout>5?timeout:5},json:!0};this.post(options,(_error,_response,_data)=>{this.log(`已将脚本【${fname}】发给手机!`),this.done()})}getCallerFileNameAndLine(){let error;try{throw Error("")}catch(err){error=err}const stack=error.stack,stackArr=stack.split("\n");let callerLogIndex=1;{const callerStackLine=stackArr[1];return this.path=this.path?this.path:require("path"),`[${callerStackLine.substring(callerStackLine.lastIndexOf(this.path.sep)+1,callerStackLine.lastIndexOf(":"))}]`}}getFunName(fun){var ret=fun.toString();return ret=(ret=ret.substr("function ".length)).substr(0,ret.indexOf("("))}boxJsJsonBuilder(info,param){if(this.isNode()){let boxjsJsonPath="/Users/lowking/Desktop/Scripts/lowking.boxjs.json";if(param&¶m.hasOwnProperty("target_boxjs_json_path")&&(boxjsJsonPath=param.target_boxjs_json_path),!this.fs.existsSync(boxjsJsonPath))return;if(!this.isJsonObject(info)||!this.isJsonObject(param))return void this.log("构建BoxJsJson传入参数格式错误,请传入json对象");this.log("using node");let needAppendKeys=["settings","keys"];const domain="https://raw.githubusercontent.com/Orz-3";let boxJsJson={},scritpUrl="#lk{script_url}";if(param&¶m.hasOwnProperty("script_url")&&(scritpUrl=this.isEmpty(param.script_url)?"#lk{script_url}":param.script_url),boxJsJson.id=`${this.prefix}${this.id}`,boxJsJson.name=this.name,boxJsJson.desc_html=`⚠️使用说明详情【点我查看】`,boxJsJson.icons=[`${domain}/mini/master/Alpha/${this.id.toLocaleLowerCase()}.png`,`${domain}/mini/master/Color/${this.id.toLocaleLowerCase()}.png`],boxJsJson.keys=[],boxJsJson.settings=[{id:`${this.prefix}IsEnableLog${this.id}`,name:"开启/关闭日志",val:!0,type:"boolean",desc:"默认开启"},{id:`${this.prefix}NotifyOnlyFail${this.id}`,name:"只当执行失败才通知",val:!1,type:"boolean",desc:"默认关闭"},{id:`${this.prefix}IsEnableTgNotify${this.id}`,name:"开启/关闭Telegram通知",val:!1,type:"boolean",desc:"默认关闭"},{id:`${this.prefix}TgNotifyUrl${this.id}`,name:"Telegram通知地址",val:"",type:"text",desc:"Tg的通知地址,如:https://api.telegram.org/bot-token/sendMessage?chat_id=-100140&parse_mode=Markdown&text="}],boxJsJson.author="#lk{author}",boxJsJson.repo="#lk{repo}",boxJsJson.script=`${scritpUrl}?raw=true`,!this.isEmpty(info))for(let i in needAppendKeys){let key=needAppendKeys[i];if(!this.isEmpty(info[key])){if("settings"===key)for(let i=0;i0){let apps=boxjsJson.apps,targetIdx=apps.indexOf(apps.filter(app=>app.id==boxJsJson.id)[0]);targetIdx>=0?boxjsJson.apps[targetIdx]=boxJsJson:boxjsJson.apps.push(boxJsJson);let ret=JSON.stringify(boxjsJson,null,2);if(!this.isEmpty(param))for(const key in param){let val="";param.hasOwnProperty(key)?val=param[key]:"author"===key?val="@lowking":"repo"===key&&(val="https://github.com/lowking/Scripts"),ret=ret.replace(`#lk{${key}}`,val)}const regex=/(?:#lk\{)(.+?)(?=\})/;let m=regex.exec(ret);null!==m&&this.log("生成BoxJs还有未配置的参数,请参考https://github.com/lowking/Scripts/blob/master/util/example/ToolKitDemo.js#L17-L18传入参数:\n");let loseParamSet=new Set;for(;null!==(m=regex.exec(ret));)loseParamSet.add(m[1]),ret=ret.replace(`#lk{${m[1]}}`,"");loseParamSet.forEach(p=>{console.log(`${p} `)}),this.fs.writeFileSync(boxjsJsonPath,ret)}}}}isJsonObject(obj){return"object"==typeof obj&&"[object object]"==Object.prototype.toString.call(obj).toLowerCase()&&!obj.length}appendNotifyInfo(info,type){1==type?this.notifyInfo=info:this.notifyInfo.push(info)}prependNotifyInfo(info){this.notifyInfo.splice(0,0,info)}execFail(){this.execStatus=!1}isRequest(){return"undefined"!=typeof $request}isSurge(){return"undefined"!=typeof $httpClient}isQuanX(){return"undefined"!=typeof $task}isLoon(){return"undefined"!=typeof $loon}isJSBox(){return"undefined"!=typeof $app&&"undefined"!=typeof $http}isStash(){return"undefined"!=typeof $environment&&$environment["stash-version"]}isNode(){return"function"==typeof require&&!this.isJSBox()}sleep(time){return new Promise(resolve=>setTimeout(resolve,time))}log(message){this.isEnableLog&&console.log(`${this.logSeparator}${message}`)}logErr(message){this.execStatus=!0,this.isEnableLog&&(console.log(`${this.logSeparator}${this.name}执行异常:`),console.log(message),console.log(`\n${message.message}`))}msg(subtitle,message,openUrl,mediaUrl){if(!this.isRequest()&&this.isNotifyOnlyFail&&this.execStatus);else if(this.isEmpty(message)&&(message=Array.isArray(this.notifyInfo)?this.notifyInfo.join("\n"):this.notifyInfo),!this.isEmpty(message))if(this.isEnableTgNotify){this.log(`${this.name}Tg通知开始`);for(let key in this.tgEscapeCharMapping)this.tgEscapeCharMapping.hasOwnProperty(key)&&(message=message.replace(key,this.tgEscapeCharMapping[key]));this.get({url:encodeURI(`${this.tgNotifyUrl}📌${this.name}\n${message}`)},(_error,_statusCode,_body)=>{this.log("Tg通知完毕")})}else{let options={};const hasOpenUrl=!this.isEmpty(openUrl),hasMediaUrl=!this.isEmpty(mediaUrl);this.isQuanX()&&(hasOpenUrl&&(options["open-url"]=openUrl),hasMediaUrl&&(options["media-url"]=mediaUrl),$notify(this.name,subtitle,message,options)),(this.isSurge()||this.isStash())&&(hasOpenUrl&&(options.url=openUrl),$notification.post(this.name,subtitle,message,options)),this.isNode()&&this.log("⭐️"+this.name+"\n"+subtitle+"\n"+message),this.isJSBox()&&$push.schedule({title:this.name,body:subtitle?subtitle+"\n"+message:message})}}getVal(key,defaultValue=""){let value;return this.isSurge()||this.isLoon()||this.isStash()?value=$persistentStore.read(key):this.isQuanX()?value=$prefs.valueForKey(key):this.isNode()?(this.data=this.loadData(),value=process.env[key]||this.data[key]):value=this.data&&this.data[key]||null,value||defaultValue}setVal(key,val){return this.isSurge()||this.isLoon()||this.isStash()?$persistentStore.write(val,key):this.isQuanX()?$prefs.setValueForKey(val,key):this.isNode()?(this.data=this.loadData(),this.data[key]=val,this.writeData(),!0):this.data&&this.data[key]||null}loadData(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const curDirDataFilePath=this.path.resolve(this.dataFile),rootDirDataFilePath=this.path.resolve(process.cwd(),this.dataFile),isCurDirDataFile=this.fs.existsSync(curDirDataFilePath),isRootDirDataFile=!isCurDirDataFile&&this.fs.existsSync(rootDirDataFilePath);if(!isCurDirDataFile&&!isRootDirDataFile)return{};{const datPath=isCurDirDataFile?curDirDataFilePath:rootDirDataFilePath;try{return JSON.parse(this.fs.readFileSync(datPath))}catch(e){return{}}}}}writeData(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const curDirDataFilePath=this.path.resolve(this.dataFile),rootDirDataFilePath=this.path.resolve(process.cwd(),this.dataFile),isCurDirDataFile=this.fs.existsSync(curDirDataFilePath),isRootDirDataFile=!isCurDirDataFile&&this.fs.existsSync(rootDirDataFilePath),jsondata=JSON.stringify(this.data);isCurDirDataFile?this.fs.writeFileSync(curDirDataFilePath,jsondata):isRootDirDataFile?this.fs.writeFileSync(rootDirDataFilePath,jsondata):this.fs.writeFileSync(curDirDataFilePath,jsondata)}}adapterStatus(response){return response&&(response.status?response.statusCode=response.status:response.statusCode&&(response.status=response.statusCode)),response}get(options,callback=(()=>{})){this.isQuanX()&&("string"==typeof options&&(options={url:options}),options.method="GET",$task.fetch(options).then(response=>{callback(null,this.adapterStatus(response),response.body)},reason=>callback(reason.error,null,null))),(this.isSurge()||this.isLoon()||this.isStash())&&$httpClient.get(options,(error,response,body)=>{callback(error,this.adapterStatus(response),body)}),this.isNode()&&this.node.request(options,(error,response,body)=>{callback(error,this.adapterStatus(response),body)}),this.isJSBox()&&("string"==typeof options&&(options={url:options}),options.header=options.headers,options.handler=function(resp){let error=resp.error;error&&(error=JSON.stringify(resp.error));let body=resp.data;"object"==typeof body&&(body=JSON.stringify(resp.data)),callback(error,this.adapterStatus(resp.response),body)},$http.get(options))}post(options,callback=(()=>{})){this.isQuanX()&&("string"==typeof options&&(options={url:options}),options.method="POST",$task.fetch(options).then(response=>{callback(null,this.adapterStatus(response),response.body)},reason=>callback(reason.error,null,null))),(this.isSurge()||this.isLoon()||this.isStash())&&$httpClient.post(options,(error,response,body)=>{callback(error,this.adapterStatus(response),body)}),this.isNode()&&this.node.request.post(options,(error,response,body)=>{callback(error,this.adapterStatus(response),body)}),this.isJSBox()&&("string"==typeof options&&(options={url:options}),options.header=options.headers,options.handler=function(resp){let error=resp.error;error&&(error=JSON.stringify(resp.error));let body=resp.data;"object"==typeof body&&(body=JSON.stringify(resp.data)),callback(error,this.adapterStatus(resp.response),body)},$http.post(options))}put(options,callback=(()=>{})){this.isQuanX()&&("string"==typeof options&&(options={url:options}),options.method="PUT",$task.fetch(options).then(response=>{callback(null,this.adapterStatus(response),response.body)},reason=>callback(reason.error,null,null))),(this.isSurge()||this.isLoon()||this.isStash())&&(options.method="PUT",$httpClient.put(options,(error,response,body)=>{callback(error,this.adapterStatus(response),body)})),this.isNode()&&(options.method="PUT",this.node.request.put(options,(error,response,body)=>{callback(error,this.adapterStatus(response),body)})),this.isJSBox()&&("string"==typeof options&&(options={url:options}),options.header=options.headers,options.handler=function(resp){let error=resp.error;error&&(error=JSON.stringify(resp.error));let body=resp.data;"object"==typeof body&&(body=JSON.stringify(resp.data)),callback(error,this.adapterStatus(resp.response),body)},$http.post(options))}costTime(){let info=`${this.name}执行完毕!`;this.isNode()&&this.isExecComm&&(info=`指令【${this.comm[1]}】执行完毕!`);const endTime=(new Date).getTime(),ms=endTime-this.startTime,costTime=ms/1e3;this.execCount++,this.costTotalMs+=ms,this.log(`${info}耗时【${costTime}】秒\n总共执行【${this.execCount}】次,平均耗时【${(this.costTotalMs/this.execCount/1e3).toFixed(4)}】秒`),this.setVal(this.costTotalStringKey,JSON.stringify(`${this.costTotalMs},${this.execCount}`))}done(value={}){this.costTime(),(this.isSurge()||this.isQuanX()||this.isLoon()||this.isStash())&&$done(value)}getRequestUrl(){return $request.url}getResponseBody(){return $response.body}isGetCookie(reg){return!("OPTIONS"==$request.method||!this.getRequestUrl().match(reg))}isEmpty(obj){return void 0===obj||null==obj||""==obj||"null"==obj||"undefined"==obj||0===obj.length}randomString(len){len=len||32;var $chars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890",maxPos=$chars.length,pwd="";for(let i=0;i>> 32 - u, r) } function c(n, t, r, e, u, o, c) { return f(t & r | ~t & e, n, t, u, o, c) } function i(n, t, r, e, u, o, c) { return f(t & e | r & ~e, n, t, u, o, c) } function l(n, t, r, e, u, o, c) { return f(t ^ r ^ e, n, t, u, o, c) } function a(n, t, r, e, u, o, c) { return f(r ^ (t | ~e), n, t, u, o, c) } function t(n) { /[\x80-\xFF]/.test(n) && (n = unescape(encodeURI(n))), txt = ""; let t = n.length, r = [1732584193, -271733879, -1732584194, 271733878], e; for (e = 64; e <= n.length; e += 64)o(r, function (n) { let t = [], r; for (r = 0; r < 64; r += 4)t[r >> 2] = n.charCodeAt(r) + (n.charCodeAt(r + 1) << 8) + (n.charCodeAt(r + 2) << 16) + (n.charCodeAt(r + 3) << 24); return t }(n.substring(e - 64, e))); n = n.substring(e - 64); var u = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for (e = 0; e < n.length; e++)u[e >> 2] |= n.charCodeAt(e) << (e % 4 << 3); if (u[e >> 2] |= 128 << (e % 4 << 3), 55 < e) for (o(r, u), e = 0; e < 16; e++)u[e] = 0; return u[14] = 8 * t, o(r, u), r } let e = "0123456789abcdef".split(""); function r(t) { for (let n = 0; n < t.length; n++)t[n] = function (n) { let t = "", r = 0; for (; r < 4; r++)t += e[n >> 8 * r + 4 & 15] + e[n >> 8 * r & 15]; return t }(t[n]); return t.join("") } function h(n, t) { return n + t & 4294967295 } return { md5: function (n) { return r(t(n)) } } }
//Crypto-end