Continue seeded Qinglong script collection
This commit is contained in:
342
脚本库/APP版/账密/享玩游戏APP/2025-04-28_sudojia_xiangwan_659341f6.js
Normal file
342
脚本库/APP版/账密/享玩游戏APP/2025-04-28_sudojia_xiangwan_659341f6.js
Normal file
@@ -0,0 +1,342 @@
|
||||
// # Source: https://github.com/sudojia/AutoTaskScript/blob/script/src/client/sudojia_xiangwan.js
|
||||
// # Raw: https://raw.githubusercontent.com/sudojia/AutoTaskScript/script/src/client/sudojia_xiangwan.js
|
||||
// # Repo: sudojia/AutoTaskScript
|
||||
// # Path: src/client/sudojia_xiangwan.js
|
||||
// # UploadedAt: 2025-04-28T19:26:13+08:00
|
||||
// # SHA256: 659341f6d90da24ae84aff1ca890993bb08f62f22537ed7eca9ee139ad06e61d
|
||||
// # Category: APP版/账密
|
||||
// # Evidence: username/password/mobile/login
|
||||
//
|
||||
|
||||
/**
|
||||
* 享玩游戏APP
|
||||
* 下载链接:https://dl.duoyou.com/fenapk/xwshare/xw_100016.apk?version=1.3
|
||||
*
|
||||
* 会员v0:起始签到 10 个玩豆,连续签到递增 1 玩豆,最高签到 15 个玩豆
|
||||
* 会员v1-2:起始 15,最高 20
|
||||
* ...
|
||||
* 会员v10:起始 75,最高 80
|
||||
* 具体自行查看签到规则
|
||||
*
|
||||
* 以会员v0来计算(包含连签奖励):
|
||||
* 10 玩豆 兑换 0.1 现金,
|
||||
* 500 玩豆 兑换 5 现金,大约需 21 天
|
||||
* 1000 玩豆 兑换 10 现金,大约需 30 天
|
||||
* 5000 玩豆 兑换 50 现金,大约需 200 天
|
||||
* 10000 玩豆 兑换 100现金,大约需 381 天
|
||||
* 30000 玩豆 兑换 300 现金,大约需 1135 天 😂😂😂
|
||||
*
|
||||
* export XWGAME_ACCOUNTS = '手机号#密码'
|
||||
* 多账号用 & 或换行
|
||||
*
|
||||
* @author Telegram@sudojia
|
||||
* @site https://blog.imzjw.cn
|
||||
* @date 2025/02/25
|
||||
*
|
||||
* const $ = new Env('享玩游戏APP')
|
||||
* cron: 33 0 * * *
|
||||
*/
|
||||
const initScript = require('../utils/initScript')
|
||||
const {$, notify, sudojia, checkUpdate} = initScript('享玩游戏APP');
|
||||
const crypto = require('crypto');
|
||||
const moment = require('moment');
|
||||
const fs = require('fs').promises;
|
||||
const path = require('path');
|
||||
const xiangWanList = process.env.XWGAME_ACCOUNTS ? process.env.XWGAME_ACCOUNTS.split(/[\n&]/) : [];
|
||||
// 消息推送
|
||||
let message = '';
|
||||
// token 缓存地址
|
||||
const TOKEN_CACHE_PATH = path.join(__dirname, 'xiangwan_token_cache.json');
|
||||
// 接口地址
|
||||
const baseUrl = 'https://sdk-api.xiangwan.com'
|
||||
// 加密秘钥(Base64)
|
||||
const keyBase64 = '5snOI0E5WUpP99pG5+fzug==';
|
||||
// 解码 Base64 得到原始的二进制密钥
|
||||
const key = Buffer.from(keyBase64, 'base64');
|
||||
// 加密 Iv(Base64)
|
||||
const ivBase64 = 'KhVRUtkYTNM82dSDxb7/YQ==';
|
||||
// 解码 Base64 得到原始的二进制 IV
|
||||
const iv = Buffer.from(ivBase64, 'base64');
|
||||
// 请求头
|
||||
const headers = {
|
||||
'User-Agent': 'okhttp/4.11.0',
|
||||
'Accept-Encoding': 'gzip',
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
};
|
||||
|
||||
!(async () => {
|
||||
await checkUpdate($.name, xiangWanList);
|
||||
for (let i = 0; i < xiangWanList.length; i++) {
|
||||
const index = i + 1;
|
||||
const [account, pwd] = xiangWanList[i].split('#');
|
||||
console.log(`\n*****第[${index}]个${$.name}账号*****`);
|
||||
await login(account, pwd);
|
||||
if (!$.isLogin) {
|
||||
continue;
|
||||
}
|
||||
await $.wait(sudojia.getRandomWait(1e3, 2e3));
|
||||
message += `📣====${$.name}账号[${index}]====📣\n`;
|
||||
await main();
|
||||
await $.wait(sudojia.getRandomWait(2000, 2500));
|
||||
}
|
||||
if (message) {
|
||||
await notify.sendNotify(`「${$.name}」`, `${message}`);
|
||||
}
|
||||
})().catch((e) => $.logErr(e)).finally(() => $.done());
|
||||
|
||||
async function main() {
|
||||
await sign();
|
||||
await $.wait(sudojia.getRandomWait(1e3, 2e3));
|
||||
await getUserInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*
|
||||
* @param account
|
||||
* @param password
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function login(account, password) {
|
||||
try {
|
||||
let cachedToken = await getTokenFromCache("xiangwan", account);
|
||||
if (cachedToken) {
|
||||
headers.authorization = `Bearer ${cachedToken}`;
|
||||
console.log('使用缓存 token 登录,验证中...');
|
||||
const isValid = await validateToken(cachedToken);
|
||||
await $.wait(sudojia.getRandomWait(2e3, 3e3));
|
||||
if (isValid) {
|
||||
$.isLogin = true;
|
||||
console.log('token 验证有效✅');
|
||||
return;
|
||||
} else {
|
||||
console.log('缓存 token 验证失效,开始重新登录更新 token...');
|
||||
}
|
||||
}
|
||||
const encryptData = await sudojia.sendRequest(`${baseUrl}/account/account_login`, 'post', headers, {
|
||||
"params": encryptCredentials(JSON.stringify({
|
||||
...getCommonParams(),
|
||||
account: account,
|
||||
password: password
|
||||
}))
|
||||
});
|
||||
const decryptData = JSON.parse(decryptCredentials(encryptData));
|
||||
if (200 !== decryptData.status_code) {
|
||||
$.isLogin = false;
|
||||
return console.error(`登录失败 ->`, decryptData);
|
||||
}
|
||||
console.log('登录成功~');
|
||||
headers.authorization = `Bearer ${decryptData.data.token}`;
|
||||
$.isLogin = true;
|
||||
// 保存 token 到文件
|
||||
await saveTokenToCache("xiangwan", account, decryptData.data.token);
|
||||
} catch (e) {
|
||||
$.isLogin = false;
|
||||
if (e.response || e.response.data) {
|
||||
console.error(`登录时发生异常 ->`, e.response.data);
|
||||
} else {
|
||||
console.error(`登录时发生异常 ->`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 签到
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function sign() {
|
||||
try {
|
||||
console.log('\n开始执行...');
|
||||
await $.wait(sudojia.getRandomWait(1e3, 2e3));
|
||||
const days = moment().format('YYYYMMDD');
|
||||
const encryptData = await sudojia.sendRequest(`${baseUrl}/discover/sign`, 'post', headers, {
|
||||
"params": encryptCredentials(JSON.stringify({
|
||||
...getCommonParams(),
|
||||
"days": days
|
||||
}))
|
||||
});
|
||||
const decryptData = JSON.parse(decryptCredentials(encryptData));
|
||||
if (200 !== decryptData.status_code) {
|
||||
message += `签到失败 -> ${decryptData.message}\n`;
|
||||
return console.error(`签到失败 ->`, decryptData.message);
|
||||
}
|
||||
console.log(`签到成功,恭喜获得:${decryptData.data.score}玩豆`);
|
||||
message += `签到成功,恭喜获得:${decryptData.data.score}玩豆\n`;
|
||||
} catch (e) {
|
||||
console.error(`签到时发生异常 ->`, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function getUserInfo() {
|
||||
try {
|
||||
const encryptData = await sudojia.sendRequest(`${baseUrl}/me/member_info`, 'post', headers, {
|
||||
"params": encryptCredentials(JSON.stringify({
|
||||
...getCommonParams()
|
||||
}))
|
||||
});
|
||||
const decryptData = JSON.parse(decryptCredentials(encryptData));
|
||||
if (200 !== decryptData.status_code) {
|
||||
return console.error(`获取用户信息时发生异常 ->`, decryptData);
|
||||
}
|
||||
const {nickname, mobile, balance} = decryptData.data;
|
||||
const hiddenMobile = `${mobile.slice(0, 3)}***${mobile.slice(-3)}` || 18888888888;
|
||||
const displayName = nickname || "吴彦祖";
|
||||
console.log(`${displayName}(${hiddenMobile})`);
|
||||
console.log(`当前玩豆:${balance}`);
|
||||
message += `${nickname}(${hiddenMobile})\n`;
|
||||
message += `当前玩豆:${balance}\n\n`;
|
||||
} catch (e) {
|
||||
console.error(`获取用户信息时发生异常 ->`, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证 token 是否有效
|
||||
*
|
||||
* @param token
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
async function validateToken(token) {
|
||||
try {
|
||||
const encryptData = await sudojia.sendRequest(`${baseUrl}/me/member_account`, 'post', {
|
||||
authorization: `Bearer ${token}`
|
||||
}, {
|
||||
"params": encryptCredentials(JSON.stringify({
|
||||
...getCommonParams()
|
||||
}))
|
||||
});
|
||||
const decryptData = JSON.parse(decryptCredentials(encryptData));
|
||||
return 200 === decryptData.status_code;
|
||||
} catch (error) {
|
||||
console.error('验证 token 时发生异常:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取公共请求参数
|
||||
*
|
||||
* @returns {Object} 包含公共请求参数的对象
|
||||
*/
|
||||
function getCommonParams() {
|
||||
return {
|
||||
"app_channel": "xw_100016",
|
||||
"app_version": "1.3",
|
||||
"invite_uid": "",
|
||||
"app_os": "android",
|
||||
"server_device_id": "176"
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密请求数据
|
||||
*
|
||||
* @returns {string} 加密后的Base64字符串
|
||||
*/
|
||||
function encryptCredentials(plainText) {
|
||||
// 创建加密器
|
||||
const cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
|
||||
// 加密数据
|
||||
let encrypted = cipher.update(plainText, 'utf8', 'base64');
|
||||
encrypted += cipher.final('base64');
|
||||
return encrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密响应数据
|
||||
*
|
||||
* @param encryptedText
|
||||
* @returns {string}
|
||||
*/
|
||||
function decryptCredentials(encryptedText) {
|
||||
// 创建解密器
|
||||
const decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
|
||||
// 解密数据
|
||||
let decrypted = decipher.update(encryptedText, 'base64', 'utf8');
|
||||
decrypted += decipher.final('utf8');
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从文件中读取 token
|
||||
*
|
||||
* @param platform
|
||||
* @param username
|
||||
* @returns {Promise<*|null>}
|
||||
*/
|
||||
async function getTokenFromCache(platform, username) {
|
||||
try {
|
||||
try {
|
||||
// 检查文件是否存在
|
||||
await fs.access(TOKEN_CACHE_PATH);
|
||||
} catch (error) {
|
||||
console.warn('token 缓存文件不存在,创建一个空文件...');
|
||||
await fs.writeFile(TOKEN_CACHE_PATH, JSON.stringify({}, null, 2), 'utf8');
|
||||
return null;
|
||||
}
|
||||
const cache = await fs.readFile(TOKEN_CACHE_PATH, 'utf-8');
|
||||
// 检查文件内容是否为空
|
||||
if (!cache.trim()) {
|
||||
console.warn('token 缓存文件内容为空,开始重新登录生成 token 内容');
|
||||
return null;
|
||||
}
|
||||
let cacheObj;
|
||||
try {
|
||||
cacheObj = JSON.parse(cache);
|
||||
} catch (parseError) {
|
||||
console.error('解析 token 缓存文件失败:', parseError);
|
||||
return null; // 解析失败时返回 null
|
||||
}
|
||||
// 检查平台和用户名是否存在
|
||||
if (cacheObj[platform] && cacheObj[platform][username]) {
|
||||
return cacheObj[platform][username];
|
||||
} else {
|
||||
console.warn(`token 缓存文件中未找到[${username}]的账号,开始重新登录生成 token`);
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('读取缓存文件失败:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 token 保存到文件
|
||||
*
|
||||
* @param platform
|
||||
* @param username
|
||||
* @param token
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function saveTokenToCache(platform, username, token) {
|
||||
try {
|
||||
let cacheObj = {};
|
||||
try {
|
||||
const cache = await fs.readFile(TOKEN_CACHE_PATH, 'utf-8');
|
||||
if (cache.trim()) {
|
||||
cacheObj = JSON.parse(cache);
|
||||
} else {
|
||||
console.warn('token 缓存文件内容为空,开始初始化为空对象...');
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('读取缓存文件失败,初始化为空对象:', error);
|
||||
}
|
||||
if (!cacheObj[platform]) {
|
||||
cacheObj[platform] = {};
|
||||
}
|
||||
cacheObj[platform][username] = token;
|
||||
await fs.writeFile(TOKEN_CACHE_PATH, JSON.stringify(cacheObj, null, 2), 'utf-8');
|
||||
console.log('token 已保存到缓存文件[xiangwan_token_cache.json]');
|
||||
console.log(`路径:${TOKEN_CACHE_PATH}`);
|
||||
} catch (error) {
|
||||
console.error('保存 token 失败:', error);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user