/*
Bing积分-lowking-v2.3.5
⚠️只测试过surge没有其他app自行测试
1.3.4版本的速度更新,不然第二天无法重置执行状态,导致无法做任务
记得到boxjs里面设置每日任务重置时间,不设置默认每天早上8点
************************
Surge 4.2.0+ 脚本配置(其他APP自行转换配置):
************************
[Script]
# > Bing积分
Bing积分cookie = requires-body=0,type=http-request,pattern=https:\/\/rewards\.bing\.com,script-path=https://raw.githubusercontent.com/lowking/Scripts/master/bing/bingPoint.js
Bing积分 = type=cron,cronexp="0 10 0 * * ?",wake-system=1,script-path=https://raw.githubusercontent.com/lowking/Scripts/master/bing/bingPoint.js
[MITM]
hostname = %APPEND% rewards.bing.com
*/
const lk = new ToolKit(`Bing积分`, `BingPoint`, {"httpApi": "ffff@10.0.0.19:6166"})
const scriptTimeout = 30
const bingPointCookieKey = 'bingPointCookieKey'
const bingSearchCookieKey = 'bingSearchCookieKey'
const bingSearchCookieMobileKey = 'bingSearchCookieMobileKey'
const searchRepeatKey = "bingSearchRepeatKey"
const searchRepeatMobileKey = "searchRepeatMobileKey"
const searchRepeatEdgeKey = "searchRepeatEdgeKey"
const searchPcCountKey = "bingSearchPcCountKey"
const searchPcAmountKey = "searchPcAmountKey"
const searchMobileCountKey = "bingSearchMobileCountKey"
const searchMobileAmountKey = "searchMobileAmountKey"
const searchEdgeCountKey = "bingSearchEdgeCountKey"
const searchEdgeAmountKey = "searchEdgeAmountKey"
const bingCachePointKey = "bingCachePointKey"
const bingIsContinueWhenZeroKey = "bingIsContinueWhenZeroKey"
const bingResetHoursKey = "bingResetHoursKey"
let bingPointHeader
let bingPointCookie = lk.getVal(bingPointCookieKey)
let bingSearchCookie = lk.getVal(bingSearchCookieKey)
let bingSearchMobileCookie = lk.getVal(bingSearchCookieMobileKey)
let isSearchRepeat = lk.getVal(searchRepeatKey)
let isSearchMobileRepeat = lk.getVal(searchRepeatMobileKey)
let isSearchEdgeRepeat = lk.getVal(searchRepeatEdgeKey)
let searchPcCount = lk.getVal(searchPcCountKey, 0)
let searchPcAmount = lk.getVal(searchPcAmountKey, 10)
let searchMobileCount = lk.getVal(searchMobileCountKey, 0)
let searchMobileAmount = lk.getVal(searchMobileAmountKey, 10)
let searchEdgeCount = lk.getVal(searchEdgeCountKey, 0)
let searchEdgeAmount = lk.getVal(searchEdgeAmountKey, 10)
let cachePoint = lk.getVal(bingCachePointKey, 0)
let isContinueWhenZero = lk.getVal(bingIsContinueWhenZeroKey, 1)
let bingResetHours = lk.getVal(bingResetHoursKey, 8)
let isAlreadySearchPc = false, isAlreadySearchMobile = false, isAlreadySearchEdge = false
let nowString = lk.formatDate(new Date(), 'yyyyMMdd')
if(!lk.isExecComm) {
if (lk.isRequest()) {
getCookie()
lk.done()
} else {
lk.boxJsJsonBuilder({
"icons": [
"https://raw.githubusercontent.com/lowking/Scripts/master/doc/icon/bingPoint.png",
"https://raw.githubusercontent.com/lowking/Scripts/master/doc/icon/bingPoint.png"
],
"settings": [
{
"id": bingResetHoursKey,
"name": "Bing每日任务重置时间",
"val": 8,
"type": "number",
"desc": "写小时数,默认:8"
},
{
"id": bingPointCookieKey,
"name": "Bing积分cookie",
"val": "",
"type": "text",
"desc": "Bing积分cookie"
},
{
"id": bingSearchCookieMobileKey,
"name": "Bing每日搜索cookie(移动端)",
"val": "",
"type": "text",
"desc": "请使用手机打开https://cn.bing.com/search?q=test抓去对应请求的cookie"
},
{
"id": searchMobileAmountKey,
"name": "Bing每日执行搜索(移动端)次数",
"val": 10,
"type": "number",
"desc": "Bing每日执行搜索(移动端)次数"
},
{
"id": bingSearchCookieKey,
"name": "Bing每日搜索cookie(PC)",
"val": "",
"type": "text",
"desc": "请使用电脑打开https://cn.bing.com/search?q=test抓去对应请求的cookie"
},
{
"id": searchPcAmountKey,
"name": "Bing每日执行搜索(PC)次数",
"val": 10,
"type": "number",
"desc": "Bing每日执行搜索(PC)次数"
},
{
"id": searchEdgeAmountKey,
"name": "Bing每日执行搜索(Edge)次数",
"val": 10,
"type": "number",
"desc": "Bing每日执行搜索(Edge)次数"
}
],
"keys": [bingPointCookieKey],
"script_timeout": scriptTimeout
}, {
"script_url": "https://github.com/lowking/Scripts/blob/master/bing/bingPoint.js",
"author": "@lowking",
"repo": "https://github.com/lowking/Scripts",
})
all()
}
}
function getCookie() {
if (lk.isMatch(/\/rewards\.bing\.com/)) {
lk.log(`开始获取cookie`)
let headers = Object.keys($request.headers).reduce((obj, key) => {
obj[key.toLowerCase()] = $request.headers[key]
return obj
}, {})
try {
const bingHeader = headers.cookie.s()
if (!!bingHeader) {
lk.setVal(bingPointCookieKey, bingHeader)
lk.appendNotifyInfo('🎉成功获取cookie,可以关闭相应脚本')
}
} catch (e) {
lk.execFail()
lk.appendNotifyInfo('❌获取bing cookie失败')
}
}
lk.msg(``)
lk.done()
}
async function dealMsg(dashBoard, newPoint) {
return new Promise((resolve, _reject) => {
let availablePoints = dashBoard?.dashboard?.userStatus?.availablePoints || "-"
if (availablePoints != "-" && cachePoint) {
lk.setVal(bingCachePointKey, availablePoints.s())
let increaseAmount = availablePoints - cachePoint
lk.prependNotifyInfo(`本次执行:${increaseAmount >= 0 ? "+" + increaseAmount : increaseAmount}`)
lk.setVal(bingIsContinueWhenZeroKey, (increaseAmount + newPoint).s())
}
resolve(`当前积分:${availablePoints}${newPoint > 0 ? "+" + newPoint : ""} 日常获得:${dashBoard?.dashboard?.userStatus?.counters?.dailyPoint[0]?.pointProgress || "-"}/${dashBoard?.dashboard?.userStatus?.counters?.dailyPoint[0]?.pointProgressMax || "-"}`)
})
}
async function all() {
// 每天任务重置时间到了之后,允许执行
let isReset = lk.now.getHours() == bingResetHours
if (isReset) {
searchPcCount = 0
searchMobileCount = 0
searchEdgeCount = 0
}
if (!isReset && isContinueWhenZero <= 0) {
lk.done()
return
}
let msg = ``
if (bingPointCookie == '') {
lk.execFail()
lk.appendNotifyInfo(`⚠️请先打开rewards.bing.com获取cookie`)
} else {
bingPointHeader = {}
bingPointHeader["authority"] = 'rewards.bing.com'
bingPointHeader["accept"] = 'application/json, text/javascript, */*; q=0.01'
bingPointHeader["accept-language"] = 'zh-CN,zh;q=0.9'
bingPointHeader["cookie"] = bingPointCookie
bingPointHeader["correlation-context"] = 'v=1,ms.b.tel.market=zh-CN'
bingPointHeader["dnt"] = '1'
bingPointHeader["referer"] = 'https://rewards.bing.com/redeem/000899036002'
bingPointHeader["sec-ch-ua"] = '"Chromium";v="111", "Not(A:Brand";v="8"'
bingPointHeader["sec-ch-ua-arch"] = '"x86"'
bingPointHeader["sec-ch-ua-bitness"] = '"64"'
bingPointHeader["sec-ch-ua-full-version"] = '"111.0.5563.64"'
bingPointHeader["sec-ch-ua-mobile"] = '?0'
bingPointHeader["sec-ch-ua-platform"] = '"macOS"'
bingPointHeader["sec-ch-ua-platform-version"] = '13.2.0'
bingPointHeader["sec-fetch-dest"] = 'document'
bingPointHeader["sec-fetch-mode"] = 'navigate'
bingPointHeader["sec-fetch-site"] = 'none'
bingPointHeader["user-agent"] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36'
if (bingSearchCookie != '') {
await searchPc()
await lk.sleep(5000)
await searchEdge()
}
await lk.sleep(5000)
if (bingSearchMobileCookie != '') {
await searchMobile()
}
await lk.sleep(2000)
let dashBoard = await getDashBoard()
if (dashBoard?.dashboard) {
let newPoint = await reportAct(dashBoard)
msg = await dealMsg(dashBoard, newPoint)
} else {
lk.appendNotifyInfo("❌未获取到活动信息")
}
}
if (!lk.isNode()) {
lk.log(lk.notifyInfo.join("\n"))
}
lk.msg(msg)
lk.done()
}
function doReportActForQuiz(title, item, rvt) {
return new Promise((resolve, _reject) => {
// todo 预留方法,目前官网手动都做不了都任务🤣
const t = '做问答奖励任务:' + title
lk.log(t)
let ret = 0
let url = {
url: `https://rewards.bing.com/api/reportactivity?X-Requested-With=XMLHttpRequest&_=${lk.startTime}`,
headers: bingPointHeader,
body: `id=${item.name}&hash=${item.hash}&timeZone=480&activityAmount=1&__RequestVerificationToken=${rvt}`
}
lk.log(url.s())
lk.log(item.s())
lk.post(url, (error, _response, data) => {
try {
if (error) {
lk.execFail()
lk.log(error)
lk.appendNotifyInfo(`❌${t}失败,请稍后再试`)
} else {
// {"activity":{"id":"3484a93d-db98-490f-998e-10e64e481de7","points":10,"quantity":1,"timestamp":"2023-03-01T22:22:39.5968778+08:00","activityType":11,"channel":"","activitySubtype":"","currencyCode":"","purchasePrice":0.0,"orderId":""},"balance":157}
lk.log(data)
data = data.o()
if (data?.activity?.points) {
ret = 1
}
}
} catch (e) {
lk.logErr(e)
lk.log(`bing返回数据:${data}`)
lk.execFail()
lk.appendNotifyInfo(`❌${t}错误,请稍后再试`)
} finally {
resolve(ret)
}
})
})
}
function doReportActForUrlreward(title, item, rvt) {
return new Promise((resolve, _reject) => {
const t = '做url奖励任务:' + title
lk.log(t)
let ret = 0
let url = {
url: `https://rewards.bing.com/api/reportactivity?X-Requested-With=XMLHttpRequest&_=${lk.startTime}`,
headers: bingPointHeader,
body: `id=${item.name}&hash=${item.hash}&timeZone=480&activityAmount=1&__RequestVerificationToken=${rvt}`
}
lk.log(url.s())
lk.log(item.s())
lk.post(url, (error, _response, data) => {
try {
if (error) {
lk.execFail()
lk.log(error)
lk.appendNotifyInfo(`❌${t}失败,请稍后再试`)
} else {
// {"activity":{"id":"3484a93d-db98-490f-998e-10e64e481de7","points":10,"quantity":1,"timestamp":"2023-03-01T22:22:39.5968778+08:00","activityType":11,"channel":"","activitySubtype":"","currencyCode":"","purchasePrice":0.0,"orderId":""},"balance":157}
lk.log(data)
data = data.o()
if (data?.activity?.points) {
ret = 1
}
}
} catch (e) {
lk.logErr(e)
lk.log(`bing返回数据:${data}`)
lk.execFail()
lk.appendNotifyInfo(`❌${t}错误,请稍后再试`)
} finally {
resolve(ret)
}
})
})
}
function searchEdge() {
return new Promise(async (resolve, _reject) => {
lk.log(`开始执行每日搜索(Edge)`)
let isAlwaysSearch = searchEdgeCount == -1
if (isAlwaysSearch) {
// 总是搜索的话,赋值为0,搜索次数设置为1
searchEdgeCount = 0
searchEdgeAmount = 1
}
if (!isAlwaysSearch && nowString == isSearchEdgeRepeat && searchEdgeCount >= searchEdgeAmount) {
lk.log(`今日搜索(Edge)已达配置上限:${searchEdgeAmount}次`)
isAlreadySearchEdge = true
resolve()
return
}
let h = bingPointHeader.s().o()
if (nowString != isSearchEdgeRepeat || searchEdgeCount < searchEdgeAmount) {
for (let i = searchEdgeCount; i < searchEdgeAmount; i++) {
h["authority"] = "cn.bing.com"
h["upgrade-insecure-requests"] = "1"
h["accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"
h["user-agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.63"
h["sec-fetch-site"] = "none"
h["sec-fetch-mode"] = "navigate"
h["sec-fetch-user"] = "?1"
h["sec-fetch-dest"] = "document"
h["sec-fetch-dest"] = "document"
h["sec-ch-ua-full-version-list"] = "Not A(Brand;v=24.0.0.0, Chromium;v=110.0.5481.177"
h["accept-encoding"] = "UTF-8"
h["Content-Encoding"] = "UTF-8"
h["cookie"] = bingSearchCookie
let url = {
url: `https://www.bing.com/search?q=${lk.randomString(10)}`,
headers: h,
gzip: true
}
lk.get(url, (error, _response, data) => {
++searchEdgeCount
})
}
while (searchEdgeCount < searchEdgeAmount) {
lk.log(`waiting`)
await lk.sleep(200)
}
try {
if (!isAlwaysSearch) {
lk.log(`保存今天(${nowString})搜索(Edge)次数:${searchEdgeCount}`)
lk.setVal(searchEdgeCountKey, searchEdgeCount.s())
}
lk.setVal(searchRepeatKey, nowString)
} catch (e) {
lk.logErr(e)
}
resolve()
} else {
resolve()
}
})
}
function searchMobile() {
return new Promise(async (resolve, _reject) => {
lk.log(`开始执行每日搜索(移动端)`)
let isAlwaysSearch = searchMobileCount == -1
if (isAlwaysSearch) {
// 总是搜索的话,赋值为0,搜索次数设置为1
searchMobileCount = 0
searchMobileAmount = 1
}
if (!isAlwaysSearch && nowString == isSearchMobileRepeat && searchMobileCount >= searchMobileAmount) {
lk.log(`今日搜索(移动端)已达配置上限:${searchMobileAmount}次`)
isAlreadySearchMobile = true
resolve()
return
}
let h = bingPointHeader.s().o()
if (nowString != isSearchMobileRepeat || searchMobileCount < searchMobileAmount) {
for (let i = searchMobileCount; i < searchMobileAmount; i++) {
h["authority"] = "cn.bing.com"
h["accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
h["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"
h["accept-language"] = "zh-CN,zh-Hans;q=0.9"
h["referer"] = "https://cn.bing.com/"
h["accept-encoding"] = "UTF-8"
h["Content-Encoding"] = "UTF-8"
h["cookie"] = bingSearchMobileCookie
let searchWord = lk.randomString(10)
let url = {
url: `https://cn.bing.com/search?q=${searchWord}&search=&form=QBLH&sp=-1&lq=0&pq=${searchWord}&sc=8-2&qs=n&sk=&ghsh=0&ghacc=0&ghpl=`,
headers: h,
gzip: true
}
lk.get(url, (error, _response, data) => {
++searchMobileCount
})
}
while (searchMobileCount < searchMobileAmount) {
lk.log(`waiting`)
await lk.sleep(200)
}
try {
if (!isAlwaysSearch) {
lk.log(`保存今天(${nowString})搜索(移动端)次数:${searchMobileCount}`)
lk.setVal(searchMobileCountKey, searchMobileCount.s())
}
lk.setVal(searchRepeatMobileKey, nowString)
} catch (e) {
lk.logErr(e)
}
resolve()
} else {
resolve()
}
})
}
function searchPc() {
return new Promise(async (resolve, _reject) => {
lk.log(`开始执行每日搜索(PC)`)
let isAlwaysSearch = searchPcCount == -1
if (isAlwaysSearch) {
// 总是搜索的话,赋值为0,搜索次数设置为1
searchPcCount = 0
searchPcAmount = 1
}
if (!isAlwaysSearch && nowString == isSearchRepeat && searchPcCount >= searchPcAmount) {
lk.log(`今日搜索(PC)已达配置上限:${searchPcAmount}次`)
isAlreadySearchPc = true
resolve()
return
}
let h = bingPointHeader.s().o()
if (nowString != isSearchRepeat || searchPcCount < searchPcAmount) {
for (let i = searchPcCount; i < searchPcAmount; i++) {
h["authority"] = "cn.bing.com"
h["upgrade-insecure-requests"] = "1"
h["accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"
h["sec-fetch-site"] = "none"
h["sec-fetch-mode"] = "navigate"
h["sec-fetch-user"] = "?1"
h["sec-fetch-dest"] = "document"
h["sec-fetch-dest"] = "document"
h["sec-ch-ua-full-version-list"] = "Not A(Brand;v=24.0.0.0, Chromium;v=110.0.5481.177"
h["accept-encoding"] = "UTF-8"
h["Content-Encoding"] = "UTF-8"
h["cookie"] = bingSearchCookie
let url = {
url: `https://www.bing.com/search?q=${lk.randomString(10)}`,
headers: h,
gzip: true
}
lk.get(url, (error, _response, data) => {
++searchPcCount
})
}
while (searchPcCount < searchPcAmount) {
lk.log(`waiting`)
await lk.sleep(200)
}
try {
if (!isAlwaysSearch) {
lk.log(`保存今天(${nowString})搜索(PC)次数:${searchPcCount}`)
lk.setVal(searchPcCountKey, searchPcCount.s())
}
lk.setVal(searchRepeatKey, nowString)
} catch (e) {
lk.logErr(e)
}
resolve()
} else {
resolve()
}
})
}
function reportAct(dashBoard) {
return new Promise(async (resolve, _reject) => {
let newPoint = 0
let promotionalItem, morePromotions
morePromotions = dashBoard?.dashboard?.morePromotions || []
if ((promotionalItem = dashBoard?.dashboard?.promotionalItem)) {
morePromotions.push(promotionalItem)
}
// lk.log(morePromotions.s())
if (morePromotions.length > 0) {
let todoCount = 0, sucCount = 0, failCount = 0, completeCount = 0, completePoint = 0
morePromotions.forEach(_ = async (item) => {
let title = item?.attributes?.title
let point = item?.pointProgressMax
let type = item?.attributes?.type
if (item?.complete == false) {
if (point > 0) {
let ret = 0
let b = true || title == "Rewa rds 挑戰"
lk.log(`开始任务:${title}【${point}】\n${type}\n${b}`)
if (b) {
if (type === "urlreward") {
ret = await doReportActForUrlreward(title, item, dashBoard?.rvt)
} else if (type === "quiz") {
ret = -1 // await doReportActForQuiz(title, item, dashBoard?.rvt)
} else {
ret = -2
}
}
todoCount++
if (ret === 1) {
lk.appendNotifyInfo(`🎉${title}【${point}】`)
sucCount++
completePoint += point
newPoint += point
} else {
failCount++
lk.execFail()
if (ret === 0) {
lk.appendNotifyInfo(`❌${title}【${point}】`)
} else {
failCount--
lk.log(`⎌${title}【${point}】`)
}
}
} else {
todoCount++
}
} else {
completeCount++
completePoint += point
lk.appendNotifyInfo(`✓${title}【${point}】`)
}
})
let err = ""
let totalCount = sucCount + failCount
while (true) {
lk.log(`total: ${morePromotions.length}, suc: ${sucCount}, fail: ${failCount}, complete: ${completeCount}, todo:${todoCount}`)
if (todoCount + completeCount >= morePromotions.length) {
lk.log(`任务都做完了,退出`)
err = `🎉任务都做完啦,共获得${completePoint}积分`
break
}
if (new Date().getTime() - lk.startTime > scriptTimeout * 1000) {
lk.log(`执行超时,强制退出`)
err = "❌执行超时,强制退出(请添加分流切换节点)"
break
}
await lk.sleep(100)
totalCount = sucCount + failCount
}
if (!err) {
if (totalCount > 0) {
lk.execFail()
lk.prependNotifyInfo(`🎉成功:${sucCount}个,❌失败:${failCount}个`)
} else {
lk.appendNotifyInfo(`🎉今天的任务都做完啦`)
}
} else {
lk.prependNotifyInfo(err)
lk.prependNotifyInfo(`🎉:${sucCount}个,❌:${failCount}个,今日已完成:${completeCount}个`)
}
resolve(newPoint)
} else {
lk.execFail()
lk.prependNotifyInfo(`❌未获取到活动信息`)
resolve(newPoint)
}
})
}
function getDashBoard() {
return new Promise((resolve, _reject) => {
const t = '获取面板信息'
lk.log(`开始${t}`)
let url = {
url: `https://rewards.bing.com/?_=${lk.startTime}`,
headers: bingPointHeader,
}
lk.get(url, (error, _response, data) => {
try {
if (error) {
lk.execFail()
lk.appendNotifyInfo(`❌${t}失败,请稍后再试`)
resolve({})
} else {
let rvt = data.split("__RequestVerificationToken")[1].split("value=\"")[1].split("\"")[0]
url.url = `https://rewards.bing.com/api/getuserinfo?type=1&X-Requested-With=XMLHttpRequest&_=${lk.startTime}`
let dashboard = data.split("var dashboard = ")[1].split("\n")[0].slice(0, -2).o()
// 和上面网页返回截取的结构一样
// lk.get(url, (error, _response, data) => {
// if (error) {
// lk.execFail()
// lk.appendNotifyInfo(`❌${t}失败,请稍后再试`)
// resolve({})
// } else {
// lk.log(dashboard.s())
// dashboard = data.o()?.dashboard
// lk.log(dashboard.s())
// let dataObj = {
// dashboard,
// rvt
// }
// resolve(dataObj)
// }
// })
let dataObj = {
dashboard,
rvt
}
resolve(dataObj)
}
} catch (e) {
lk.logErr(e)
lk.log(`bing返回数据:${data}\n${error}\n${_response.s()}`)
lk.execFail()
lk.appendNotifyInfo(`❌${t}错误,请稍后再试,或者cookie过期,请重新抓取`)
resolve({})
}
})
})
}
// * ToolKit v1.5.0 build 204
function ToolKit(scriptName,scriptId,options){class Request{constructor(tk){this.tk=tk}fetch(options,method="GET"){options=typeof options=="string"?{url:options}:options;let fetcher;switch(method){case"PUT":fetcher=this.put;break;case"POST":fetcher=this.post;break;default:fetcher=this.get}const doFetch=new Promise((resolve,reject)=>{fetcher.call(this,options,(error,resp,data)=>error?reject({error,resp,data}):resolve({error,resp,data}))}),delayFetch=(promise,timeout=5e3)=>Promise.race([promise,new Promise((_,reject)=>setTimeout(()=>reject(new Error("请求超时")),timeout))]);return options.timeout>0?delayFetch(doFetch,options.timeout):doFetch}async get(options){return this.fetch.call(this.tk,options)}async post(options){return this.fetch.call(this.tk,options,"POST")}async put(options){return this.fetch.call(this.tk,options,"PUT")}}return new class{ab={info:1<<1,warn:1<<2,error:1<<3,debug:1<<4};aa={info:1<<1,warn:1<<2,error:1<<3,debug:1<<4};constructor(scriptName,scriptId,options){Object.prototype.s=function(replacer,space){return typeof this=="string"?this:JSON.stringify(this,replacer,space)},Object.prototype.o=function(reviver){return JSON.parse(this,reviver)},Object.prototype.getIgnoreCase=function(key){if(!key)throw"Key required";let target=this;try{typeof this=="string"&&(target=JSON.stringify(this))}catch{throw"It's not a JSON object or string!"}const ret=Object.keys(target).reduce((obj,key)=>(obj[key.toLowerCase()]=target[key],obj),{});return ret[key]},this.ab.warn|=this.aa.info,this.ab.error|=this.ab.warn,this.ab.debug|=this.ab.error,this.ac=this.ab.debug,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.a=`lk`,this.name=scriptName,this.id=scriptId,this.req=new Request(this),this.data=null,this.b=this.fb(`${this.a}${this.id}.dat`),this.c=this.fb(`${this.a}${this.id}.boxjs.json`),this.d=options,this.d?.logLevel&&(this.ac=this.ab[this.d.logLevel]),this.isExecComm=!1,this.f=this.getVal(`${this.a}IsEnableLog${this.id}`),this.f=!!this.isEmpty(this.f)||this.f.o(),this.g=this.getVal(`${this.a}NotifyOnlyFail${this.id}`),this.g=!this.isEmpty(this.g)&&this.g.o(),this.h=this.getVal(`${this.a}IsEnableTgNotify${this.id}`),this.h=!this.isEmpty(this.h)&&this.h.o(),this.i=this.getVal(`${this.a}TgNotifyUrl${this.id}`),this.h=this.h?!this.isEmpty(this.i):this.h,this.j=`${this.a}CostTotalString${this.id}`,this.k=this.getVal(this.j),this.k=this.isEmpty(this.k)?`0,0`:this.k.replace('"',""),this.l=this.k.split(",")[0],this.m=this.k.split(",")[1],this.n=0,this.o="█",this.p=" ",this.now=new Date,this.q=this.now.getTime(),this.node=(()=>{if(this.isNode()){const request=require("request");return{request}}return null})(),this.r=!0,this.s=[],this.t="chavy_boxjs_cur__acs",this.u="chavy_boxjs__acs",this.v={"|`|":",backQuote,"},this.w={",backQuote,":"`","%2CbackQuote%2C":"`"},this.y={"_":"\\_","*":"\\*","`":"\\`"},this.x={"_":"\\_","*":"\\*","[":"\\[","]":"\\]","(":"\\(",")":"\\)","~":"\\~","`":"\\`",">":"\\>","#":"\\#","+":"\\+","-":"\\-","=":"\\=","|":"\\|","{":"\\{","}":"\\}",".":"\\.","!":"\\!"},this.log(`${this.name}, 开始执行!`),this.fd()}fb(_a){if(!this.isNode())return _a;let _b=process.argv.slice(1,2)[0].split("/");return _b[_b.length-1]=_a,_b.join("/")}fc(_a){const _c=this.path.resolve(_a),_d=this.path.resolve(process.cwd(),_a),_e=this.fs.existsSync(_c),_f=!_e&&this.fs.existsSync(_d);return{_c,_d,_e,_f}}async fd(){if(!this.isNode())return;if(this.e=process.argv.slice(1),this.e[1]!="p")return;this.isExecComm=!0,this.log(`开始执行指令【${this.e[1]}】=> 发送到其他终端测试脚本!`);let httpApi=this.d?.httpApi,_h;if(this.isEmpty(this?.d?.httpApi))this.log(`未设置options,使用默认值`),this.isEmpty(this?.d)&&(this.d={}),this.d.httpApi=`ffff@10.0.0.6:6166`,httpApi=this.d.httpApi,_h=httpApi.split("@")[1];else{if(typeof httpApi=="object")if(_h=this.isNumeric(this.e[2])?this.e[3]||"unknown":this.e[2],httpApi[_h])httpApi=httpApi[_h];else{const keys=Object.keys(httpApi);keys[0]?(_h=keys[0],httpApi=httpApi[keys[0]]):httpApi="error"}if(!/.*?@.*?:[0-9]+/.test(httpApi)){this.log(`❌httpApi格式错误!格式: ffff@3.3.3.18:6166`),this.done();return}}this.fe(this.e[2],_h,httpApi)}fe(timeout,_h,httpApi){let _i=this.e[0];const[_j,_k]=httpApi.split("@");this.log(`获取【${_i}】内容传给【${_h||_k}】`),this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const{_c,_d,_e,_f}=this.fc(_i);if(!_e&&!_f){lk.done();return}const _m=_e?_c:_d;let options={url:`http://${_k}/v1/scripting/evaluate`,headers:{"X-Key":_j},body:{script_text:new String(this.fs.readFileSync(_m)),mock_type:"cron",timeout:!this.isEmpty(timeout)&&timeout>5?timeout:5},json:!0};this.req.post(options).then(({error,resp,data})=>{this.log(`已将脚本【${_i}】发给【${_h||_k}】,执行结果:
${this.p}error: ${error}
${this.p}resp: ${resp?.s()}
${this.p}data: ${this.fj(data)}`),this.done()}).catch(e=>{let _ae="",_l=!1;if(e?.error?.code)switch(e.error.code){case"EHOSTDOWN":_ae=`请检查配置的目标设备【${_h||_k}】是否在线!`,_l=!0;break;case"ECONNREFUSED":_ae=`目标设备【${_h||_k}】拒绝连接,请确认服务端口已开启且可访问!`,_l=!0;break;case"EHOSTUNREACH":_ae=`无法到达目标设备【${_h||_k}】,请检查网络连接和路由设置!`,_l=!0;break;case"ENETUNREACH":_ae=`网络不可达,无法访问目标设备【${_h||_k}】,请检查本地网络环境!`,_l=!0;break;case"ETIMEDOUT":_ae=`连接目标设备【${_h||_k}】超时,请检查网络状况或目标设备响应状态!`,_l=!0;break;case"ECONNRESET":_ae=`与目标设备【${_h||_k}】的连接被重置,可能是设备重启或网络异常!`,_l=!0;break;case"ENOTFOUND":_ae=`未能解析目标设备地址【${_h||_k}】,请检查配置的主机名或DNS设置!`,_l=!0;break;case"EADDRINUSE":_ae=`本地端口已被占用,无法建立与目标设备【${_h||_k}】的连接!`,_l=!0;break;case"EACCES":_ae=`权限不足,无法访问目标设备【${_h||_k}】!`,_l=!0;break;default:_l=!1}if(!_l)throw e;this.log(_ae)})}boxJsJsonBuilder(info,param){if(!this.isNode())return;if(!this.isJsonObject(info)||!this.isJsonObject(param)){this.log("构建BoxJsJson传入参数格式错误,请传入json对象");return}let _p=param?.targetBoxjsJsonPath||"/Users/lowking/Desktop/Scripts/lowking.boxjs.json";if(!this.fs.existsSync(_p))return;this.log("using node");let _q=["settings","keys"];const _r="https://raw.githubusercontent.com/Orz-3";let boxJsJson={},scritpUrl="#lk{script_url}";if(boxJsJson.id=`${this.a}${this.id}`,boxJsJson.name=this.name,boxJsJson.desc_html=`⚠️使用说明详情【点我查看】`,boxJsJson.icons=[`${_r}/mini/master/Alpha/${this.id.toLocaleLowerCase()}.png`,`${_r}/mini/master/Color/${this.id.toLocaleLowerCase()}.png`],boxJsJson.keys=[],boxJsJson.settings=[{id:`${this.a}IsEnableLog${this.id}`,name:"开启/关闭日志",val:!0,type:"boolean",desc:"默认开启"},{id:`${this.a}NotifyOnlyFail${this.id}`,name:"只当执行失败才通知",val:!1,type:"boolean",desc:"默认关闭"},{id:`${this.a}IsEnableTgNotify${this.id}`,name:"开启/关闭Telegram通知",val:!1,type:"boolean",desc:"默认关闭"},{id:`${this.a}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 key of _q){if(this.isEmpty(info[key]))break;if(key==="settings")for(let i=0;iapp.id==boxJsJson.id)[0]);targetIdx>=0?boxjsJson.apps[targetIdx]=boxJsJson:boxjsJson.apps.push(boxJsJson);let ret=boxjsJson.s(null,2);if(!this.isEmpty(param))for(const key in param){let val=param[key];if(!val)switch(key){case"author":val="@lowking";break;case"repo":val="https://github.com/lowking/Scripts";break;default:continue}ret=ret.replaceAll(`#lk{${key}}`,val)}const regex=/(?:#lk\{)(.+?)(?=\})/;let m=regex.exec(ret);m!==null&&this.log(`⚠️生成BoxJs还有未配置的参数,请参考:
${this.p}https://github.com/lowking/Scripts/blob/master/util/example/ToolKitDemo.js#L17-L19
${this.p}传入参数: `);let _n=new Set;for(;(m=regex.exec(ret))!==null;)_n.add(m[1]),ret=ret.replace(`#lk{${m[1]}}`,``);_n.forEach(p=>console.log(`${this.p}${p}`)),this.fs.writeFileSync(_p,ret)}isJsonObject(obj){return typeof obj=="object"&&Object.prototype.toString.call(obj).toLowerCase()=="[object object]"&&!obj.length}appendNotifyInfo(info,type){type==1?this.s=info:this.s.push(info)}prependNotifyInfo(info){this.s.splice(0,0,info)}execFail(){this.r=!1}isRequest(){return typeof $request!="undefined"}isSurge(){return typeof $httpClient!="undefined"}isQuanX(){return typeof $task!="undefined"}isLoon(){return typeof $loon!="undefined"}isJSBox(){return typeof $app!="undefined"&&typeof $http!="undefined"}isStash(){return"undefined"!=typeof $environment&&$environment["stash-version"]}isNode(){return typeof require=="function"&&!this.isJSBox()}sleep(ms){return this.n+=ms,new Promise(resolve=>setTimeout(resolve,ms))}randomSleep(minMs,maxMs){return this.sleep(this.randomNumber(minMs,maxMs))}randomNumber(min,max){return Math.floor(Math.random()*(max-min+1)+min)}log(message){if(!this.f)return;this.ac===this.ab.debug&&console.log(`
${this.o}DEBUG${this.o}${message}`)}info(message){if(!this.f)return;this.ac&this.aa.info&&console.log(`
${this.o}INFO${this.o}${message}`)}warn(message){if(!this.f)return;this.ac&this.aa.warn&&console.log(`
${this.o}WARN${this.o}${message}`)}error(message){if(!this.f)return;this.ac&this.aa.error&&console.log(`
${this.o}ERROR${this.o}${message}`)}debug(message){if(!this.f)return;this.ac===this.ab.debug&&console.log(`
${this.o}DEBUG${this.o}${message}`)}logErr(message){if(this.r=!0,this.f){let msg="";this.isEmpty(message.error)||(msg=`${msg}
${this.p}${message.error.s()}`),this.isEmpty(message.message)||(msg=`${msg}
${this.p}${message.message.s()}`),msg=`${this.o}${this.name}执行异常:${this.p}${msg}`,message&&(msg=`${msg}
${this.p}${message.s()}`),console.log(msg)}}ff(mapping,message){for(let key in mapping){if(!mapping.hasOwnProperty(key))continue;message=message.replaceAll(key,mapping[key])}return message}msg(subtitle,message,openUrl,mediaUrl,copyText,disappearS){if(!this.isRequest()&&this.g&&this.r)return;if(this.isEmpty(message)&&(Array.isArray(this.s)?message=this.s.join(`
`):message=this.s),this.isEmpty(message))return;if(this.h){this.log(`${this.name}Tg通知开始`);const fa=this.i&&this.i.indexOf("parse_mode=Markdown")!=-1;if(fa){message=this.ff(this.v,message);let _t=this.y;this.i.indexOf("parse_mode=MarkdownV2")!=-1&&(_t=this.x),message=this.ff(_t,message)}message=`📌${this.name}
${message}`,fa&&(message=this.ff(this.w,message));let u=`${this.i}${encodeURIComponent(message)}`;this.req.get({url:u})}else{let options={};const _u=!this.isEmpty(openUrl),_v=!this.isEmpty(mediaUrl),_w=!this.isEmpty(copyText),_x=disappearS>0;this.isSurge()||this.isLoon()||this.isStash()?(_u&&(options.url=openUrl,options.action="open-url"),_w&&(options.text=copyText,options.action="clipboard"),this.isSurge()&&_x&&(options["auto-dismiss"]=disappearS),_v&&(options["media-url"]=mediaUrl),$notification.post(this.name,subtitle,message,options)):this.isQuanX()?(_u&&(options["open-url"]=openUrl),_v&&(options["media-url"]=mediaUrl),$notify(this.name,subtitle,message,options)):this.isNode()?this.log("⭐️"+this.name+`
`+subtitle+`
`+message):this.isJSBox()&&$push.schedule({title:this.name,body:subtitle?subtitle+`
`+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.fh(),value=process.env[key]||this.data[key]):value=this.data&&this.data[key]||null,value||defaultValue}fg(key,val){if(key==this.u)return;const _y=`${this.a}${this.id}`;let _z=this.getVal(this.t,"{}").o();if(!_z.hasOwnProperty(_y))return;let curSessionId=_z[_y],_aa=this.getVal(this.u,"[]").o();if(_aa.length==0)return;let _ab=[];if(_aa.forEach(_ac=>{_ac.id==curSessionId&&(_ab=_ac.datas)}),_ab.length==0)return;let _ad=!1;_ab.forEach(kv=>{kv.key==key&&(kv.val=val,_ad=!0)}),_ad||_ab.push({key,val}),_aa.forEach(_ac=>{_ac.id==curSessionId&&(_ac.datas=_ab)}),this.setVal(this.u,_aa.s())}setVal(key,val){return this.isSurge()||this.isLoon()||this.isStash()?(this.fg(key,val),$persistentStore.write(val,key)):this.isQuanX()?(this.fg(key,val),$prefs.setValueForKey(val,key)):this.isNode()?(this.data=this.fh(),this.data[key]=val,this.fi(),!0):this.data&&this.data[key]||null}fh(){if(!this.isNode())return{};this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const{_c,_d,_e,_f}=this.fc(this.b);if(_e||_f){const _m=_e?_c:_d;return this.fs.readFileSync(_m).o()}return{}}fi(){if(!this.isNode())return;this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const{_c,_d,_e,_f}=this.fc(this.b),_g=this.data.s();_e?this.fs.writeFileSync(_c,_g):_f?this.fs.writeFileSync(_d,_g):this.fs.writeFileSync(_c,_g)}fj(data){const _s=`${this.p}${this.p}`;let ret="";return Object.keys(data).forEach(key=>{let lines=data[key]?.s().split(`
`);key=="output"&&(lines=lines.slice(0,-2)),ret=`${ret}
${_s}${key}:
${_s}${this.p}${lines?.join(`
${_s}${this.p}`)}`}),ret}fk(response){return response&&(response.status=response?.status||response?.statusCode,delete response.statusCode,response)}get(options,callback=()=>{}){this.isSurge()||this.isLoon()||this.isStash()?$httpClient.get(options,(error,response,body)=>{callback(error,this.fk(response),body)}):this.isQuanX()?(typeof options=="string"&&(options={url:options}),options.method="GET",$task.fetch(options).then(response=>{callback(null,this.fk(response),response.body)},reason=>callback(reason.error,null,null))):this.isNode()?this.node.request(options,(error,response,body)=>{callback(error,this.fk(response),body)}):this.isJSBox()&&(typeof options=="string"&&(options={url:options}),options.header=options.headers,options.handler=function(resp){let error=resp.error;error&&(error=resp.error.s());let body=resp.data;typeof body=="object"&&(body=resp.data.s()),callback(error,this.adapterStatus(resp.response),body)},$http.get(options))}post(options,callback=()=>{}){this.isSurge()||this.isLoon()||this.isStash()?$httpClient.post(options,(error,response,body)=>{callback(error,this.fk(response),body)}):this.isQuanX()?(typeof options=="string"&&(options={url:options}),options.method="POST",$task.fetch(options).then(response=>{callback(null,this.fk(response),response.body)},reason=>callback(reason.error,null,null))):this.isNode()?this.node.request.post(options,(error,response,body)=>{callback(error,this.fk(response),body)}):this.isJSBox()&&(typeof options=="string"&&(options={url:options}),options.header=options.headers,options.handler=function(resp){let error=resp.error;error&&(error=resp.error.s());let body=resp.data;typeof body=="object"&&(body=resp.data.s()),callback(error,this.adapterStatus(resp.response),body)},$http.post(options))}put(options,callback=()=>{}){this.isSurge()||this.isLoon()||this.isStash()?(options.method="PUT",$httpClient.put(options,(error,response,body)=>{callback(error,this.fk(response),body)})):this.isQuanX()?(typeof options=="string"&&(options={url:options}),options.method="PUT",$task.fetch(options).then(response=>{callback(null,this.fk(response),response.body)},reason=>callback(reason.error,null,null))):this.isNode()?(options.method="PUT",this.node.request.put(options,(error,response,body)=>{callback(error,this.fk(response),body)})):this.isJSBox()&&(typeof options=="string"&&(options={url:options}),options.header=options.headers,options.handler=function(resp){let error=resp.error;error&&(error=resp.error.s());let body=resp.data;typeof body=="object"&&(body=resp.data.s()),callback(error,this.adapterStatus(resp.response),body)},$http.post(options))}sum(a,b){let aa=Array.from(a,Number),bb=Array.from(b,Number),ret=[],c=0,i=Math.max(a.length,b.length);for(;i--;)c+=(aa.pop()||0)+(bb.pop()||0),ret.unshift(c%10),c=Math.floor(c/10);for(;c;)ret.unshift(c%10),c=Math.floor(c/10);return ret.join("")}fl(){let info=`${this.name}, 执行完毕!`;this.isNode()&&this.isExecComm&&(info=`指令【${this.e[1]}】执行完毕!`);const endTime=(new Date).getTime(),ms=endTime-this.q,fl=ms/1e3,count=this.sum(this.m,"1"),total=this.sum(this.l,ms.s()),average=(Number(total)/Number(count)/1e3).toFixed(4);info=`${info}
${this.p}耗时【${fl}】秒(含休眠${this.n?(this.n/1e3).toFixed(4):0}秒)`,info=`${info}
${this.p}总共执行【${count}】次,平均耗时【${average}】秒`,info=`${info}
${this.p}ToolKit v1.5.0 build 204.`,this.log(info),this.setVal(this.j,`${total},${count}`.s())}done(value={}){this.fl(),(this.isSurge()||this.isQuanX()||this.isLoon()||this.isStash())&&$done(value)}getRequestUrl(){return $request.url}getResponseBody(){return $response.body}isMatch(reg){return!!($request.method!="OPTIONS"&&this.getRequestUrl().match(reg))}isEmpty(obj){return typeof obj=="undefined"||obj==null||obj.s()=="{}"||obj==""||obj.s()=='""'||obj.s()=="null"||obj.s()=="undefined"||obj.length===0}isNumeric(s){return!isNaN(parseFloat(s))&&isFinite(s)}randomString(len,chars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"){len=len||32;let maxPos=chars.length,pwd="";for(let i=0;i