mirror of
https://github.com/jiahuigithub/zzxm.git
synced 2026-11-06 06:36:47 +08:00
更新
This commit is contained in:
1 parent
551b945e60
commit
77b4a2f5fe
3 files changed
+1272
-308
No files matched your search
@@ -0,0 +1,464 @@
|
||||
// 青龙脚本 - 星妈会自动任务
|
||||
// 30 0 * * * xmyx.js
|
||||
// 使用方法:在青龙面板中添加环境变量 XMH_COOKIE,多账号换行
|
||||
// 环境变量格式:cuk值(可选备注)
|
||||
// 示例:
|
||||
// wSWQiOiIxIiwic2l25tKNA7BQuLVgf36dv7fheE5mEQi744fpzBiP7573mUX6yHvXhEMfqyuLoa7YymNuEzAHHh8rQSV5gpnXCcaXQfdXUCwd8dmwgyWXWMU6svEybBVBc4bLChq6PFQGNpoBatKdQQk
|
||||
// wSWQiOiIxIiwic2l25tKNA7BQuLVgXfu6A5zs1CqL11PPghn23mgGmCbV7LmLFZsGf4fxZex68XaC3adKe5vssytNrfb7QPcMeNudgbQLvg8xoMSK3mnncdqrCSK6KNbmdrrHeq2S9gmjdfAAsUbH8Jg # 我的账号1
|
||||
// wSWQiOiIxIiwic2l25tKNA7BQuLVgXCbJsU79CeJUS8inM6PyM7eGX8xL2kcy99Naz41C2qycwEhu1EK7imYASNPsEFsXGK8bcpHpYA3wYnPEJZ8rRXok5CxdLfdKvWU1u6mJpw1Kz3AMxWh6gh31d1E # 老婆的账号
|
||||
|
||||
const $ = init();
|
||||
// 优先使用青龙面板自带的 sendNotify
|
||||
const notify = $.isNode() ? (() => {
|
||||
try {
|
||||
return require('./sendNotify');
|
||||
} catch (e) {
|
||||
console.log('⚠️ sendNotify 加载失败,通知功能将不可用');
|
||||
return null;
|
||||
}
|
||||
})() : '';
|
||||
const API_HOST = "https://momclub.feihe.com";
|
||||
|
||||
// 初始化函数
|
||||
function init() {
|
||||
return {
|
||||
isNode: () => typeof process !== 'undefined' && process.version,
|
||||
http: require('axios'),
|
||||
wait: (ms) => new Promise(resolve => setTimeout(resolve, ms)),
|
||||
log: console.log
|
||||
};
|
||||
}
|
||||
|
||||
// 任务类型映射
|
||||
const TASK_TYPES = {
|
||||
CHECKIN: "checkIn", // 签到
|
||||
BROWSE_PAGE: "receive", // 浏览任务
|
||||
COMPLETE: "complete" // 完成类任务
|
||||
};
|
||||
|
||||
let allAccounts = [];
|
||||
let totalCredits = 0;
|
||||
let currentAccount = 1;
|
||||
|
||||
class XingMaHui {
|
||||
constructor(cuk, index, remark = '') {
|
||||
this.cuk = cuk;
|
||||
this.index = index;
|
||||
this.remark = remark;
|
||||
this.accountName = remark ? `账号${index}(${remark})` : `账号${index}`;
|
||||
this.creditsEarned = 0;
|
||||
this.taskResults = [];
|
||||
this.userInfo = null;
|
||||
this.initialPoints = 0; // 初始积分
|
||||
this.finalPoints = 0; // 最终积分
|
||||
}
|
||||
|
||||
// 生成请求头
|
||||
getHeaders() {
|
||||
return {
|
||||
'Host': 'momclub.feihe.com',
|
||||
'cuk': this.cuk,
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090a13) UnifiedPCWindowsWechat(0xf2541022) XWEB/16467',
|
||||
'xweb_xhr': '1',
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': '*/*',
|
||||
'Sec-Fetch-Site': 'cross-site',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
'Referer': 'https://servicewechat.com/wxc83b55d61c7fc51d/41/page-frame.html',
|
||||
'Accept-Encoding': 'gzip, deflate, br',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.9',
|
||||
'Priority': 'u=1, i'
|
||||
};
|
||||
}
|
||||
|
||||
// 生成时间戳
|
||||
getMockTime() {
|
||||
return Date.now();
|
||||
}
|
||||
|
||||
// 发送请求
|
||||
async request(url, method = 'GET', data = null) {
|
||||
const headers = this.getHeaders();
|
||||
|
||||
try {
|
||||
let response;
|
||||
const config = {
|
||||
headers: headers,
|
||||
timeout: 10000
|
||||
};
|
||||
|
||||
if (method === 'GET') {
|
||||
response = await $.http.get(url, config);
|
||||
} else {
|
||||
response = await $.http.post(url, data, config);
|
||||
}
|
||||
|
||||
if (response.status === 200) {
|
||||
return response.data;
|
||||
} else {
|
||||
console.log(`❌ 请求失败: ${response.status}`);
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`❌ 请求异常: ${error.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取用户信息
|
||||
async getUserInfo() {
|
||||
const url = `${API_HOST}/pmall/c/user/memberInfo`;
|
||||
const result = await this.request(url);
|
||||
|
||||
if (result && result.code === "000000" && result.data) {
|
||||
this.userInfo = result.data;
|
||||
return this.userInfo;
|
||||
} else {
|
||||
console.log(`❌ 获取用户信息失败: ${result ? result.message : '网络错误'}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 查询单个任务结果
|
||||
async querySingleTaskResult(taskName) {
|
||||
const url = `${API_HOST}/pmall/c/activity/todo/queryTodoResult`;
|
||||
const result = await this.request(url);
|
||||
|
||||
if (result && result.code === "000000" && result.data) {
|
||||
// 查找特定任务的结果
|
||||
const taskResult = result.data.find(task => task.taskName === taskName);
|
||||
if (taskResult) {
|
||||
const credits = taskResult.actualCredits || 0;
|
||||
console.log(`🎉 任务【${taskName}】获得积分: ${credits}`);
|
||||
this.taskResults.push(`✅ ${taskName} +${credits}积分`);
|
||||
this.creditsEarned += credits;
|
||||
return credits;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 查询所有任务结果
|
||||
async queryAllTaskResults() {
|
||||
const url = `${API_HOST}/pmall/c/activity/todo/queryTodoResult`;
|
||||
const result = await this.request(url);
|
||||
|
||||
if (result && result.code === "000000" && result.data) {
|
||||
let total = 0;
|
||||
result.data.forEach(task => {
|
||||
const credits = task.actualCredits || 0;
|
||||
total += credits;
|
||||
console.log(`📊 ${task.taskName}: +${credits}积分`);
|
||||
});
|
||||
console.log(`🎉 今日已获得积分: ${total}`);
|
||||
return total;
|
||||
} else {
|
||||
console.log(`❌ 查询任务结果失败: ${result ? result.message : '未知错误'}`);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取任务列表
|
||||
async getTaskList() {
|
||||
const url = `${API_HOST}/pmall/c/activity/todo/list?mockTime=${this.getMockTime()}`;
|
||||
const result = await this.request(url);
|
||||
|
||||
if (result && result.code === "000000") {
|
||||
return result.data;
|
||||
} else {
|
||||
console.log(`❌ 获取任务列表失败: ${result ? result.message : '网络错误'}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 执行签到
|
||||
async doCheckIn(activityId, taskName) {
|
||||
const url = `${API_HOST}/pmall/c/activity/todo/checkIn`;
|
||||
const data = {
|
||||
"activityId": activityId,
|
||||
"mockTime": this.getMockTime()
|
||||
};
|
||||
|
||||
const result = await this.request(url, 'POST', data);
|
||||
if (result && result.code === "000000") {
|
||||
console.log(`✅ ${taskName} 完成`);
|
||||
// 查询签到结果
|
||||
await $.wait(1000);
|
||||
await this.querySingleTaskResult(taskName);
|
||||
return true;
|
||||
} else {
|
||||
console.log(`❌ ${taskName} 失败: ${result ? result.message : '未知错误'}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 执行浏览任务
|
||||
async doBrowseTask(activityId, taskName) {
|
||||
const url = `${API_HOST}/pmall/c/activity/todo/receive`;
|
||||
const data = {
|
||||
"activityId": activityId,
|
||||
"mockTime": this.getMockTime()
|
||||
};
|
||||
|
||||
const result = await this.request(url, 'POST', data);
|
||||
if (result && result.code === "000000") {
|
||||
console.log(`✅ ${taskName} 完成`);
|
||||
// 查询任务结果
|
||||
await $.wait(1000);
|
||||
await this.querySingleTaskResult(taskName);
|
||||
return true;
|
||||
} else {
|
||||
console.log(`❌ ${taskName} 失败: ${result ? result.message : '未知错误'}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 执行完成类任务
|
||||
async doCompleteTask(activityId, taskName) {
|
||||
const url = `${API_HOST}/pmall/c/activity/todo/complete`;
|
||||
const data = {
|
||||
"activityId": activityId,
|
||||
"mockTime": this.getMockTime()
|
||||
};
|
||||
|
||||
const result = await this.request(url, 'POST', data);
|
||||
if (result && result.code === "000000") {
|
||||
console.log(`✅ ${taskName} 完成`);
|
||||
// 查询任务结果
|
||||
await $.wait(1000);
|
||||
await this.querySingleTaskResult(taskName);
|
||||
return true;
|
||||
} else {
|
||||
console.log(`❌ ${taskName} 失败: ${result ? result.message : '未知错误'}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 执行所有任务
|
||||
async doAllTasks() {
|
||||
console.log(`\n🚀 开始执行 ${this.accountName} 任务...`);
|
||||
|
||||
// 首先获取用户信息(初始积分)
|
||||
console.log('📡 获取初始用户信息...');
|
||||
await this.getUserInfo();
|
||||
if (this.userInfo) {
|
||||
this.initialPoints = this.userInfo.points;
|
||||
console.log(`📊 初始积分: ${this.initialPoints}`);
|
||||
}
|
||||
|
||||
// 获取任务列表
|
||||
const taskData = await this.getTaskList();
|
||||
if (!taskData) {
|
||||
console.log('❌ 获取任务列表失败,跳过该账号');
|
||||
return;
|
||||
}
|
||||
|
||||
// 执行签到任务
|
||||
if (taskData.checkInTodo) {
|
||||
const checkInId = taskData.checkInTodo.id;
|
||||
const taskName = taskData.checkInTodo.name;
|
||||
await this.doCheckIn(checkInId, taskName);
|
||||
await $.wait(2000);
|
||||
}
|
||||
|
||||
// 执行其他任务
|
||||
if (taskData.taskTodo && taskData.taskTodo.length > 0) {
|
||||
for (const task of taskData.taskTodo) {
|
||||
const taskId = task.id;
|
||||
const taskName = task.name;
|
||||
const taskType = task.taskTodoExtra?.type;
|
||||
|
||||
console.log(`\n🚀 处理任务: ${taskName}`);
|
||||
|
||||
// 根据任务类型执行不同的操作
|
||||
switch (taskType) {
|
||||
case 'BROWSE_PAGE':
|
||||
await this.doBrowseTask(taskId, taskName);
|
||||
break;
|
||||
case 'AddQw':
|
||||
case 'FirstOrder':
|
||||
// 这些任务需要手动完成,跳过
|
||||
console.log(`⏭️ 跳过需要手动完成的任务: ${taskName}`);
|
||||
break;
|
||||
default:
|
||||
await this.doCompleteTask(taskId, taskName);
|
||||
break;
|
||||
}
|
||||
|
||||
// 短暂延迟,避免请求过快
|
||||
await $.wait(2000);
|
||||
}
|
||||
}
|
||||
|
||||
// 查询所有任务结果汇总
|
||||
console.log(`\n📋 任务完成汇总:`);
|
||||
await this.queryAllTaskResults();
|
||||
|
||||
// 重新获取用户信息以获取最终积分
|
||||
console.log('\n📡 获取最终用户信息...');
|
||||
await this.getUserInfo();
|
||||
if (this.userInfo) {
|
||||
this.finalPoints = this.userInfo.points;
|
||||
console.log(`📊 最终积分: ${this.finalPoints}`);
|
||||
const actualIncrease = this.finalPoints - this.initialPoints;
|
||||
console.log(`🎊 实际积分增加: ${actualIncrease}`);
|
||||
}
|
||||
|
||||
console.log(`🎊 ${this.accountName} 任务执行完成`);
|
||||
}
|
||||
|
||||
// 获取任务结果
|
||||
getResults() {
|
||||
return {
|
||||
accountName: this.accountName,
|
||||
credits: this.creditsEarned,
|
||||
tasks: this.taskResults,
|
||||
userInfo: this.userInfo,
|
||||
initialPoints: this.initialPoints,
|
||||
finalPoints: this.finalPoints
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 解析环境变量(支持备注)
|
||||
function parseCookies(cookieStr) {
|
||||
const cookies = [];
|
||||
const lines = cookieStr.split('\n').filter(line => line.trim());
|
||||
|
||||
lines.forEach((line, index) => {
|
||||
const parts = line.split('#');
|
||||
const cuk = parts[0].trim();
|
||||
const remark = parts[1] ? parts[1].trim() : '';
|
||||
|
||||
if (cuk) {
|
||||
cookies.push({
|
||||
cuk: cuk,
|
||||
index: index + 1,
|
||||
remark: remark
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return cookies;
|
||||
}
|
||||
|
||||
// 主函数
|
||||
async function main() {
|
||||
console.log("🚀 星妈会自动任务开始执行...\n");
|
||||
|
||||
// 读取环境变量
|
||||
const cookieStr = process.env.XMH_COOKIE || '';
|
||||
|
||||
if (!cookieStr) {
|
||||
console.log("❌ 未找到有效的cuk配置,请检查环境变量 XMH_COOKIE");
|
||||
return;
|
||||
}
|
||||
|
||||
// 解析cookies
|
||||
const cookieList = parseCookies(cookieStr);
|
||||
|
||||
if (cookieList.length === 0) {
|
||||
console.log("❌ 未找到有效的cuk配置,请检查环境变量 XMH_COOKIE");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`📝 找到 ${cookieList.length} 个账号\n`);
|
||||
|
||||
// 显示账号信息
|
||||
cookieList.forEach(cookie => {
|
||||
console.log(` ${cookie.index}. ${cookie.remark || '未备注'}`);
|
||||
});
|
||||
console.log('');
|
||||
|
||||
// 初始化账号实例
|
||||
for (const cookie of cookieList) {
|
||||
allAccounts.push(new XingMaHui(cookie.cuk, cookie.index, cookie.remark));
|
||||
}
|
||||
|
||||
// 依次执行每个账号的任务
|
||||
for (const account of allAccounts) {
|
||||
currentAccount = account.index;
|
||||
await account.doAllTasks();
|
||||
totalCredits += account.creditsEarned;
|
||||
|
||||
// 账号间延迟
|
||||
if (account.index < allAccounts.length) {
|
||||
console.log("\n⏳ 等待5秒后处理下一个账号...\n");
|
||||
await $.wait(5000);
|
||||
}
|
||||
}
|
||||
|
||||
// 汇总结果
|
||||
await showSummary();
|
||||
}
|
||||
|
||||
// 显示汇总结果
|
||||
async function showSummary() {
|
||||
console.log("\n" + "=".repeat(70));
|
||||
console.log("🎉 星妈会任务执行汇总");
|
||||
console.log("=".repeat(70));
|
||||
|
||||
let summaryMessage = `星妈会任务完成情况:\n\n`;
|
||||
let consoleMessage = ``;
|
||||
|
||||
for (const account of allAccounts) {
|
||||
const results = account.getResults();
|
||||
|
||||
// 显示用户基本信息
|
||||
if (results.userInfo) {
|
||||
summaryMessage += `📱 ${results.accountName}:\n`;
|
||||
summaryMessage += ` 手机号:${results.userInfo.mobile}\n`;
|
||||
summaryMessage += ` 会员等级:${results.userInfo.gradeName}\n`;
|
||||
summaryMessage += ` 初始积分:${results.initialPoints}\n`;
|
||||
summaryMessage += ` 最终积分:${results.finalPoints}\n`;
|
||||
summaryMessage += ` 实际增加:${results.finalPoints - results.initialPoints}积分\n`;
|
||||
|
||||
consoleMessage += `📱 ${results.accountName}:\n`;
|
||||
consoleMessage += ` 📞 手机号:${results.userInfo.mobile}\n`;
|
||||
consoleMessage += ` ⭐ 会员等级:${results.userInfo.gradeName}\n`;
|
||||
consoleMessage += ` 📥 初始积分:${results.initialPoints}\n`;
|
||||
consoleMessage += ` 📤 最终积分:${results.finalPoints}\n`;
|
||||
consoleMessage += ` 📈 实际增加:${results.finalPoints - results.initialPoints}积分\n`;
|
||||
} else {
|
||||
summaryMessage += `📱 ${results.accountName}:\n`;
|
||||
summaryMessage += ` ❌ 用户信息获取失败\n`;
|
||||
|
||||
consoleMessage += `📱 ${results.accountName}:\n`;
|
||||
consoleMessage += ` ❌ 用户信息获取失败\n`;
|
||||
}
|
||||
|
||||
// 显示任务完成情况
|
||||
summaryMessage += ` 今日获得:${results.credits}积分\n`;
|
||||
consoleMessage += ` 🎉 今日获得:${results.credits}积分\n`;
|
||||
|
||||
if (results.tasks.length > 0) {
|
||||
summaryMessage += ` 完成任务:\n`;
|
||||
consoleMessage += ` ✅ 完成任务:\n`;
|
||||
results.tasks.forEach(task => {
|
||||
summaryMessage += ` ${task}\n`;
|
||||
consoleMessage += ` ${task}\n`;
|
||||
});
|
||||
}
|
||||
summaryMessage += `\n`;
|
||||
consoleMessage += `\n`;
|
||||
}
|
||||
|
||||
summaryMessage += `📊 总计:${allAccounts.length} 个账号,今日共获得 ${totalCredits} 积分`;
|
||||
consoleMessage += `📊 总计:${allAccounts.length} 个账号,今日共获得 ${totalCredits} 积分`;
|
||||
|
||||
console.log(consoleMessage);
|
||||
|
||||
// 发送通知
|
||||
if ($.isNode() && notify) {
|
||||
await notify.sendNotify("星妈会任务完成", summaryMessage);
|
||||
}
|
||||
}
|
||||
|
||||
// 运行脚本
|
||||
main().catch(error => {
|
||||
console.log(`❌ 脚本执行出错: ${error}`);
|
||||
if ($.isNode() && notify) {
|
||||
notify.sendNotify("星妈会任务异常", `执行过程中出现错误: ${error}`);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,808 @@
|
||||
/*
|
||||
================================================================================
|
||||
脚本名称: 飞鹤|北纬47度好物(原星妈优选)
|
||||
30 0 * * * xmyx.js
|
||||
脚本作者: Leiyiyan
|
||||
创建日期: 2024-10-08
|
||||
最后更新: 2024-12-03
|
||||
================================================================================
|
||||
|
||||
【功能说明】
|
||||
飞鹤|北纬47度好物小程序 每日签到、自动完成任务
|
||||
|
||||
【使用方法】
|
||||
1. 青龙面板配置:
|
||||
- 进入青龙面板 → 环境变量
|
||||
- 添加变量名:xmtoken
|
||||
- 变量值:每行一个token(支持多账号)
|
||||
|
||||
2. 环境变量格式(三种方式任选其一):
|
||||
方式1(推荐):换行分隔
|
||||
token1
|
||||
token2
|
||||
token3
|
||||
|
||||
方式2:&符号分隔
|
||||
token1&token2&token3
|
||||
|
||||
方式3:@符号分隔
|
||||
token1@token2@token3
|
||||
|
||||
【获取Token】
|
||||
方法1:抓包获取
|
||||
- 抓包地址:https://www.feihevip.com/api/starMember/getMemberInfo
|
||||
- 抓取请求头中的 token 字段
|
||||
|
||||
方法2:使用抓包工具(推荐使用 Quantumult X 或 Surge)
|
||||
[Script]
|
||||
http-response ^https?:\/\/www\.feihevip\.com\/api\/starMember\/getMemberInfo script-path=xmyx.js, requires-body=true, timeout=60, tag=星妈优选获取Cookie
|
||||
|
||||
[MITM]
|
||||
hostname = www.feihevip.com
|
||||
|
||||
【定时任务】
|
||||
建议每天早上0点30分执行
|
||||
cron: 30 0 * * *
|
||||
|
||||
【图标】
|
||||
https://raw.githubusercontent.com/leiyiyan/resource/main/icons/xmyx.png
|
||||
|
||||
================================================================================
|
||||
⚠️【免责声明】
|
||||
================================================================================
|
||||
1、此脚本仅用于学习研究,不保证其合法性、准确性、有效性,请根据情况自行判断,
|
||||
本人对此不承担任何保证责任。
|
||||
2、由于此脚本仅用于学习研究,您必须在下载后 24 小时内将所有内容从您的计算机
|
||||
或手机或任何存储设备中完全删除,若违反规定引起任何事件本人对此均不负责。
|
||||
3、请勿将此脚本用于任何商业或非法目的,若违反规定请自行对此负责。
|
||||
4、此脚本涉及应用与本人无关,本人对因此引起的任何隐私泄漏或其他后果不承担
|
||||
任何责任。
|
||||
5、本人对任何脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失
|
||||
和损害。
|
||||
6、如果任何单位或个人认为此脚本可能涉嫌侵犯其权利,应及时通知并提供身份证明,
|
||||
所有权证明,我们将在收到认证文件确认后删除此脚本。
|
||||
7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改
|
||||
或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
|
||||
const $ = new Env("星妈优选");
|
||||
const ckName = "xmtoken";
|
||||
|
||||
//-------------------- 一般不动变量区域 -------------------------------------
|
||||
$.appid = "wx4205ec55b793245e";
|
||||
const Notify = 1;//0为关闭通知,1为打开通知,默认为1
|
||||
// 优先使用青龙面板自带的 sendNotify,如果不存在则使用本地的
|
||||
const notify = $.isNode() ? (() => {
|
||||
try {
|
||||
// 尝试加载青龙面板的 sendNotify
|
||||
return require('./sendNotify');
|
||||
} catch (e) {
|
||||
try {
|
||||
// 如果青龙的不存在,尝试加载本地的
|
||||
return require('./sendNotify');
|
||||
} catch (err) {
|
||||
console.log('⚠️ sendNotify 加载失败,通知功能将不可用');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
})() : '';
|
||||
// 初始化 got 库
|
||||
if ($.isNode()) {
|
||||
try {
|
||||
$.initGotEnv();
|
||||
} catch (e) {
|
||||
console.log('⚠️ got 库初始化失败,部分功能可能受限');
|
||||
}
|
||||
}
|
||||
let envSplitor = ["\n", "&", "@"]; //多账号分隔符,优先使用换行符
|
||||
// 从环境变量读取 token,支持多账号
|
||||
// 环境变量名: xmtoken
|
||||
// 格式: 多个token用@或换行分隔,例如: token1@token2@token3
|
||||
var userCookie = ($.isNode() ? process.env[ckName] : $.getdata(ckName)) || '';
|
||||
let userList = [];
|
||||
let userIdx = 0;
|
||||
let userCount = 0;
|
||||
// 调试
|
||||
$.is_debug = ($.isNode() ? process.env.IS_DEDUG : $.getdata('is_debug')) || 'false';
|
||||
// 为多用户准备的通知数组
|
||||
$.notifyList = [];
|
||||
// 为通知准备的空数组
|
||||
$.notifyMsg = [];
|
||||
|
||||
//---------------------- 自定义变量区域 -----------------------------------
|
||||
const appid = 'xmyx'
|
||||
const appKey = 'TwUQ01lKS1Km5zlV2f7amsZc5EQYkTbv'
|
||||
|
||||
//---------------------- 脚本入口函数 -----------------------------------
|
||||
async function main() {
|
||||
try {
|
||||
$.log('\n' + '='.repeat(50));
|
||||
$.log('🎯 开始执行任务');
|
||||
$.log('='.repeat(50) + '\n');
|
||||
|
||||
// 仅调用一次 getTaskList
|
||||
let taskList = [];
|
||||
if (userList.length > 0) {
|
||||
taskList = await userList[0].getTaskList();
|
||||
$.log(`� 获取到 ${taskList.length} 个账号任务\n`);
|
||||
}
|
||||
|
||||
for (let user of userList) {
|
||||
$.log(`\n${'─'.repeat(50)}`);
|
||||
$.log(`📱 账号 ${user.index} 开始执行`);
|
||||
$.log('─'.repeat(50));
|
||||
|
||||
// 先获取用户信息
|
||||
const userInfoBefore = await user.getUserInfo();
|
||||
if (userInfoBefore) {
|
||||
const { userName, score, level, mobile } = userInfoBefore;
|
||||
user.userName = userName;
|
||||
user.avatar = userInfoBefore.avatar;
|
||||
user.mobile = mobile;
|
||||
$.log(`� 用户: ${userName || '未知'}${mobile ? ` (${mobile})` : ''}`);
|
||||
$.log(`💰 当前积分: ${score} | 等级: ${level}`);
|
||||
}
|
||||
|
||||
const flag = await user.getSignInfo();
|
||||
|
||||
if (user.ckStatus) {
|
||||
// 完成任务
|
||||
if (taskList.length > 0) {
|
||||
$.log(`\n📝 开始执行任务列表...`);
|
||||
for(let task of taskList) {
|
||||
await user.tofinish(task.taskName, task.taskType);
|
||||
await $.wait(1000 * (task.completeTaskDuration?task.completeTaskDuration:3))
|
||||
await user.completeTask(task.taskName, task.taskType);
|
||||
await $.wait(user.getRandomTime());
|
||||
}
|
||||
}
|
||||
|
||||
// 查询最终用户信息
|
||||
const userInfoAfter = await user.getUserInfo();
|
||||
if (userInfoAfter) {
|
||||
const { score, level, userName, avatar, mobile } = userInfoAfter;
|
||||
user.avatar = avatar;
|
||||
user.userName = userName;
|
||||
user.mobile = mobile;
|
||||
await user.refreshToken(user.token);
|
||||
|
||||
const earnedPoints = userInfoBefore ? score - userInfoBefore.score : 0;
|
||||
$.log(`\n✨ 任务完成`);
|
||||
$.log(`� 用户:分 ${userName}${mobile ? ` (${mobile})` : ''}`);
|
||||
$.log(`💰 最终积分: ${score} ${earnedPoints > 0 ? `(+${earnedPoints})` : ''}`);
|
||||
$.log(`⭐ 等级: ${level}`);
|
||||
|
||||
$.title = `今日任务已全部完成`;
|
||||
// 通知消息包含手机号/fullName
|
||||
const displayName = mobile ? `${userName} (${mobile})` : userName;
|
||||
DoubleLog(`「${displayName}」积分: ${score}${earnedPoints > 0 ? ` (+${earnedPoints})` : ''}, 等级: ${level}`);
|
||||
}
|
||||
} else {
|
||||
//将ck过期消息存入消息数组
|
||||
$.notifyMsg.push(`❌账号${user.userName || user.index} >> Token已失效`)
|
||||
}
|
||||
|
||||
//账号通知
|
||||
$.notifyList.push({ "id": user.index, "avatar": user.avatar, "message": $.notifyMsg });
|
||||
//清空数组
|
||||
$.notifyMsg = [];
|
||||
}
|
||||
|
||||
$.log(`\n${'='.repeat(50)}`);
|
||||
$.log(`✅ 所有账号执行完成`);
|
||||
$.log('='.repeat(50) + '\n');
|
||||
} catch (e) {
|
||||
$.log(`⛔️ main run error => ${e}`);
|
||||
throw new Error(`⛔️ main run error => ${e}`);
|
||||
}
|
||||
}
|
||||
class UserInfo {
|
||||
constructor(user) {
|
||||
//默认属性
|
||||
this.index = ++userIdx;
|
||||
this.token = user.token || user;
|
||||
this.userId = user.userId;
|
||||
this.userName = user.userName;
|
||||
this.avatar = user.avatar;
|
||||
this.ckStatus = true;
|
||||
this.doFlag = { "true": "✅", "false": "⛔️" };
|
||||
|
||||
//请求封装
|
||||
this.baseUrl = ``;
|
||||
this.host = "https://www.feihevip.com/api";
|
||||
this.headers = {
|
||||
"Host": "www.feihevip.com",
|
||||
"token": this.token,
|
||||
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.48(0x1800302b) NetType/4G Language/zh_CN",
|
||||
"Referer": "https://servicewechat.com/wx4205ec55b793245e/366/page-frame.html",
|
||||
"fhAppid": appid,
|
||||
"source": 1
|
||||
}
|
||||
|
||||
this.getRandomTime = () => randomInt(1e3, 3e3);
|
||||
this.fetch = async (o) => {
|
||||
try {
|
||||
if (typeof o === 'string') o = { url: o };
|
||||
if (o?.url?.startsWith("/")) o.url = this.host + o.url
|
||||
const res = await Request({ ...o, headers: o.headers || this.headers, url: o.url || this.baseUrl })
|
||||
// debug(res, o?.url?.replace(/\/+$/, '').substring(o?.url?.lastIndexOf('/') + 1));
|
||||
if (res?.code == 40001) throw new Error(res?.message || `用户需要去登录`);
|
||||
return res;
|
||||
} catch (e) {
|
||||
this.ckStatus = false;
|
||||
$.log(`⛔️ 请求发起失败!${e}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 签到
|
||||
async getSignInfo() {
|
||||
try {
|
||||
const { fhNonceStr, fhTimestamp, fhSign } = getSignature();
|
||||
const opts = {
|
||||
url: '/member/signin/getSignInfo',
|
||||
type: "get",
|
||||
params: {
|
||||
signType: 1
|
||||
},
|
||||
headers: Object.assign({}, this.headers, {
|
||||
fhNonceStr,
|
||||
fhTimestamp,
|
||||
fhSign
|
||||
})
|
||||
}
|
||||
const res = await this.fetch(opts);
|
||||
if (!res?.data) {
|
||||
$.log(`⚠️ 签到信息获取失败`);
|
||||
return;
|
||||
}
|
||||
const { signStatus } = res.data;
|
||||
if (signStatus === 1) {
|
||||
$.log(`✅ 今日已签到`);
|
||||
}
|
||||
|
||||
if (signStatus === 2) {
|
||||
await this.signin();
|
||||
}
|
||||
} catch (e) {
|
||||
this.ckStatus = false;
|
||||
$.log(`⛔️ 签到失败: ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 签到
|
||||
async signin() {
|
||||
try {
|
||||
const { fhNonceStr, fhTimestamp, fhSign } = getSignature();
|
||||
const res = await this.fetch({
|
||||
url: '/member/signin/sign',
|
||||
type: 'post',
|
||||
params: {},
|
||||
headers: Object.assign({}, this.headers, {
|
||||
fhNonceStr,
|
||||
fhTimestamp,
|
||||
fhSign
|
||||
})
|
||||
});
|
||||
if (res.code === '200') {
|
||||
$.log(`✅ 签到成功`);
|
||||
} else {
|
||||
$.log(`✅ 签到失败:${res.msg}`);
|
||||
}
|
||||
} catch (e) {
|
||||
this.ckStatus = false;
|
||||
$.log(`⛔️ 执行任务今日签到失败! ${e}`);
|
||||
}
|
||||
}
|
||||
// 获取任务列表
|
||||
async getTaskList() {
|
||||
try {
|
||||
const { fhNonceStr, fhTimestamp, fhSign } = getSignature();
|
||||
const opts = {
|
||||
url: '/member/signin/getTaskList',
|
||||
type: "get",
|
||||
headers: Object.assign({}, this.headers, {
|
||||
fhNonceStr,
|
||||
fhTimestamp,
|
||||
fhSign
|
||||
})
|
||||
}
|
||||
const res = await this.fetch(opts);
|
||||
debug(res, `获取任务列表`);
|
||||
if (res?.code == '200' && res?.data) {
|
||||
return res.data;
|
||||
} else {
|
||||
$.log(`⛔️ 获取任务列表失败! ${res?.msg}\n`);
|
||||
return [];
|
||||
}
|
||||
} catch (e) {
|
||||
this.ckStatus = false;
|
||||
$.log(`⛔️ 获取任务列表失败! ${e}`);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
// 执行任务
|
||||
async tofinish(taskName, taskType) {
|
||||
try {
|
||||
const { fhNonceStr, fhTimestamp, fhSign } = getSignature();
|
||||
const opts = {
|
||||
url: '/member/signin/tofinish',
|
||||
type: "get",
|
||||
params: {
|
||||
taskType
|
||||
},
|
||||
headers: Object.assign({}, this.headers, {
|
||||
fhNonceStr,
|
||||
fhTimestamp,
|
||||
fhSign
|
||||
})
|
||||
}
|
||||
const res = await this.fetch(opts);
|
||||
debug(res, `执行任务: ${taskName}`)
|
||||
if (res?.code == '200') {
|
||||
$.log(` 🚀 开始: ${taskName}`);
|
||||
} else {
|
||||
$.log(` ⚠️ ${taskName}: ${res?.msg}`);
|
||||
}
|
||||
} catch (e) {
|
||||
this.ckStatus = false;
|
||||
$.log(` ⛔️ ${taskName} 失败: ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 完成任务
|
||||
async completeTask(taskName, taskType) {
|
||||
try {
|
||||
const { fhNonceStr, fhTimestamp, fhSign } = getSignature();
|
||||
const opts = {
|
||||
url: '/member/signin/completeTask',
|
||||
type: "get",
|
||||
params: {
|
||||
taskType
|
||||
},
|
||||
headers: Object.assign({}, this.headers, {
|
||||
fhNonceStr,
|
||||
fhTimestamp,
|
||||
fhSign
|
||||
})
|
||||
}
|
||||
const res = await this.fetch(opts);
|
||||
debug(res, `完成任务: ${taskName}`)
|
||||
if(res?.code == '200') {
|
||||
if(res?.data) {
|
||||
const point = res?.data?.awardSendPoints;
|
||||
$.log(` ✅ 完成: ${taskName} +${point}积分`);
|
||||
}else{
|
||||
$.log(` ℹ️ ${taskName} 已完成`);
|
||||
}
|
||||
}else{
|
||||
$.log(` ⛔️ ${taskName} 失败: ${res?.msg}`);
|
||||
}
|
||||
} catch (e) {
|
||||
this.ckStatus = false;
|
||||
$.log(` ⛔️ ${taskName} 异常: ${e}`);
|
||||
}
|
||||
}
|
||||
// 获取用户信息
|
||||
async getUserInfo() {
|
||||
try {
|
||||
const { fhNonceStr, fhTimestamp, fhSign } = getSignature({});
|
||||
const opts = {
|
||||
url: '/starMember/getMemberInfo',
|
||||
type: "post",
|
||||
dataType: "json",
|
||||
headers: Object.assign({}, this.headers, {
|
||||
fhNonceStr,
|
||||
fhTimestamp,
|
||||
fhSign
|
||||
}),
|
||||
body: {}
|
||||
}
|
||||
const res = await this.fetch(opts);
|
||||
debug(res, `查询用户信息`)
|
||||
|
||||
if(res?.code == '200' && res?.data) {
|
||||
// 积分
|
||||
const score = res?.data?.memberPoints?.scoreValue;
|
||||
// 等级
|
||||
const level = res?.data?.memberGrade?.currentGrade;
|
||||
// 用户名
|
||||
const userName = res?.data?.baseInfo?.nickName;
|
||||
// 头像
|
||||
const avatar = res?.data?.baseInfo?.headImgUrl;
|
||||
|
||||
// 手机号(从多个可能的字段中获取,优先使用看起来像手机号的)
|
||||
let mobile = '';
|
||||
const possibleFields = [
|
||||
res?.data?.baseInfo?.mobile,
|
||||
res?.data?.baseInfo?.fullName,
|
||||
res?.data?.mobile
|
||||
];
|
||||
|
||||
// 找到第一个看起来像手机号的字段(11位数字)
|
||||
for (const field of possibleFields) {
|
||||
if (field && /^1\d{10}$/.test(field)) {
|
||||
mobile = field;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没找到手机号格式的,就用 fullName 或 crmId
|
||||
if (!mobile) {
|
||||
mobile = res?.data?.baseInfo?.fullName || res?.data?.crmId || '';
|
||||
}
|
||||
|
||||
return { score, level, userName, avatar, mobile };
|
||||
}else{
|
||||
$.log(`⛔️ 查询用户信息失败! ${res?.msg}\n`);
|
||||
}
|
||||
} catch (e) {
|
||||
this.ckStatus = false;
|
||||
$.log(`⛔️ 查询用户信息失败! ${e}`);
|
||||
}
|
||||
}
|
||||
// 刷新token
|
||||
async refreshToken(token) {
|
||||
try {
|
||||
const { fhNonceStr, fhTimestamp, fhSign } = getSignature2();
|
||||
const options = {
|
||||
url: `https://mom.feihe.com/program/token/refreshToken`,
|
||||
type: "get",
|
||||
headers: {
|
||||
"Host": "mom.feihe.com",
|
||||
"token": token,
|
||||
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.48(0x1800302b) NetType/4G Language/zh_CN",
|
||||
"Referer": "https://servicewechat.com/wx4205ec55b793245e/366/page-frame.html",
|
||||
"fhAppid": 'xmh',
|
||||
"source": 1,
|
||||
fhNonceStr,
|
||||
fhTimestamp,
|
||||
fhSign
|
||||
}
|
||||
};
|
||||
//post方法
|
||||
let result = await Request(options);
|
||||
let refreshToken = result?.data;
|
||||
|
||||
if (refreshToken) {
|
||||
// 更新当前用户的token
|
||||
this.token = refreshToken;
|
||||
this.headers.token = refreshToken;
|
||||
$.log(`🎉 刷新 token 成功`)
|
||||
debug(result, '获取token');
|
||||
} else {
|
||||
$.log(`⚠️ 刷新 token 返回为空`)
|
||||
}
|
||||
} catch (e) {
|
||||
$.log(`⛔️ 刷新 Token 失败: ${e}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
async function getCookie() {
|
||||
if ($request && $request.method === 'OPTIONS') return;
|
||||
|
||||
const header = ObjectKeys2LowerCase($request.headers);
|
||||
const token = header.token;
|
||||
const body = $.toObj($response.body);
|
||||
if (!(body?.data)) {
|
||||
$.msg($.name, `❌获取Cookie失败!`, "")
|
||||
return;
|
||||
}
|
||||
// 积分
|
||||
const score = body?.data?.memberPoints?.scoreValue;
|
||||
// ID
|
||||
const unionId = body?.data?.unionId;
|
||||
// 用户名
|
||||
const userName = body?.data?.baseInfo?.nickName;
|
||||
// 头像
|
||||
const avatar = body?.data?.baseInfo?.headImgUrl;
|
||||
|
||||
const newData = {
|
||||
"userId": unionId,
|
||||
"avatar": avatar,
|
||||
"token": token,
|
||||
"userName": userName,
|
||||
}
|
||||
|
||||
userCookie = userCookie ? JSON.parse(userCookie) : [];
|
||||
const index = userCookie.findIndex(e => e.userId == newData.userId);
|
||||
|
||||
userCookie[index] ? userCookie[index] = newData : userCookie.push(newData);
|
||||
|
||||
$.setjson(userCookie, ckName);
|
||||
$.msg($.name, `🎉${newData.userName}更新token成功!`, ``);
|
||||
}
|
||||
//自动生成token
|
||||
async function getWxToken(code) {
|
||||
try {
|
||||
const { fhNonceStr, fhTimestamp, fhSign } = getSignature({code});
|
||||
const options = {
|
||||
url: `https://www.feihevip.com/api/wechat/auth/miniAssets`,
|
||||
type: "post",
|
||||
dataType: "json",
|
||||
headers: {
|
||||
"Host": "www.feihevip.com",
|
||||
"token": '',
|
||||
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.48(0x1800302b) NetType/4G Language/zh_CN",
|
||||
"Referer": "https://servicewechat.com/wx4205ec55b793245e/366/page-frame.html",
|
||||
"fhAppid": appid,
|
||||
"source": 1,
|
||||
fhNonceStr,
|
||||
fhTimestamp,
|
||||
fhSign
|
||||
},
|
||||
body: {
|
||||
code
|
||||
}
|
||||
};
|
||||
//post方法
|
||||
let result = await Request(options);
|
||||
let token = result?.data?.token;
|
||||
debug(result, '获取token');
|
||||
return token;
|
||||
} catch (e) {
|
||||
$.log(`❌getWxToken run error => ${e}`)
|
||||
}
|
||||
}
|
||||
|
||||
//检查code服务器
|
||||
async function checkCodeServer(appid) {
|
||||
// 环境变量
|
||||
$.codeServer = $.isNode() ? process.env["CODESERVER_ADDRESS"] : $.getdata('@codeServer.address');
|
||||
// 需要获取的微信列表,用,分隔
|
||||
$.wxId = ($.isNode() ? process.env["CODESERVER_WXID"] : $.getdata('@codeServer.wxId')).split(",");
|
||||
// 获取codeList
|
||||
let codeList = await Promise.all($.wxId.map(e => getCode(e)));
|
||||
async function getCode(wxId) {
|
||||
try {
|
||||
const options = {
|
||||
url: `${$.codeServer}/api/Common/JSLogin`,
|
||||
headers: { "accept": "application/json", "content-type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
'wxId': wxId,
|
||||
'appId': appid
|
||||
})
|
||||
};
|
||||
let res = await $.http.post(options);
|
||||
res = $.toObj(res?.body);
|
||||
return res?.Data?.code;
|
||||
} catch (e) {
|
||||
$.log(e);
|
||||
}
|
||||
}
|
||||
debug(codeList);
|
||||
!codeList.length
|
||||
? $.log(`❌获取code授权失败!请检查服务器运行是否正常 => 尝试读取数据持久化 `)
|
||||
: $.log(`✅获取code授权成功!当前code数量为${codeList.length}`);
|
||||
let userList = await Promise.all(codeList.map(async (code) => {
|
||||
const token = await getWxToken(code);
|
||||
const newToken = await refreshToken(token);
|
||||
debug(newToken)
|
||||
return { "token": newToken };
|
||||
}));
|
||||
userList = userList.filter(value => Object.keys(value).length !== 0)
|
||||
return userList;
|
||||
}
|
||||
//检查环境变量
|
||||
async function checkEnv() {
|
||||
try {
|
||||
if (!userCookie) {
|
||||
throw new Error(`❌未检测到环境变量 ${ckName},请先配置`);
|
||||
}
|
||||
|
||||
let usersToAdd = [];
|
||||
|
||||
// 如果是字符串,尝试解析
|
||||
if (typeof userCookie === 'string') {
|
||||
// 尝试解析为JSON
|
||||
try {
|
||||
const parsed = JSON.parse(userCookie);
|
||||
if (Array.isArray(parsed)) {
|
||||
usersToAdd = parsed;
|
||||
} else {
|
||||
usersToAdd = [parsed];
|
||||
}
|
||||
} catch (e) {
|
||||
// 不是JSON格式,按分隔符处理
|
||||
const separator = envSplitor.find(s => userCookie.includes(s)) || envSplitor[0];
|
||||
const tokens = userCookie.split(separator).map(t => t.trim()).filter(Boolean);
|
||||
usersToAdd = tokens.map(token => ({ token }));
|
||||
}
|
||||
} else if (Array.isArray(userCookie)) {
|
||||
usersToAdd = userCookie;
|
||||
} else {
|
||||
usersToAdd = [userCookie];
|
||||
}
|
||||
|
||||
if (!usersToAdd.length) {
|
||||
throw new Error(`❌未找到有效的token数据`);
|
||||
}
|
||||
|
||||
userList.push(...usersToAdd.map(n => new UserInfo(n)).filter(Boolean));
|
||||
|
||||
userCount = userList.length;
|
||||
console.log(`✅ 共找到 ${userCount} 个账号`);
|
||||
return true;
|
||||
} catch (e) {
|
||||
throw new Error(`❌checkEnv run error => ${e}`)
|
||||
}
|
||||
}
|
||||
//请求二次封装
|
||||
async function Request(o) {
|
||||
if (typeof o === 'string') o = { url: o };
|
||||
try {
|
||||
if (!o?.url) throw new Error('[发送请求] 缺少 url 参数');
|
||||
// type => 因为env中使用method处理post的特殊请求(put/delete/patch), 所以这里使用type
|
||||
let { url: u, type, headers = {}, body: b, params, dataType = 'form', resultType = 'data' } = o;
|
||||
// post请求需要处理params参数(get不需要, env已经处理)
|
||||
const method = type ? type?.toLowerCase() : ('body' in o ? 'post' : 'get');
|
||||
const url = u.concat(method === 'post' ? '?' + $.queryStr(params) : '');
|
||||
|
||||
const timeout = o.timeout ? ($.isSurge() ? o.timeout / 1e3 : o.timeout) : 1e4
|
||||
// 根据jsonType处理headers
|
||||
if (dataType === 'json') headers['Content-Type'] = 'application/json;charset=UTF-8';
|
||||
// post请求处理body
|
||||
const body = b && dataType == 'form' ? $.queryStr(b) : $.toStr(b);
|
||||
const request = { ...o, ...(o?.opts ? o.opts : {}), url, headers, ...(method === 'post' && { body }), ...(method === 'get' && params && { params }), timeout: timeout }
|
||||
const httpPromise = $.http[method.toLowerCase()](request)
|
||||
.then(response => resultType == 'data' ? ($.toObj(response.body) || response.body) : ($.toObj(response) || response))
|
||||
.catch(err => $.log(`❌请求发起失败!原因为:${err}`));
|
||||
// 使用Promise.race来强行加入超时处理
|
||||
return Promise.race([
|
||||
new Promise((_, e) => setTimeout(() => e('当前请求已超时'), timeout)),
|
||||
httpPromise
|
||||
]);
|
||||
} catch (e) {
|
||||
console.log(`❌请求发起失败!原因为:${e}`);
|
||||
}
|
||||
};
|
||||
//生成随机数
|
||||
function randomInt(n, r) {
|
||||
return Math.round(Math.random() * (r - n) + n)
|
||||
};
|
||||
//控制台打印
|
||||
function DoubleLog(data) {
|
||||
if (data && $.isNode()) {
|
||||
console.log(`${data}`);
|
||||
$.notifyMsg.push(`${data}`)
|
||||
} else if (data) {
|
||||
console.log(`${data}`);
|
||||
$.notifyMsg.push(`${data}`)
|
||||
}
|
||||
};
|
||||
//调试
|
||||
function debug(t, l = 'debug') {
|
||||
if ($.is_debug === 'true') {
|
||||
$.log(`\n-----------${l}------------\n`);
|
||||
$.log(typeof t == "string" ? t : $.toStr(t) || `debug error => t=${t}`);
|
||||
$.log(`\n-----------${l}------------\n`)
|
||||
}
|
||||
};
|
||||
//对多账号通知进行兼容
|
||||
async function SendMsgList(l) {
|
||||
await Promise.allSettled(l?.map(u => SendMsg(u.message.join('\n'), u.avatar)));
|
||||
};
|
||||
//账号通知
|
||||
async function SendMsg(n, o) {
|
||||
n && (0 < Notify ? $.isNode() ? await notify.sendNotify($.name, n) : $.msg($.name, $.title || "", n, {
|
||||
"media-url": o
|
||||
}) : console.log(n))
|
||||
};
|
||||
//转换为小写
|
||||
function ObjectKeys2LowerCase(obj) { return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k.toLowerCase(), v])) };
|
||||
|
||||
// 获取签名
|
||||
function getSignature(data) {
|
||||
const json = data ? JSON.stringify(data) : ''
|
||||
const fhNonceStr = getFhNonceStr({ length: 16 })
|
||||
const fhTimestamp = getTimestamp()
|
||||
const signString = `fhAppid${appid}fhNonceStr${fhNonceStr}fhTimestamp${fhTimestamp}${json}${appKey}`
|
||||
// debug(signString + '->' + md5(signString).toUpperCase(), '签名字符串')
|
||||
return {
|
||||
fhNonceStr,
|
||||
fhTimestamp,
|
||||
fhSign: md5(signString).toUpperCase()
|
||||
}
|
||||
}
|
||||
function getSignature2() {
|
||||
const fhNonceStr = getFhNonceStr({ length: 16 })
|
||||
const fhTimestamp = getTimestamp()
|
||||
const signString = `fhAppidxmhfhNonceStr${fhNonceStr}fhTimestamp${fhTimestamp}98d9fe9b613a479dbcb111ca261e3ce1`
|
||||
// debug(signString + '->' + md5(signString).toUpperCase(), '签名字符串')
|
||||
return {
|
||||
fhNonceStr,
|
||||
fhTimestamp,
|
||||
fhSign: md5(signString).toUpperCase()
|
||||
}
|
||||
}
|
||||
// 获取10位时间戳
|
||||
function getTimestamp() {
|
||||
return +String(Date.now()).slice(0, 10)
|
||||
}
|
||||
// 获取随机字符串
|
||||
function getFhNonceStr(t) { var e, r, n = "", o = (t = function (t) { return t || (t = {}), { length: t.length || 8, numeric: "boolean" != typeof t.numeric || t.numeric, letters: "boolean" != typeof t.letters || t.letters, special: "boolean" == typeof t.special && t.special, exclude: Array.isArray(t.exclude) ? t.exclude : [] } }(t)).length; t.exclude; var i = function (t) { var e = ""; t.numeric && (e += "0123456789"), t.letters && (e += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), t.special && (e += "!$%^&*()_+|~-=`{}[]:;<>?,./"); for (var r = 0; r <= t.exclude.length; r++)e = e.replace(t.exclude[r], ""); return e }(t); for (e = 1; e <= o; e++)n += i.substring(r = Math.floor(Math.random() * i.length), r + 1); return n }
|
||||
|
||||
//---------------------- 主程序执行入口 -----------------------------------
|
||||
!(async () => {
|
||||
if (typeof $request != "undefined") {
|
||||
await getCookie();
|
||||
} else {
|
||||
if (!(await checkEnv())) throw new Error(`❌未检测到ck,请添加环境变量`);
|
||||
if (userList.length > 0) await main();
|
||||
}
|
||||
})()
|
||||
.catch(e => $.notifyMsg.push(e.message || e))
|
||||
.finally(async () => {
|
||||
// 新增:获取随机古诗词
|
||||
let poetry = await getRandomPoetry();
|
||||
|
||||
// 合并所有通知消息
|
||||
let finalMessage = [poetry]; // 将诗词放在开头
|
||||
let avatars = [];
|
||||
|
||||
// 处理账号通知
|
||||
for (const user of $.notifyList) {
|
||||
if (user.message.length > 0) {
|
||||
finalMessage.push(`📱 账号${user.id}\n${user.message.join('\n')}`);
|
||||
avatars.push(user.avatar);
|
||||
}
|
||||
}
|
||||
|
||||
// 添加错误通知
|
||||
if ($.notifyMsg.length > 0) {
|
||||
finalMessage.push(`❌ 错误信息:\n${$.notifyMsg.join('\n')}`);
|
||||
}
|
||||
|
||||
if (finalMessage.length > 0) {
|
||||
// 合并消息并发送
|
||||
const combinedMessage = finalMessage.join('\n\n──────────────\n\n');
|
||||
const firstValidAvatar = avatars.find(avatar => avatar) || '';
|
||||
|
||||
await SendMsg(combinedMessage, firstValidAvatar);
|
||||
}
|
||||
|
||||
$.done({ ok: 1 });
|
||||
});
|
||||
|
||||
// 新增:获取随机古诗词函数
|
||||
async function getRandomPoetry() {
|
||||
try {
|
||||
const url = 'https://v2.jinrishici.com/sentence';
|
||||
const res = await Request({
|
||||
url,
|
||||
headers: {
|
||||
'X-User-Token': '+SBGb0hF88lM7xdBcWe4t4jQCMeBXBzJ' // 示例token,建议申请自己的
|
||||
}
|
||||
});
|
||||
|
||||
if (res?.data?.content) {
|
||||
return `📜 ${res.data.content}\n —— ${res.data.origin.author}《${res.data.origin.title}》`;
|
||||
}
|
||||
} catch (e) {
|
||||
$.log('获取诗词失败,使用默认句子');
|
||||
}
|
||||
|
||||
// 备用默认句子
|
||||
const defaultPoems = [
|
||||
'及时当勉励,岁月不待人。——陶渊明《杂诗》',
|
||||
'会当凌绝顶,一览众山小。——杜甫《望岳》',
|
||||
'长风破浪会有时,直挂云帆济沧海。——李白《行路难》'
|
||||
];
|
||||
return `📜 ${defaultPoems[Math.floor(Math.random() * defaultPoems.length)]}`;
|
||||
}
|
||||
/** ---------------------------------固定不动区域----------------------------------------- */
|
||||
// prettier-ignore
|
||||
//From chavyleung's Env.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, r) => { s.call(this, t, ((t, s, a) => { t ? r(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.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) { try { return JSON.stringify(t) } 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, r) => e(r))) })) } runScript(t, e) { return new Promise((s => { let r = this.getdata("@chavy_boxjs_userCfgs.httpapi"); r = r ? r.replace(/\n/g, "").trim() : r; let a = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); a = a ? 1 * a : 20, a = e && e.timeout ? e.timeout : a; const [i, o] = r.split("@"), n = { url: `http://${o}/v1/scripting/evaluate`, body: { script_text: t, mock_type: "cron", timeout: a }, headers: { "X-Key": i, Accept: "*/*" }, timeout: a }; this.post(n, ((t, e, r) => s(r))) })).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), r = !s && this.fs.existsSync(e); if (!s && !r) return {}; { const r = s ? t : e; try { return JSON.parse(this.fs.readFileSync(r)) } 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), r = !s && this.fs.existsSync(e), a = JSON.stringify(this.data); s ? this.fs.writeFileSync(t, a) : r ? this.fs.writeFileSync(e, a) : this.fs.writeFileSync(t, a) } } lodash_get(t, e, s = void 0) { const r = e.replace(/\[(\d+)\]/g, ".$1").split("."); let a = t; for (const t of r) if (a = Object(a)[t], void 0 === a) return s; return a } lodash_set(t, e, s) { return Object(t) !== t || (Array.isArray(e) || (e = e.toString().match(/[^.[\]]+/g) || []), e.slice(0, -1).reduce(((t, s, r) => Object(t[s]) === t[s] ? t[s] : t[s] = Math.abs(e[r + 1]) >> 0 == +e[r + 1] ? [] : {}), t)[e[e.length - 1]] = s), t } getdata(t) { let e = this.getval(t); if (/^@/.test(t)) { const [, s, r] = /^@(.*?)\.(.*?)$/.exec(t), a = s ? this.getval(s) : ""; if (a) try { const t = JSON.parse(a); e = t ? this.lodash_get(t, r, "") : e } catch (t) { e = "" } } return e } setdata(t, e) { let s = !1; if (/^@/.test(e)) { const [, r, a] = /^@(.*?)\.(.*?)$/.exec(e), i = this.getval(r), o = r ? "null" === i ? null : i || "{}" : "{}"; try { const e = JSON.parse(o); this.lodash_set(e, a, t), s = this.setval(JSON.stringify(e), r) } catch (e) { const i = {}; this.lodash_set(i, a, t), s = this.setval(JSON.stringify(i), r) } } else s = this.setval(t, e); return s } getval(t) { switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": return $persistentStore.read(t); case "Quantumult X": return $prefs.valueForKey(t); case "Node.js": return this.data = this.loaddata(), this.data[t]; default: return this.data && this.data[t] || null } } setval(t, e) { switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": return $persistentStore.write(t, e); case "Quantumult X": return $prefs.setValueForKey(t, e); case "Node.js": return this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0; default: return this.data && this.data[e] || null } } initGotEnv(t) { this.got = this.got ? this.got : require("got"), this.cktough = this.cLine truncated
|
||||
|
||||
// md5
|
||||
function md5(md5str) {
|
||||
var createMD5String = function (string) { var x = Array(); var k, AA, BB, CC, DD, a, b, c, d; var S11 = 7, S12 = 12, S13 = 17, S14 = 22; var S21 = 5, S22 = 9, S23 = 14, S24 = 20; var S31 = 4, S32 = 11, S33 = 16, S34 = 23; var S41 = 6, S42 = 10, S43 = 15, S44 = 21; string = uTF8Encode(string); x = convertToWordArray(string); a = 1732584193; b = 4023233417; c = 2562383102; d = 271733878; for (k = 0; k < x.length; k += 16) { AA = a; BB = b; CC = c; DD = d; a = FF(a, b, c, d, x[k + 0], S11, 3614090360); d = FF(d, a, b, c, x[k + 1], S12, 3905402710); c = FF(c, d, a, b, x[k + 2], S13, 606105819); b = FF(b, c, d, a, x[k + 3], S14, 3250441966); a = FF(a, b, c, d, x[k + 4], S11, 4118548399); d = FF(d, a, b, c, x[k + 5], S12, 1200080426); c = FF(c, d, a, b, x[k + 6], S13, 2821735955); b = FF(b, c, d, a, x[k + 7], S14, 4249261313); a = FF(a, b, c, d, x[k + 8], S11, 1770035416); d = FF(d, a, b, c, x[k + 9], S12, 2336552879); c = FF(c, d, a, b, x[k + 10], S13, 4294925233); b = FF(b, c, d, a, x[k + 11], S14, 2304563134); a = FF(a, b, c, d, x[k + 12], S11, 1804603682); d = FF(d, a, b, c, x[k + 13], S12, 4254626195); c = FF(c, d, a, b, x[k + 14], S13, 2792965006); b = FF(b, c, d, a, x[k + 15], S14, 1236535329); a = GG(a, b, c, d, x[k + 1], S21, 4129170786); d = GG(d, a, b, c, x[k + 6], S22, 3225465664); c = GG(c, d, a, b, x[k + 11], S23, 643717713); b = GG(b, c, d, a, x[k + 0], S24, 3921069994); a = GG(a, b, c, d, x[k + 5], S21, 3593408605); d = GG(d, a, b, c, x[k + 10], S22, 38016083); c = GG(c, d, a, b, x[k + 15], S23, 3634488961); b = GG(b, c, d, a, x[k + 4], S24, 3889429448); a = GG(a, b, c, d, x[k + 9], S21, 568446438); d = GG(d, a, b, c, x[k + 14], S22, 3275163606); c = GG(c, d, a, b, x[k + 3], S23, 4107603335); b = GG(b, c, d, a, x[k + 8], S24, 1163531501); a = GG(a, b, c, d, x[k + 13], S21, 2850285829); d = GG(d, a, b, c, x[k + 2], S22, 4243563512); c = GG(c, d, a, b, x[k + 7], S23, 1735328473); b = GG(b, c, d, a, x[k + 12], S24, 2368359562); a = HH(a, b, c, d, x[k + 5], S31, 4294588738); d = HH(d, a, b, c, x[k + 8], S32, 2272392833); c = HH(c, d, a, b, x[k + 11], S33, 1839030562); b = HH(b, c, d, a, x[k + 14], S34, 4259657740); a = HH(a, b, c, d, x[k + 1], S31, 2763975236); d = HH(d, a, b, c, x[k + 4], S32, 1272893353); c = HH(c, d, a, b, x[k + 7], S33, 4139469664); b = HH(b, c, d, a, x[k + 10], S34, 3200236656); a = HH(a, b, c, d, x[k + 13], S31, 681279174); d = HH(d, a, b, c, x[k + 0], S32, 3936430074); c = HH(c, d, a, b, x[k + 3], S33, 3572445317); b = HH(b, c, d, a, x[k + 6], S34, 76029189); a = HH(a, b, c, d, x[k + 9], S31, 3654602809); d = HH(d, a, b, c, x[k + 12], S32, 3873151461); c = HH(c, d, a, b, x[k + 15], S33, 530742520); b = HH(b, c, d, a, x[k + 2], S34, 3299628645); a = II(a, b, c, d, x[k + 0], S41, 4096336452); d = II(d, a, b, c, x[k + 7], S42, 1126891415); c = II(c, d, a, b, x[k + 14], S43, 2878612391); b = II(b, c, d, a, x[k + 5], S44, 4237533241); a = II(a, b, c, d, x[k + 12], S41, 1700485571); d = II(d, a, b, c, x[k + 3], S42, 2399980690); c = II(c, d, a, b, x[k + 10], S43, 4293915773); b = II(b, c, d, a, x[k + 1], S44, 2240044497); a = II(a, b, c, d, x[k + 8], S41, 1873313359); d = II(d, a, b, c, x[k + 15], S42, 4264355552); c = II(c, d, a, b, x[k + 6], S43, 2734768916); b = II(b, c, d, a, x[k + 13], S44, 1309151649); a = II(a, b, c, d, x[k + 4], S41, 4149444226); d = II(d, a, b, c, x[k + 11], S42, 3174756917); c = II(c, d, a, b, x[k + 2], S43, 718787259); b = II(b, c, d, a, x[k + 9], S44, 3951481745); a = addUnsigned(a, AA); b = addUnsigned(b, BB); c = addUnsigned(c, CC); d = addUnsigned(d, DD) } var tempValue = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d); return tempValue.toLowerCase() }; var rotateLeft = function (lValue, iShiftBits) { return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits)) }; var addUnsigned = function (lX, lY) { var lX4, lY4, lX8, lY8, lResult; lX8 = (lX & 2147483648); lY8 = (lY & 2147483648); lX4 = (lX & 1073741824); lY4 = (lY & 1073741824); lResult = (lX & 1073741823) + (lY & 1073741823); if (lX4 & lY4) { return (lResult ^ 2147483648 ^ lX8 ^ lY8) } if (lX4 | lY4) { if (lResult & 1073741824) { return (lResult ^ 3221225472 ^ lX8 ^ lY8) } else { return (lResult ^ 1073741824 ^ lX8 ^ lY8) } } else { return (lResult ^ lX8 ^ lY8) } }; var F = function (x, y, z) { return (x & y) | ((~x) & z) }; var G = function (x, y, z) { return (x & z) | (y & (~z)) }; var H = function (x, y, z) { return (x ^ y ^ z) }; var I = function (x, y, z) { return (y ^ (x | (~z))) }; var FF = function (a, b, c, d, x, s, ac) { a = addUnsigned(a, addUnsigned(addUnsigned(F(b, c, d), x), ac)); return addUnsigned(rotateLeft(a, s), b) }; var GG = function (a, b, c, d, x, s, ac) { a = addUnsigned(a, addUnsigned(addUnsigned(G(b, c, d), x), ac)); return addUnsigned(rotateLeft(a, s), b) }; var HH = function (a, b, c, d, x, s, ac) { a = addUnsigned(a, addUnsigned(addUnsigned(H(b, c, d), x), ac)); return addUnsigned(rotateLeft(a, s), b) }; var II = function (a, b, c, d, x, s, ac) { a = addUnLine truncated
|
||||
var WordToHexValue = "", WordToHexValueTemp = "", lByte, lCount; for (lCount = 0; lCount <= 3; lCount++) {
|
||||
lByte = (lValue >>> (lCount * 8)) & 255; WordToHexValueTemp = "0" + lByte.toString(16);
|
||||
WordToHexValue = WordToHexValue + WordToHexValueTemp.substr(WordToHexValueTemp.length - 2, 2)
|
||||
} return WordToHexValue
|
||||
}; var uTF8Encode = function (string) { string = string.toString().replace(/\x0d\x0a/g, "\x0a"); var output = ""; for (var n = 0; n < string.length; n++) { var c = string.charCodeAt(n); if (c < 128) { output += String.fromCharCode(c) } else { if ((c > 127) && (c < 2048)) { output += String.fromCharCode((c >> 6) | 192); output += String.fromCharCode((c & 63) | 128) } else { output += String.fromCharCode((c >> 12) | 224); output += String.fromCharCode(((c >> 6) & 63) | 128); output += String.fromCharCode((c & 63) | 128) } } } return output }; return createMD5String(md5str)
|
||||
};
|
||||
@@ -1,308 +0,0 @@
|
||||
/*
|
||||
青龙脚本:星妈会自动任务 + 自动获取 cuk(通用 code_url)
|
||||
作者:ChatGPT 整合最终版
|
||||
|
||||
环境变量:
|
||||
soy_wxid_data → 多个 wxid,换行分隔
|
||||
soy_codeurl_data → 通用 code 获取地址
|
||||
|
||||
流程:
|
||||
wxid → 请求 code → 请求 autologin → 得到 cuk →
|
||||
构造 XMH_COOKIE 内容执行星妈会任务
|
||||
*/
|
||||
|
||||
const axios = require("axios");
|
||||
const notify = require('./sendNotify');
|
||||
|
||||
// =======================
|
||||
// 工具
|
||||
// =======================
|
||||
function sleep(ms){ return new Promise(res => setTimeout(res, ms)); }
|
||||
|
||||
function parseEnvList(name) {
|
||||
const raw = process.env[name] || "";
|
||||
return raw.split("\n").map(x => x.trim()).filter(x => x);
|
||||
}
|
||||
|
||||
function parseEnvStr(name) {
|
||||
return (process.env[name] || "").trim();
|
||||
}
|
||||
|
||||
// =======================
|
||||
// 第1步:读取环境变量
|
||||
// =======================
|
||||
const wxidList = parseEnvList("soy_wxid_data");
|
||||
const codeUrl = parseEnvStr("soy_codeurl_data");
|
||||
|
||||
if (wxidList.length === 0 || !codeUrl) {
|
||||
console.log("❌ 环境变量为空,请检查 soy_wxid_data 或 soy_codeurl_data");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
console.log(`🟢 读取到 ${wxidList.length} 个账号`);
|
||||
console.log(`🟢 通用 code_url: ${codeUrl}`);
|
||||
|
||||
// =======================
|
||||
// 第2步:获取 code
|
||||
// =======================
|
||||
async function getCode(wxid) {
|
||||
try {
|
||||
const body = { appid: "wxc83b55d61c7fc51d", wxid };
|
||||
const res = await axios.post(codeUrl, body, { timeout: 10000 });
|
||||
if (res.data?.status && res.data?.Data?.code) {
|
||||
console.log(`⭐ 获取 code 成功: ${wxid}`);
|
||||
return res.data.Data.code;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(`❌ 获取 code 失败:${wxid} →`, e.message);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// =======================
|
||||
// 第3步:code → cuk
|
||||
// =======================
|
||||
async function getCuk(code){
|
||||
const api = `https://momclub.feihe.com/pmall/c/login/autologin?code=${code}`;
|
||||
try {
|
||||
const res = await axios.get(api, {
|
||||
headers: {
|
||||
"cuk": "undefined",
|
||||
"User-Agent": "Mozilla/5.0",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
timeout: 10000
|
||||
});
|
||||
if (res.data?.code === "000000") {
|
||||
const cuk = res.data.data.cuk;
|
||||
console.log(`🎉 cuk 获取成功`);
|
||||
return cuk;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(`❌ cuk 获取失败:`, e.message);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// =======================
|
||||
// 构造最终 XMH_COOKIE 列表
|
||||
// =======================
|
||||
async function buildCookieList() {
|
||||
const result = [];
|
||||
for (let i=0;i<wxidList.length;i++){
|
||||
const wxid = wxidList[i];
|
||||
console.log(`\n========== 账号 ${i+1} ==========`);
|
||||
|
||||
const code = await getCode(wxid);
|
||||
if (!code) continue;
|
||||
|
||||
await sleep(1500);
|
||||
|
||||
const cuk = await getCuk(code);
|
||||
if (!cuk) continue;
|
||||
|
||||
result.push(`${cuk}#${wxid}`);
|
||||
await sleep(2000);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// =======================
|
||||
// 星妈会任务类
|
||||
// =======================
|
||||
const API_HOST = "https://momclub.feihe.com";
|
||||
|
||||
function init() {
|
||||
return {
|
||||
isNode: () => true,
|
||||
http: axios,
|
||||
wait: (ms) => new Promise(resolve => setTimeout(resolve, ms)),
|
||||
log: console.log
|
||||
};
|
||||
}
|
||||
const $ = init();
|
||||
|
||||
class XingMaHui {
|
||||
constructor(cuk, index, remark='') {
|
||||
this.cuk = cuk;
|
||||
this.index = index;
|
||||
this.remark = remark;
|
||||
this.accountName = remark ? `账号${index}(${remark})` : `账号${index}`;
|
||||
this.creditsEarned = 0;
|
||||
this.taskResults = [];
|
||||
this.userInfo = null;
|
||||
this.initialPoints = 0;
|
||||
this.finalPoints = 0;
|
||||
}
|
||||
|
||||
getHeaders(){
|
||||
return {
|
||||
'Host': 'momclub.feihe.com',
|
||||
'cuk': this.cuk,
|
||||
'User-Agent': 'Mozilla/5.0',
|
||||
'Content-Type': 'application/json'
|
||||
};
|
||||
}
|
||||
|
||||
async request(url, method="GET", data=null){
|
||||
try {
|
||||
const config = { headers: this.getHeaders(), timeout: 10000 };
|
||||
let res = null;
|
||||
if (method === "GET") {
|
||||
res = await $.http.get(url, config);
|
||||
} else {
|
||||
res = await $.http.post(url, data, config);
|
||||
}
|
||||
return res.data;
|
||||
} catch (e) {
|
||||
console.log("❌ 请求异常:", e.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async getUserInfo(){
|
||||
const url = `${API_HOST}/pmall/c/user/memberInfo`;
|
||||
const r = await this.request(url);
|
||||
if (r?.code === "000000") {
|
||||
this.userInfo = r.data;
|
||||
return r.data;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async getTaskList(){
|
||||
const url = `${API_HOST}/pmall/c/activity/todo/list?mockTime=${Date.now()}`;
|
||||
const r = await this.request(url);
|
||||
if (r?.code === "000000") return r.data;
|
||||
return null;
|
||||
}
|
||||
|
||||
async queryTaskCredits(name){
|
||||
const url = `${API_HOST}/pmall/c/activity/todo/queryTodoResult`;
|
||||
const r = await this.request(url);
|
||||
if (r?.code === "000000") {
|
||||
const t = r.data.find(x => x.taskName === name);
|
||||
return t?.actualCredits || 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
async doCheckIn(id, name){
|
||||
const url = `${API_HOST}/pmall/c/activity/todo/checkIn`;
|
||||
const data = { activityId:id, mockTime: Date.now() };
|
||||
console.log(`➡ 签到:${name}`);
|
||||
const r = await this.request(url, "POST", data);
|
||||
if (r?.code === "000000") {
|
||||
const c = r.data.credits || 1;
|
||||
this.creditsEarned += c;
|
||||
this.taskResults.push(`签到 ${name} +${c}`);
|
||||
}
|
||||
}
|
||||
|
||||
async doNormalTask(id, name){
|
||||
console.log(`➡ 普通任务:${name}`);
|
||||
const r1 = await this.request(`${API_HOST}/pmall/c/activity/todo/receive`, "POST",
|
||||
{activityId:id, mockTime:Date.now()}
|
||||
);
|
||||
if (r1?.code !== "000000") return;
|
||||
|
||||
await $.wait(1000);
|
||||
|
||||
const r2 = await this.request(`${API_HOST}/pmall/c/activity/todo/complete`, "POST",
|
||||
{activityId:id, mockTime:Date.now()}
|
||||
);
|
||||
if (r2?.code !== "000000") return;
|
||||
|
||||
await $.wait(1000);
|
||||
const credits = await this.queryTaskCredits(name);
|
||||
this.creditsEarned += credits;
|
||||
this.taskResults.push(`${name} +${credits}`);
|
||||
}
|
||||
|
||||
async doAllTasks(){
|
||||
console.log(`\n⭐ 开始执行 ${this.accountName}`);
|
||||
|
||||
await this.getUserInfo();
|
||||
if (this.userInfo) this.initialPoints = this.userInfo.points;
|
||||
|
||||
const list = await this.getTaskList();
|
||||
if (!list) return;
|
||||
|
||||
if (list.checkInTodo) await this.doCheckIn(list.checkInTodo.id, list.checkInTodo.name);
|
||||
|
||||
if (list.taskTodo) {
|
||||
for (const t of list.taskTodo) {
|
||||
const type = t.taskTodoExtra?.type;
|
||||
if (type === "AddQw" || type === "FirstOrder") continue;
|
||||
await this.doNormalTask(t.id, t.name);
|
||||
}
|
||||
}
|
||||
|
||||
await this.getUserInfo();
|
||||
if (this.userInfo) this.finalPoints = this.userInfo.points;
|
||||
}
|
||||
|
||||
getResults(){
|
||||
return {
|
||||
account: this.accountName,
|
||||
initial: this.initialPoints,
|
||||
final: this.finalPoints,
|
||||
gained: this.creditsEarned,
|
||||
tasks: this.taskResults,
|
||||
user: this.userInfo
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// =======================
|
||||
// 主执行
|
||||
// =======================
|
||||
(async () => {
|
||||
console.log("\n🚀 开始获取 cuk ...\n");
|
||||
|
||||
const cookieList = await buildCookieList();
|
||||
if (cookieList.length === 0) {
|
||||
console.log("❌ 无法获取任何 cuk,退出");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`\n⭐ 总共获取 ${cookieList.length} 个 cuk\n`);
|
||||
|
||||
const allAccounts = [];
|
||||
let totalCredits = 0;
|
||||
|
||||
for (let i=0;i<cookieList.length;i++){
|
||||
const [cuk, remark] = cookieList[i].split("#");
|
||||
const acc = new XingMaHui(cuk, i+1, remark);
|
||||
allAccounts.push(acc);
|
||||
}
|
||||
|
||||
console.log("🚀 开始执行星妈会任务...\n");
|
||||
|
||||
for (const acc of allAccounts){
|
||||
await acc.doAllTasks();
|
||||
totalCredits += acc.creditsEarned;
|
||||
await sleep(3000);
|
||||
}
|
||||
|
||||
// 汇总结果
|
||||
let msg = "🎉 星妈会任务完成\n\n";
|
||||
for (const acc of allAccounts){
|
||||
const r = acc.getResults();
|
||||
msg += `📍 ${r.account}
|
||||
手机号:${r.user?.mobile || "未知"}
|
||||
初始积分:${r.initial}
|
||||
最终积分:${r.final}
|
||||
本次获得:${r.gained}
|
||||
|
||||
任务:
|
||||
${r.tasks.map(t=>" - "+t).join("\n")}
|
||||
|
||||
-------------------\n`;
|
||||
}
|
||||
msg += `\n⭐ 今日总积分:${totalCredits}`;
|
||||
|
||||
console.log(msg);
|
||||
await notify.sendNotify("星妈会任务完成", msg);
|
||||
|
||||
})();
|
||||
Reference in new issue
Block a user