Script/Ctrip-DailyBonus/Ctrip.js

140 lines
19 KiB
JavaScript
Raw Normal View History

2024-05-09 19:25:14 +08:00
/********************************
携程旅行签到脚本
2024-05-09 23:15:50 +08:00
支持多账号支持Node.js支持Bark推送
配置脚本后登陆"携程旅行"微信小程序或"携程网页版"(https://m.ctrip.com/)即可获取账号授权。多账号请勿"退出登陆"。
2024-05-09 19:25:14 +08:00
脚本作者@NobyDa
更新时间2024/05/09
平台兼容Surge / QuantumultX / Loon / Stash / Node.js
模块依赖(Node.js)iconv-lite / got@11.8.3 / tough-cookie
环境变量(Node.js)CTRIP_AUTH / CTRIP_BARK_KEY
*********************************
Surge(iOS 5.9.0+/macOS 5.5.0+)
https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/CtripDailyBonus.sgmodule
*********************************
QuantumultX 任务仓库(Gallery)订阅
https://raw.githubusercontent.com/NobyDa/Script/master/NobyDa_BoxJs.json
2024-05-09 23:15:50 +08:00
工具&分析->HTTP请求->右上角添加任务仓库->选择携程脚本添加定时任务和附加组件
2024-05-09 19:25:14 +08:00
*********************************/
const $ = new Env('CTRIP_DAILY_BONUS');
const barkKey = $.isNode() && process.env['CTRIP_BARK_KEY'] || ''; // bark key
const notifyMsg = [];
const auth = ''; // '{"account":{"user1":{"auth":"xxx"},"user2":{"auth":"xxx"}}}'
!(async () => {
$.logLevel = $.getdata(`@${$.name}.Debug`) == 'true' && 'debug' || 'info';
const user = JSON.parse(auth || $.getdata($.name) || ($.isNode() && process.env['CTRIP_AUTH']) || '{}');
const userNum = Object.keys(user.account || {}).length;
if (typeof $response !== 'undefined') {
const body = JSON.parse($response.body || '{}');
return GetAuth(body, user);
}
if (userNum) {
const invalidUser = [];
for (const i in user.account) {
const text = [
userNum > 1 && `[账号${notifyMsg.length + 1}(${i.slice(-4)})]`,
await Checkin(user.account[i].auth),
await Points(user.account[i].auth)
].filter((v) => v).join(', ');
if (text.includes('登陆失效')) {
invalidUser.push(i)
}
$.info(text);
notifyMsg.push(text);
}
invalidUser.forEach((i) => delete user.account[i] && !$.isNode() && $.setjson(user, $.name));
} else {
notifyMsg.push(`未获取授权!`);
}
})()
.catch((err) => notifyMsg.push(`错误: ${err}`) && $.error(err))
.finally(async () => {
if (notifyMsg.length) {
$.msg(`携程旅行`, ``, notifyMsg.join('\n'))
}
if (barkKey) {
await BarkNotify($, barkKey, `携程旅行`, notifyMsg.join('\n'));
}
$.done({});
});
function Checkin(key) {
const opts = {
url: 'https://m.ctrip.com/restapi/soa2/22769/signToday',
headers: {
"Content-Type": "application/json",
"User-Agent": 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/21E219 MicroMessenger/8.0.49'
},
body: JSON.stringify({ head: { auth: key } })
};
$.debug(`Send checkin request:`, $.toStr(opts, 'error', null, 1));
return $.http.post(opts)
.then((resp) => {
$.debug(`Receive checkin request response:`, $.toStr(resp))
resp.body = JSON.parse(resp.body?.startsWith('{') && resp.body || '{}');
if (resp.body.code == 0) {
return '签到成功'
} else if (resp.body.code == 400001) {
return '已签过'
} else if (resp.body.code == 404001) {
return '登陆失效, 尝试移除账号...'
} else {
2024-05-09 23:41:10 +08:00
return `签到失败(${resp.body.message})`
2024-05-09 19:25:14 +08:00
}
})
.catch((err) => {
$.error(`Send checkin request error:`, err);
return `签到错误`
})
}
function Points(key) {
const opts = {
url: 'https://m.ctrip.com/restapi/soa2/15634/json/getPointsOrderUserInfo',
headers: {
"Content-Type": "application/json",
"User-Agent": 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/21E219 MicroMessenger/8.0.49'
},
body: JSON.stringify({ needUserInfo: true, head: { auth: key } })
};
$.debug(`Send points request:`, $.toStr(opts, 'error', null, 1));
return $.http.post(opts)
.then((resp) => {
$.debug(`Receive points request response:`, $.toStr(resp))
resp.body = JSON.parse(resp.body?.startsWith('{') && resp.body || '{}');
if (resp.body.isLogin) {
return `总积分: ${resp.body.availableCredits || 0}`
}
})
.catch((err) => {
$.error(`Send points request error:`, err)
return `总积分: 查询错误`
})
}
function GetAuth(body, data) {
if (body.ticket && body.uid) {
if (!data.account || !data.account[body.uid]) {
notifyMsg.push(`账号: ${body.uid}\n写入授权成功!`);
} else {
$.info(`账号: ${body.uid}\n更新授权成功!`);
}
data.account = { ...data.account, ...{ [body.uid]: { auth: body.ticket } } };
} else {
$.error(`写入授权失败, 授权值缺失.`)
}
return $.setjson(data, $.name);
}
//Bark APP notify
async function BarkNotify(c, k, t, b) { for (let i = 0; i < 3; i++) { c.log(`🔷Bark notify >> Start push (${i + 1})`); const s = await new Promise((n) => { c.post({ url: 'https://api.day.app/push', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: t, body: b, device_key: k, ext_params: { group: t } }) }, (e, r, d) => r && r.status == 200 ? n(1) : n(d || e)) }); if (s === 1) { c.log('✅Push success!'); break } else { c.log(`❌Push failed! >> ${s.message || s}`) } } };
// https://github.com/chavyleung/scripts/blob/master/Env.min.js
function Env(t, e) { 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, o) => { 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.logLevels = { debug: 0, info: 1, warn: 2, error: 3 }, this.logLevelPrefixs = { debug: "[DEBUG] ", info: "[INFO] ", warn: "[WARN] ", error: "[ERROR] " }, this.logLevel = "info", 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.encoding = "utf-8", this.startTime = (new Date).getTime(), Object.assign(this, e), this.log("", `🔔${this.name}, 开始!`) } getEnv() { return "undefined" != typeof $environment && $environment["surge-version"] ? "Surge" : "undefined" != typeof $environment && $environment["stash-version"] ? "Stash" : "undefined" != typeof module && module.exports ? "Node.js" : "undefined" != typeof $task ? "Quantumult X" : "undefined" != typeof $loon ? "Loon" : "undefined" != typeof $rocket ? "Shadowrocket" : void 0 } isNode() { return "Node.js" === this.getEnv() } isQuanX() { return "Quantumult X" === this.getEnv() } isSurge() { return "Surge" === this.getEnv() } isLoon() { return "Loon" === this.getEnv() } isShadowrocket() { return "Shadowrocket" === this.getEnv() } isStash() { return "Stash" === this.getEnv() } toObj(t, e = null) { try { return JSON.parse(t) } catch { return e } } toStr(t, e = null, ...s) { try { return JSON.stringify(t, ...s) } catch { return e } } getjson(t, e) { let s = e; if (this.getdata(t)) 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 o = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); o = o ? 1 * o : 20, o = e && e.timeout ? e.timeout : o; const [r, a] = i.split("@"), n = { url: `http://${a}/v1/scripting/evaluate`, body: { script_text: t, mock_type: "cron", timeout: o }, headers: { "X-Key": r, Accept: "*/*" }, timeout: o }; 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), o = JSON.stringify(this.data); s ? this.fs.writeFileSync(t, o) : i ? this.fs.writeFileSync(e, o) : this.fs.writeFileSync(t, o) } } lodash_get(t, e, s) { const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); let o = t; for (const t of i) if (o = Object(o)[t], void 0 === o) return s; return o } lodash_set(t, e, s) { return Object(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), o = s ? this.getval(s) : ""; if (o) try { const t = JSON.parse(o); e = t ? this.lodash_get(t, i, "") : e } catch (t) { e = "" } } return e } setdata(t, e) { let s = !1; if (