Create bz公益.js

This commit is contained in:
XiaoGe-LiBai
2025-12-10 15:07:22 +08:00
parent de0bbe7171
commit 39263f5a84

330
bz公益.js Normal file
View File

@@ -0,0 +1,330 @@
/*
* @File: lucky_sign_lottery.js
* @Description: 适用于 lucky.5202030.xyz 的全自动脚本
* @Version: 2.0.0
* @Features:
* 1. 每日自动签到
* 2. 每日/每周/每月福利自动领取 (New)
* 3. 自动抽奖 (直到次数耗尽)
* 4. Token 过期/无效时自动使用账号密码登录 (New)
* * @Usage:
* 1. 在青龙面板 "依赖管理" -> "NodeJs" 中,确保安装 `axios`。
* 2. 在 "环境变量" 中添加以下变量:
* - LUCKY_XYZ_USERNAME: 你的登录用户名 (必填用于Token过期时自动登录)
* - LUCKY_XYZ_PASSWORD: 你的登录密码 (必填用于Token过期时自动登录)
* - LUCKY_XYZ_TOKEN: (可选) 如果你不想填账号密码,可直接填 Bearer Token。
* * 3. 设置定时任务,建议每天 00:10 执行: "10 0 * * *"
*/
const axios = require('axios');
// ================= 配置区域 =================
// 环境变量名称
const ENV = {
TOKEN: 'LUCKY_XYZ_TOKEN',
USER: 'LUCKY_XYZ_USERNAME',
PASS: 'LUCKY_XYZ_PASSWORD'
};
// API 端点
const API = {
LOGIN: 'https://lucky.5202030.xyz/api/auth/login/password',
SIGN: 'https://lucky.5202030.xyz/api/sign/',
LOTTERY: 'https://lucky.5202030.xyz/api/lottery/',
CLAIM: 'https://lucky.5202030.xyz/api/lucky-code/privileges/claim/all' // 新增福利接口
};
// 配置参数
const CONFIG = {
LOTTERY_DELAY: 500, // 抽奖间隔(ms)
MAX_ATTEMPTS: 200, // 最大抽奖次数保护
USER_AGENT: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36'
};
// 全局变量,用于存储运行时 Token
let CURRENT_TOKEN = process.env[ENV.TOKEN] || '';
// ================= 工具函数 =================
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// 获取最新的请求头
function getHeaders() {
return {
'accept': 'application/json, text/plain, */*',
'authorization': CURRENT_TOKEN.startsWith('Bearer') ? CURRENT_TOKEN : `Bearer ${CURRENT_TOKEN}`,
'content-type': 'application/json',
'origin': 'https://lucky.5202030.xyz',
'referer': 'https://lucky.5202030.xyz/',
'user-agent': CONFIG.USER_AGENT
};
}
// 格式化日志输出
function log(msg, type = 'info') {
const icon = {
info: '',
success: '✅',
warn: '⚠️',
error: '❌',
gift: '🎁',
money: '💰'
}[type] || '';
console.log(`${icon} ${msg}`);
}
// ================= 核心逻辑 =================
/**
* 核心功能:登录获取 Token
*/
async function doLogin() {
const username = process.env[ENV.USER];
const password = process.env[ENV.PASS];
if (!username || !password) {
log('未配置用户名或密码,无法执行自动登录。请检查环境变量。', 'error');
return false;
}
log(`正在尝试使用账号 [${username}] 登录...`, 'info');
try {
const response = await axios.post(API.LOGIN, {
username: username,
password: password
}, {
headers: {
'content-type': 'application/json',
'user-agent': CONFIG.USER_AGENT
}
});
const data = response.data;
if (data.success && data.data && data.data.access_token) {
// 更新全局 Token
CURRENT_TOKEN = `Bearer ${data.data.access_token}`;
log(`登录成功!当前余额: ${data.data.user.balance}`, 'success');
return true;
} else {
log(`登录失败: ${data.message}`, 'error');
return false;
}
} catch (error) {
log(`登录接口请求异常: ${error.message}`, 'error');
return false;
}
}
/**
* 通用请求包装器 (包含 401 自动重试逻辑)
* @param {Function} requestFn 实际的请求函数
* @param {string} taskName 任务名称
*/
async function requestWithRetry(requestFn, taskName) {
try {
// 如果没有 Token先尝试登录
if (!CURRENT_TOKEN) {
log('检测到 Token 为空,尝试自动登录...', 'warn');
const loginSuccess = await doLogin();
if (!loginSuccess) throw new Error('登录失败,无法继续执行任务');
}
return await requestFn();
} catch (error) {
// 捕获 401 Unauthorized 错误
if (error.response && error.response.status === 401) {
log(`Token 已过期或无效,正在尝试重新登录...`, 'warn');
const loginSuccess = await doLogin();
if (loginSuccess) {
log(`登录成功,重新执行任务: ${taskName}`, 'info');
return await requestFn(); // 重试一次
} else {
log(`重新登录失败,放弃任务: ${taskName}`, 'error');
}
} else {
throw error; // 其他错误直接抛出
}
}
}
/**
* 任务1每日签到
*/
async function doSignIn() {
console.log('\n--- 🟢 任务1: 每日签到 ---');
const execute = async () => {
const response = await axios.post(API.SIGN, null, { headers: getHeaders() });
const data = response.data;
if (data.success) {
log(`签到成功: ${data.message}`, 'success');
log(`获得奖励: ${data.reward}`, 'gift');
log(`当前余额: ${data.current_balance}`, 'money');
} else {
log(`签到结果: ${data.message}`, 'info');
}
};
try {
await requestWithRetry(execute, '每日签到');
} catch (error) {
log(`签到执行异常: ${error.message}`, 'error');
}
}
/**
* 任务2领取福利 (每日/每周/每月)
*/
async function doClaimPrivileges() {
console.log('\n--- 🟢 任务2: 领取特权福利 ---');
const execute = async () => {
const response = await axios.post(API.CLAIM, null, { headers: getHeaders() });
const data = response.data;
if (data.success) {
log(`${data.message}`, 'success');
// 解析并打印详细获得的物品
if (data.total_items && data.total_items.length > 0) {
console.log(' [获得物品清单]:');
data.total_items.forEach(item => {
// 简单的字典翻译,可根据实际情况补充
const itemNameMap = {
'time_rewind': '时光倒流(补签卡)',
'lucky_charm': '幸运符',
'revive_ticket': '复活票'
};
const name = itemNameMap[item.item_type] || item.item_type;
console.log(` - ${name} x ${item.quantity}`);
});
} else {
console.log(' - 本次没有获得新的物品 (可能已领取)');
}
} else {
log(`领取福利失败: ${data.message}`, 'warn');
}
};
try {
await requestWithRetry(execute, '领取福利');
} catch (error) {
log(`领取福利异常: ${error.message}`, 'error');
}
}
/**
* 任务3自动抽奖
*/
async function doLottery() {
console.log('\n--- 🟢 任务3: 自动抽奖 ---');
const stats = {
totalNet: 0,
draws: 0,
wins: 0,
losses: 0,
draws_0: 0,
endBalance: 0
};
let remainingAttempts = -1;
// 定义单次抽奖逻辑
const executeOneDraw = async () => {
return axios.post(API.LOTTERY, null, { headers: getHeaders() });
};
// 如果一开始就没 Token先登录一次避免循环里每次都判断
if (!CURRENT_TOKEN) {
if (!await doLogin()) return;
}
for (let i = 1; i <= CONFIG.MAX_ATTEMPTS; i++) {
try {
// 这里不使用 requestWithRetry 避免过于复杂的嵌套,
// 假设任务1和2通过后 Token 应该是有效的。
// 如果中途过期 (极少见)catch 块会捕获。
const response = await executeOneDraw();
const data = response.data;
if (data.success) {
stats.draws++;
stats.totalNet += data.net_change;
stats.endBalance = data.current_balance;
if (data.net_change > 0) stats.wins++;
else if (data.net_change < 0) stats.losses++;
else stats.draws_0++;
console.log(`[第${String(i).padStart(3, '0')}抽] ${data.message} | 变动: ${data.net_change} | 剩余: ${data.remaining_attempts}`);
remainingAttempts = data.remaining_attempts;
if (remainingAttempts === 0) {
log('今日抽奖次数已耗尽', 'info');
break;
}
} else {
log(`抽奖停止: ${data.message}`, 'warn');
break;
}
await delay(CONFIG.LOTTERY_DELAY);
} catch (error) {
// 如果中途 401尝试补救一次
if (error.response && error.response.status === 401) {
log('抽奖途中 Token 失效,尝试重连...', 'warn');
if (await doLogin()) {
i--; // 回退计数器,重试这一次
continue;
} else {
break; // 登录失败,彻底退出
}
}
log(`抽奖请求错误: ${error.message}`, 'error');
break;
}
}
// 统计报告
console.log('\n📊 [抽奖统计]');
if (stats.draws > 0) {
console.log(` - 总次数: ${stats.draws}`);
console.log(` - 盈利局: ${stats.wins}`);
console.log(` - 亏损局: ${stats.losses}`);
console.log(` - 最终余额: ${stats.endBalance}`);
console.log(` - 今日盈亏: ${stats.totalNet.toFixed(2)}`);
} else {
console.log(' - 未进行有效抽奖');
}
}
// ================= 主程序 =================
async function main() {
console.log(`🚀 Lucky.XYZ 自动脚本启动`);
// 1. 签到
await doSignIn();
// 2. 领福利 (中间间隔一下)
await delay(1000);
await doClaimPrivileges();
// 3. 抽奖
await delay(1000);
await doLottery();
console.log('\n🏁 所有任务执行完毕。');
}
main().catch(error => {
console.error('❌ 脚本致命错误:', error);
process.exit(1);
});