/* 中国联通 v1.09 + 自动提取Token整合版 包含以下功能: 1. 首页签到 (话费红包/积分) 2. 联通祝福 (各类抽奖) 3. 天天领现金 (每日打卡/立减金) 4. 权益超市 (任务/抽奖/浇水/领奖)(功能暂时无效) 5. 安全管家 (日常任务/积分领取) 6. 联通云盘 (签到/抽奖/AI互动) 7. 联通阅读 (新版重构: 自动获取书籍/心跳阅读/8051抽奖/查红包) 更新说明: v1.09: - 移除过时的龟兔赛跑、阅光宝盒等冗余代码。 - 移植Python版阅读逻辑,采用Token加密登录,流程更简洁稳定。 配置说明: 变量名: chinaUnicomCookie 赋值方式有两种: 1. 直接填Token (旧方式): export chinaUnicomCookie="a3e4c1ff25da2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 2. 填账号密码 (新方式 - 推荐): export chinaUnicomCookie="18600000000#123456" (多账号用 & 或 换行 隔开) cron: 0 0,7,20 * * * const $ = new Env("中国联通"); From:yaohuo28507 (Integration by AI, Woread Refactored) */ const fs = require('fs'); const crypto = require("crypto"); // 新增:用于账号密码登录的RSA加密 const appName = createLogger("中国联通"), got = require("got"), path = require("path"), { exec: execCommand } = require("child_process"), cryptoJS = require("crypto-js"), { CookieJar: cookieJar } = require("tough-cookie"), chinaUnicom = "chinaUnicom", delimiters = ["\n", "&", "@"], cookieVars = [chinaUnicom + "Cookie"], signDisabled = process.env[chinaUnicom + "Sign"] === "false", ltzfDisabled = process.env[chinaUnicom + "Ltzf"] === "false", requestTimeout = 50000, retryCount = 3, projectName = "chinaUnicom", retryDelay = 5, appVersion = "iphone_c@11.0503", userAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 unicom{version:" + appVersion + "}", productId = "10000002", secretKey = "7k1HcDL8RKvc", defaultPassword = "woreadst^&*12345", secondProductId = "10000006", secondSecretKey = "yQsp9gUqv7qX", someConstant = "QzUzOUM2QTQ2MTc4", ivString = "16-Bytes--String", errorCode = "225", errorNumber = "225", partyName = "party", apiKey = "6-WfVldfFrt3zhjHhe6kzwI-XfG5aMCzRTLI_4K7_a0", clientId = "73b138fd-250c-4126-94e2-48cbcc8b9cbe", anotherClientId = "7cb46449-3b11-4414-bb49-cbd15525fb88", maxRetries = "9", minRetries = "1", serviceLife = "wocareMBHServiceLife1", anotherApiKey = "beea1c7edf7c4989b2d3621c4255132f", anotherEncryptionKey = "f4cd4ffeb5554586acf65ba7110534f5", numbers = "0123456789", letters = "qwertyuiopasdfghjklzxcvbnm", uuid = process.env[chinaUnicom + "Uuid"] || appName.randomUuid(), someArray = [9, 10, 11, 12, 13], delayMs = 1000, timeoutMs = 5000, client_Id = "1001000003", ProductId2 = "100002", emptyString = ""; // 已清理旧变量 const maskStr = (str) => { try { let s = String(str); if (s.length === 11) { return s.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2'); } return s; } catch (e) { return str; } }; const expiration_time = 7, appMonth_28_MaxTimes = 5, maxDrawTimes = 5; const activityIds = { ttlxj: "TTLXJ20210330", card_618: "NZJK618CJHD" }; const constellationMatchingActivity = { name: "星座配对", id: 2 }; const turntableActivity = { name: "大转盘", id: 3 }; const blindBoxActivity = { name: "盲盒抽奖", id: 4 }; const wocareActivities = [constellationMatchingActivity, turntableActivity, blindBoxActivity]; const card618PrizeMap = { ZFGJBXXCY1: "空气", GJBNZJK19: "[6]", GJBNZJK20: "[1]", GJBNZJK21: "[8]", GJBNZJK22: "[狂]", GJBNZJK23: "[欢]" }; const card618DrawTypeSuffix = { "抽奖": "01", "首次进入": "02", "卡片合成": "03", "瓜分奖励": "04" }; // RSA 公钥,用于密码登录 const LOGIN_PUB_KEY = `-----BEGIN PUBLIC KEY-----\n${"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDc+CZK9bBA9IU+gZUOc6FUGu7yO9WpTNB0PzmgFBh96Mg1WrovD1oqZ+eIF4LjvxKXGOdI79JRdve9NPhQo07+uqGQgE4imwNnRx7PFtCRryiIEcUoavuNtuRVoBAm6qdB0SrctgaqGfLgKvZHOnwTjyNqjBUxzMeQlEC2czEMSwIDAQAB".match(/.{1,64}/g).join('\n')}\n-----END PUBLIC KEY-----`; function UencryptWithCryptoJS(algorithm, mode, padding, plaintext, key, iv) { return cryptoJS[algorithm].encrypt( cryptoJS.enc.Utf8.parse(plaintext), cryptoJS.enc.Utf8.parse(key), { mode: cryptoJS.mode[mode], padding: cryptoJS.pad[padding], iv: cryptoJS.enc.Utf8.parse(iv) } ).ciphertext.toString(cryptoJS.enc.Hex); } function decrypt(cipherMethod, mode, padding, ciphertextHex, key, iv) { return cryptoJS[cipherMethod].decrypt({ ciphertext: cryptoJS.enc.Hex.parse(ciphertextHex) }, cryptoJS.enc.Utf8.parse(key), { mode: cryptoJS.mode[mode], padding: cryptoJS.pad[padding], iv: cryptoJS.enc.Utf8.parse(iv) }).toString(cryptoJS.enc.Utf8); } let processCount = 0; let processState = 0; /** * Initializes process monitoring and sets up termination handling. */ function initializeProcessMonitoring() { processState = 1; process.on("SIGTERM", () => { processState = 2; process.exit(0); }); const scriptName = path.basename(process.argv[1]); const excludedCommands = ["bash", "timeout", "grep"]; let commandList = ["ps afx"]; commandList.push(`grep ${scriptName}`); commandList = commandList.concat(excludedCommands.map(cmd => `grep -v "${cmd} "`)); commandList.push("wc -l"); const commandString = commandList.join("|"); const checkProcessCount = () => { execCommand(commandString, (error, stdout, stderr) => { if (error || stderr) { return; } processCount = parseInt(stdout.trim(), 10); }); if (processState === 1) { setTimeout(checkProcessCount, 2000); } }; checkProcessCount(); } /** * Class for managing user services with HTTP request handling and logging. */ class UserService { constructor() { this.index = appName.userIdx++; this.name = ""; this.valid = false; const retryOptions = { limit: 0 }; const defaultHeaders = { Connection: "keep-alive" }; const httpClientOptions = { retry: retryOptions, timeout: requestTimeout, followRedirect: false, ignoreInvalidCookies: true, headers: defaultHeaders }; this.got = got.extend(httpClientOptions); if (processState === 0) { initializeProcessMonitoring(); } } /** * Logs messages with an optional prefix based on user index and name. * @param {string} message - The log message. * @param {object} options - Additional logging options. */ log(message, options = {}) { let logPrefix = ""; const userCountLength = appName.userCount.toString().length; if (this.index) { logPrefix += `账号[${appName.padStr(this.index, userCountLength)}]`; } // 新增一个参数来控制是否显示手机号 if (this.name && !options.hideName) { logPrefix += `[${maskStr(this.name)}]`; // 使用 maskStr 包裹 this.name } appName.log(logPrefix + message, options); // 如果需要通知,将日志添加到用户自己的通知数组中 if (options.notify) { this.notifyLogs.push(logPrefix + message); } } /** * Sets a cookie in the cookie jar. * @param {string} name - The name of the cookie. * @param {string} value - The value of the cookie. * @param {string} domain - The domain for the cookie. * @param {string} url - The URL for the cookie. * @param {object} options - Additional options. */ set_cookie(name, value, domain, url, options = {}) { this.cookieJar.setCookieSync(`${name}=${value}; Domain=${domain};`, url); } /** * Makes an HTTP request with retry logic. * @param {object} requestOptions - The options for the HTTP request. * @returns {Promise} - The result of the HTTP request. */ async request(requestOptions) { const networkErrors = ["ECONNRESET", "EADDRINUSE", "ENOTFOUND", "EAI_AGAIN"]; const timeoutErrors = ["TimeoutError"]; const protocolErrors = ["EPROTO"]; const validCodes = []; let response = null; let attemptCount = 0; const requestName = requestOptions.fn || requestOptions.url; let validCode = appName.get(requestOptions, "valid_code", validCodes); requestOptions.method = requestOptions.method?.toUpperCase() || "GET"; while (attemptCount < retryCount) { try { attemptCount++; let errorCode = ""; let errorName = ""; let error = null; const timeout = requestOptions.timeout || this.got.defaults.options.timeout.request || requestTimeout; let timeoutOccurred = false; await new Promise((resolve) => { setTimeout(() => { timeoutOccurred = true; resolve(); }, timeout); this.got(requestOptions).then( (res) => { response = res; }, (err) => { error = err; response = err.response; errorCode = error?.code || ""; errorName = error?.name || ""; } ).finally(() => resolve()); }); if (timeoutOccurred) { this.log(`[${requestName}] 请求超时(${timeout / 1000}秒),重试第${attemptCount}次`); } else if (protocolErrors.includes(errorCode)) { this.log(`[${requestName}] 请求错误[${errorCode}][${errorName}]`); if (error?.message) { console.log(error.message); } break; } else if (timeoutErrors.includes(errorName)) { this.log(`[${requestName}] 请求错误[${errorCode}][${errorName}],重试第${attemptCount}次`); } else if (networkErrors.includes(errorCode)) { this.log(`[${requestName}] 请求错误[${errorCode}][${errorName}],重试第${attemptCount}次`); } else { const statusCode = response?.statusCode || ""; const statusCategory = Math.floor(statusCode / 100); if (statusCode) { if (statusCategory > 3 && !validCode.includes(statusCode)) { this.log(`请求[${requestName}] 返回[${statusCode}]`); } if (statusCategory <= 4) { break; } } else { this.log(`请求[${requestName}] 错误[${errorCode}][${errorName}]`); } } } catch (err) { if (err.name === "TimeoutError") { this.log(`[${requestName}] 请求超时,重试第${attemptCount}次`); } else { this.log(`[${requestName}] 请求错误(${err.message}),重试第${attemptCount}次`); } } } if (response == null) { return Promise.resolve({ statusCode: errorCode || -1, headers: null, result: null }); } let { statusCode, headers, body } = response; if (body) { try { body = JSON.parse(body); } catch { } } const result = { statusCode, headers, result: body }; return Promise.resolve(result); } } let UserServiceClass = UserService; try { let LocalBasicService = require("./LocalBasic"); UserServiceClass = LocalBasicService; } catch { } let userServiceInstance = new UserServiceClass(appName); class CustomUserService extends UserServiceClass { constructor(tokenString) { super(appName); this.cookieString = ""; this.uuid = process.env[chinaUnicom + "Uuid"] || appName.randomUuid(); // 初始化登录信息变量 this.account_mobile = ""; this.account_password = ""; this.token_online = ""; // 自动判断是 Token 还是 账号#密码 // Token 通常较长,账号密码相对较短。这里简单通过 # 判断 if (tokenString.includes("#") && tokenString.length < 64 && !tokenString.startsWith("a3")) { const parts = tokenString.split("#"); this.account_mobile = parts[0]; this.account_password = parts[1]; this.name = this.account_mobile; // 初始显示手机号 this.log(`识别到账号密码模式,准备自动提取Token: ${maskStr(this.account_mobile)}`); } else { let deftokenParts = tokenString.split("#"); this.token_online = deftokenParts[0]; } const defaultHeaders = { "User-Agent": userAgent }; this.got = this.got.extend({ headers: defaultHeaders, hooks: { beforeRequest: [ (options) => { if (this.cookieString) { options.headers.cookie = this.cookieString; } }, ], afterResponse: [ (response) => { const newCookies = response.headers["set-cookie"]; if (newCookies && Array.isArray(newCookies)) { let cookieObj = {}; if (this.cookieString) { this.cookieString.split(";").forEach((pair) => { const parts = pair.split("="); if (parts.length >= 2) cookieObj[parts[0].trim()] = parts.slice(1).join("=").trim(); }); } newCookies.forEach((str) => { const pair = str.split(";")[0]; const parts = pair.split("="); if (parts.length >= 2) { const key = parts[0].trim(); const value = parts.slice(1).join("=").trim(); cookieObj[key] = value; } }); this.cookieString = Object.entries(cookieObj) .map(([k, v]) => `${k}=${v}`) .join("; "); } return response; }, ], }, }); this.unicomTokenId = appName.randomString(32); this.tokenId_cookie = "chinaunicom-" + appName.randomString(32, numbers + letters).toUpperCase(); this.rptId = ""; this.city = []; this.t_flmf_task = 0; this.t_woread_draw = 0; // 尽管新版阅读已移除这些逻辑,但保留变量初始化以防调用旧代码报错 this.need_read_rabbit = false; this.moonbox_task_record = {}; this.initialTelephoneAmount = null; this.notifyLogs = []; // 为每个用户实例添加独立的通知日志数组 this.moonbox_notified = []; // for security butler this.sec_ticket1 = ""; this.sec_token = ""; this.sec_ticket = ""; this.sec_jeaId = ""; this.sec_oldJFPoints = null; this.ttxc_token = ""; this.ttxc_userId = ""; // for new woread logic this.wr_catid = null; this.wr_cardid = null; this.wr_cntindex = null; this.wr_chapterallindex = null; this.wr_chapterid = null; this.cookieString = `TOKENID_COOKIE=${this.tokenId_cookie}; UNICOM_TOKENID=${this.unicomTokenId}; sdkuuid=${this.unicomTokenId}`; } // --- RSA 加密辅助函数 (对应原脚本2的功能) --- rsa_encrypt(val) { const randomStr = Array.from({ length: 6 }, () => Math.floor(Math.random() * 9)).join(''); const buffer = Buffer.from(String(val) + randomStr); return crypto.publicEncrypt({ key: LOGIN_PUB_KEY, padding: crypto.constants.RSA_PKCS1_PADDING }, buffer).toString("base64"); } // --- 使用账号密码登录获取 token_online --- async unicom_login() { this.log(`正在使用账号 ${maskStr(this.account_mobile)} 进行登录...`); const now = new Date(); const pad = (n) => n.toString().padStart(2, '0'); const reqtime = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`; try { const payload = { "version": "iphone_c@12.0100", "mobile": this.rsa_encrypt(this.account_mobile), "reqtime": reqtime, "deviceModel": "iPhone17,2", "password": this.rsa_encrypt(this.account_password) }; const requestOptions = { fn: "unicom_login", method: "post", url: "https://m.client.10010.com/mobileService/login.htm", headers: { "User-Agent": `ChinaUnicom4.x/12.0.1 (com.chinaunicom.mobilebusiness; build:120001; iOS 19.2.0) Alamofire/5.9.1 unicom{version:"iphone_c@12.0100"}` }, form: payload }; let response = await this.request(requestOptions); let { result: data, statusCode } = response; if (data && (data.code === "0" || data.code === "0000")) { if (data.token_online) { this.token_online = data.token_online; this.log(`✅ 登录成功,获取到 token_online`); return true; } else { this.log(`❌ 登录响应中未找到 token_online`); return false; } } else { this.log(`❌ 登录失败: ${data ? data.desc : '无响应'} (Code: ${data ? data.code : statusCode})`); return false; } } catch (e) { this.log(`❌ 登录过程异常: ${e.message}`); return false; } } get_bizchannelinfo() { const bizChannelInfo = { bizChannelCode: errorNumber, disriBiz: partyName, unionSessionId: "", stType: "", stDesmobile: "", source: "", rptId: this.rptId, ticket: "", tongdunTokenId: this.tokenId_cookie, xindunTokenId: this.unicomTokenId }; let bizChannelInfoString = JSON.stringify(bizChannelInfo); return bizChannelInfoString; } get_epay_authinfo() { const authInfo = { mobile: "", sessionId: this.sessionId, tokenId: this.tokenId, userId: "" }; return JSON.stringify(authInfo); } get_flmf_data(actCode = "welfareCenter") { const flmfData = { sid: this.flmf_sid, actcode: actCode }; return flmfData; } encode_woread(data, password = defaultPassword) { let encryptedData = UencryptWithCryptoJS("AES", "CBC", "Pkcs7", JSON.stringify(data), password, ivString); return Buffer.from(encryptedData, "utf-8").toString("base64"); } encode_woread1(data, password = defaultPassword) { let encryptedData = UencryptWithCryptoJS("AES", "CBC", "Pkcs7", data, password, ivString); return Buffer.from(encryptedData, "utf-8").toString("base64"); } // 新增:单字符串加密,用于模拟Python脚本中的参数加密 encode_woread_str(text, password = defaultPassword) { let encryptedData = UencryptWithCryptoJS("AES", "CBC", "Pkcs7", text, password, ivString); return Buffer.from(encryptedData, "utf-8").toString("base64"); } get_woread_param() { return { timestamp: appName.time("yyyyMMddhhmmss"), token: this.woread_token, userid: this.woread_userid, userId: this.woread_userid, userIndex: this.woread_userIndex, userAccount: this.mobile, verifyCode: this.woread_verifycode }; } get_woread_m_param() { return { timestamp: appName.time("yyyyMMddhhmmss"), signtimestamp: Date.now(), source: maxRetries, token: this.woread_token }; } get_ltyp_sign_header(secretKey) { const currentTime = Date.now(); const randomSequence = Math.floor(89999 * Math.random()) + 100000; const productId = ProductId2; const version = emptyString; const signature = cryptoJS.MD5(secretKey + currentTime + randomSequence + productId + version).toString(); const header = { key: secretKey, resTime: currentTime, reqSeq: randomSequence, channel: productId, version: version, sign: signature }; return header; } async onLine(options = {}) { // 检查是否需要先登录获取Token if (!this.token_online && this.account_mobile && this.account_password) { let loginSuccess = await this.unicom_login(); if (!loginSuccess) { this.log("⚠️ 账号密码登录失败,无法继续执行 onLine"); return false; } } let loginSuccess = false; // const filePath = path.join(__dirname, 'chinaUnicom_cache.json'); try { const androidVersion = "android@11.0000"; const deviceId = this.uuid ; let requestOptions = { fn: "onLine", method: "post", url: "https://m.client.10010.com/mobileService/onLine.htm", headers: { 'User-Agent': `Dalvik/2.1.0 (Linux; U; Android 9; ALN-AL10 Build/PQ3A.190705.11211540);unicom{version:${androidVersion}}` }, form: { isFirstInstall: '1', netWay: 'Wifi', version: androidVersion, // deviceId: deviceId, token_online: this.token_online, provinceChanel: 'general', deviceModel: 'ALN-AL10', step: 'dingshi', androidId: '291a7deb1d716b5a', reqtime: Date.now(), } }; let response = await this.request(requestOptions); let { result: responseData, statusCode: responseStatus } = response; let responseCode = appName.get(responseData, "code", responseStatus); if (responseCode == 0) { loginSuccess = true; this.valid = true; this.mobile = responseData?.["desmobile"]; this.name = responseData?.["desmobile"]; this.ecs_token = responseData?.["ecs_token"]; this.city = responseData?.["list"]; this.log("登录成功"); } else { this.valid = false; this.log("登录失败[" + responseCode + "]"); // 如果是因为Token失效且配置了密码,尝试重新登录(可选优化) } } catch (error) { console.log(error); this.log("发生异常:" + error.message); } finally { return loginSuccess; } } // ============================================ // 权益超市 NEW LOGIC // ============================================ async get_ticket(ecs_token) { this.log("权益超市: 正在获取 ticket..."); try { const requestOptions = { fn: "get_ticket", method: "get", url: "https://m.client.10010.com/mobileService/openPlatform/openPlatLineNew.htm?to_url=https://contact.bol.wo.cn/market", headers: { 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 12; leijun Pro Build/SKQ1.22013.001);unicom{version:android@11.0702}', 'Connection': "Keep-Alive", 'Accept-Encoding': "gzip", 'Cookie': `ecs_token=${ecs_token}` }, followRedirect: false // Important: we need to capture the 302 redirect }; const { headers, statusCode } = await this.request(requestOptions); if (statusCode === 302 && headers?.location) { const locationUrl = new URL(headers.location); const ticket = locationUrl.searchParams.get("ticket"); if (ticket) { this.log("权益超市: 获取ticket成功"); return ticket; } } this.log(`权益超市: 获取ticket失败, status: ${statusCode}`); return null; } catch (e) { this.log(`权益超市: 获取ticket异常: ${e.message}`); return null; } } async get_userToken(ticket) { this.log("权益超市: 正在获取 userToken..."); try { const requestOptions = { fn: "get_userToken", method: "post", url: `https://backward.bol.wo.cn/prod-api/auth/marketUnicomLogin?ticket=${ticket}`, headers: { 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 12; leijun Pro Build/SKQ1.22013.001);unicom{version:android@11.0702}', 'Connection': "Keep-Alive", 'Accept-Encoding': "gzip", } }; const { result, statusCode } = await this.request(requestOptions); if (result?.code === 200) { const userToken = result?.data?.token; if (userToken) { this.log("权益超市: 获取userToken成功"); return userToken; } } this.log(`权益超市: 获取userToken失败: ${result?.msg || '返回数据异常'}`); return null; } catch (e) { this.log(`权益超市: 获取userToken异常: ${e.message}`); return null; } } async get_AllActivityTasks(ecs_token, userToken) { this.log("权益超市: 正在获取任务列表..."); try { const requestOptions = { fn: "getAllActivityTasks", method: "get", url: "https://backward.bol.wo.cn/prod-api/promotion/activityTask/getAllActivityTasks?activityId=12", headers: { 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 12; leijun Pro Build/SKQ1.22013.001);unicom{version:android@11.0702}', 'Authorization': `Bearer ${userToken}`, 'Cookie': `ecs_token=${ecs_token}` } }; const { result } = await this.request(requestOptions); if (result?.code === 200) { const tasks = result?.data?.activityTaskUserDetailVOList || []; this.log(`权益超市: 成功获取到 ${tasks.length} 个任务`); return tasks; } this.log(`权益超市: 查询任务列表失败: ${result?.msg || '未知错误'}`); return []; } catch (e) { this.log(`权益超市: 查询任务列表异常: ${e.message}`); return []; } } async do_ShareList(shareList, userToken) { this.log("权益超市: 开始执行任务..."); for (const task of shareList) { const { name, param1: param, triggerTime, triggeredTime } = task; if (name.includes("购买") || name.includes("秒杀")) { this.log(`权益超市: 🚫 ${name} [跳过]`); continue; } if (triggeredTime >= triggerTime) { this.log(`权益超市: ✅ ${name} [已完成]`); continue; } let url = ""; if (name.includes("浏览") || name.includes("查看")) { url = `https://backward.bol.wo.cn/prod-api/promotion/activityTaskShare/checkView?checkKey=${param}`; } else if (name.includes("分享")) { url = `https://backward.bol.wo.cn/prod-api/promotion/activityTaskShare/checkShare?checkKey=${param}`; } if (url) { try { const requestOptions = { fn: `do_task_${name}`, method: "post", url: url, headers: { 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 12; leijun Pro Build/SKQ1.22013.001);unicom{version:android@11.0702}', 'Authorization': `Bearer ${userToken}`, } }; const { result } = await this.request(requestOptions); if (result?.code === 200) { this.log(`权益超市: ✅ ${name} [执行成功]`); } else { this.log(`权益超市: ❌ ${name} [执行失败]: ${result?.msg}`); } } catch (e) { this.log(`权益超市: ❌ ${name} [执行异常]: ${e.message}`); } } await appName.wait(2000 + Math.random() * 2000); } } async get_Raffle(userToken) { this.log("权益超市: 正在查询奖品池..."); try { const requestOptions = { fn: "get_Raffle", method: "post", url: "https://backward.bol.wo.cn/prod-api/promotion/home/raffleActivity/prizeList?id=12", headers: { 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 12; leijun Pro Build/SKQ1.22013.001);unicom{version:android@11.0702}', 'Authorization': `Bearer ${userToken}` } }; const { result } = await this.request(requestOptions); if (result?.code === 200 && Array.isArray(result.data)) { const keywords = ['月卡', '月会员', '月度', 'VIP月', '一个月']; const livePrizes = result.data.filter(prize => keywords.some(kw => prize.name.includes(kw)) && parseInt(prize.dailyPrizeLimit, 10) > 0 && parseInt(prize.quantity, 10) > 0 ); if (livePrizes.length > 0) { this.log("权益超市: 📢 当前已放水!可抽有库存奖品👇👇👇"); livePrizes.forEach(item => { this.log(` - ${item.name} (日库存:${item.dailyPrizeLimit}, 总库存:${item.quantity}, 概率:${(item.probability * 100).toFixed(1)}%)`); }); return true; } } this.log("权益超市: 📢 当前未放水!终止抽奖😡😡😡"); return false; } catch (e) { this.log(`权益超市: 查询奖品池异常: ${e.message}`); return false; } } async get_raffle_count(userToken) { this.log("权益超市: 正在查询抽奖次数..."); try { const requestOptions = { fn: "get_raffle_count", method: "post", url: "https://backward.bol.wo.cn/prod-api/promotion/home/raffleActivity/getUserRaffleCount?id=12", headers: { 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 12; leijun Pro Build/SKQ1.22013.001);unicom{version:android@11.0702}', 'Authorization': `Bearer ${userToken}` } }; const { result } = await this.request(requestOptions); let count = result?.data || 0; if (result?.code === 200 && count > 0) { this.log(`权益超市: ✅ 当前抽奖次数: ${count}`); for (let i = 0; i < count; i++) { this.log(`权益超市: 🎯 第 ${i + 1} 次抽奖...`); const success = await this.get_userRaffle(userToken); if (!success) { this.log("权益超市: 抽奖失败或遇到验证, 停止后续抽奖"); break; } await appName.wait(3000 + Math.random() * 2000); } } else { this.log(`权益超市: 当前无抽奖次数`); } } catch (e) { this.log(`权益超市: 查询抽奖次数异常: ${e.message}`); } } async get_userRaffle(userToken) { try { const requestOptions = { fn: "get_userRaffle", method: "post", url: "https://backward.bol.wo.cn/prod-api/promotion/home/raffleActivity/userRaffle?id=12&channel=", headers: { 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 12; leijun Pro Build/SKQ1.22013.001);unicom{version:android@11.0702}', 'Authorization': `Bearer ${userToken}` } }; const { result } = await this.request(requestOptions); if (result?.code === 200 && result?.data) { const { lotteryRecordId, prizesName, message } = result.data; if (prizesName) { this.log(`权益超市: ✅ 抽奖成功: ${prizesName}`); } else { this.log(`权益超市: ⚠️ 抽奖成功, 但: ${message}`); } if (lotteryRecordId) { // GrantPrize is always true based on python script this.log("权益超市: 尝试领取:${prizesName}"); await this.get_grantPrize(userToken, lotteryRecordId, prizesName || '未知奖品'); } return true; } else if (result?.code === 500) { this.log("权益超市: 遇到人机验证, 尝试绕过..."); return await this.get_validateCaptcha(userToken); } else { this.log(`权益超市: 抽奖失败: ${result?.msg || '未知错误'}`); return false; } } catch (e) { this.log(`权益超市: 抽奖异常: ${e.message}`); return false; } } async get_validateCaptcha(userToken) { try { const requestOptions = { fn: "get_validateCaptcha", method: "post", url: "https://backward.bol.wo.cn/prod-api/promotion/home/raffleActivity/validateCaptcha?id=12", headers: { 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 12; leijun Pro Build/SKQ1.22013.001);unicom{version:android@11.0702}', 'Authorization': `Bearer ${userToken}` } }; const { result } = await this.request(requestOptions); if (result?.code === 200) { this.log("权益超市: 人机验证成功, 重新抽奖..."); return await this.get_userRaffle(userToken); } this.log(`权益超市: 人机验证失败: ${result?.msg}`); return false; } catch (e) { this.log(`权益超市: 人机验证异常: ${e.message}`); return false; } } async queryGeneralPrizes(userToken) { this.log("权益超市: 正在查询待领取奖品..."); if (!userToken) { this.log("权益超市-查通用奖品: userToken not found, skipping."); return; } // 'this.mobile' is available after a successful onLine.htm call. if (!this.mobile) { this.log("权益超市-查待领取奖品: 手机号未找到, 跳过."); return; } try { const requestBody = { "isReceive": "0", "receiveStatus": "0", "limit": 20, "page": 1, "mobile": this.mobile, "businessSources": ["3", "4", "5", "6", "99"], "isPromotion": 1, "returnFormatType": 1 }; const requestOptions = { fn: "queryGeneralPrizes", method: "post", url: `https://backward.bol.wo.cn/prod-api/market/contactReceive/queryReceiveRecord`, headers: { 'Authorization': `Bearer ${userToken}`, 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 12; leijun Pro Build/SKQ1.22013.001);unicom{version:android@11.0702}', 'Content-Type': 'application/json' }, json: requestBody }; const { result } = await this.request(requestOptions); if (result?.code !== 200) { this.log(`权益超市-查待领取奖品: 查询失败: ${result?.msg || '未知错误'}`); return; } const prizes = result.data?.recordObjs || []; const now = new Date(); const claimablePrizes = prizes.filter(prize => { if (!prize.receiveEndTime) return false; const endTime = new Date(prize.receiveEndTime.replace(/-/g, "/")); return endTime > now; }); if (claimablePrizes.length > 0) { this.log(`权益超市: 查询到 ${claimablePrizes.length} 个可领取奖品:`, { notify: true }); for (const prize of claimablePrizes) { this.log(` - ${prize.recordName} (截止: ${prize.receiveEndTime})`); if (prize.businessId) { await this.grantGeneralPrize(userToken, prize); await appName.wait(1500 + Math.random() * 1000); } else { this.log(` └─ 缺少 businessId, 无法自动领取.`); } } } else { this.log("权益超市: 未发现可领取的奖品。"); } } catch (e) { this.log(`权益超市-查待领取奖品: 任务异常: ${e.message}`); } } async grantGeneralPrize(userToken, prize) { this.log(`权益超市: └─ 尝试领取: ${prize.recordName}`); try { const requestOptions = { fn: "grantGeneralPrize", method: "post", url: "https://backward.bol.wo.cn/prod-api/promotion/home/raffleActivity/grantPrize", headers: { 'Authorization': `Bearer ${userToken}`, 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 12; leijun Pro Build/SKQ1.22013.001);unicom{version:android@11.0702}', 'Content-Type': 'application/json' }, json: { "recordId": prize.businessId } // Using businessId as recordId }; const { result } = await this.request(requestOptions); if (result?.code === 200) { this.log(`权益超市: └─ ✅ [领取成功]`); } else { this.log(`权益超市: └─ ❌ [领取失败]: ${result?.msg}`); } } catch (e) { this.log(`权益超市: └─ 领取通用奖品 ${prize.recordName} 异常: ${e.message}`); } } async get_grantPrize(userToken, lotteryRecordId, prizesName) { try { const requestOptions = { fn: "get_grantPrize", method: "post", url: "https://backward.bol.wo.cn/prod-api/promotion/home/raffleActivity/grantPrize?activityId=12", headers: { 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 12; leijun Pro Build/SKQ1.22013.001);unicom{version:android@11.0702}', 'Authorization': `Bearer ${userToken}`, 'Content-Type': 'application/json' }, json: { "recordId": lotteryRecordId } }; const { result } = await this.request(requestOptions); if (result?.code === 200) { this.log(`权益超市: ✅ ${prizesName} [领取成功]`); } else { this.log(`权益超市: ❌ ${prizesName} [领取失败]: ${result?.msg}`); } } catch (e) { this.log(`权益超市: 领取奖品异常: ${e.message}`); } } async marketWateringTask(userToken) { this.log("权益超市: 浇花任务开始..."); if (!userToken) { this.log("权益超市-浇花: userToken not found, skipping."); return; } try { // 1. Get watering status const statusOptions = { fn: "marketGetWateringStatus", method: "get", url: `https://backward.bol.wo.cn/prod-api/promotion/activityTask/getMultiCycleProcess?activityId=13`, headers: { 'Authorization': `Bearer ${userToken}`, 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 12; leijun Pro Build/SKQ1.22013.001);unicom{version:android@11.0702}', } }; const { result: statusResult } = await this.request(statusOptions); if (statusResult?.code !== 200) { this.log(`权益超市-浇花: 获取状态失败: ${statusResult?.msg || '未知错误'}`); return; } const { triggeredTime, triggerTime, createDate } = statusResult.data; this.log(`权益超市-浇花: 当前进度 ${triggeredTime}/${triggerTime}`, { notify: true }); // 2. Conditional logic if (triggeredTime >= triggerTime) { this.log("权益超市-浇花: 🌟 您有鲜花权益待领取! (连续浇花已满) 🌟", { notify: true }); return; } // Check if watered today const todayStr = new Date(new Date().getTime() + 8 * 3600 * 1000).toISOString().split('T')[0]; const lastWateredDateStr = createDate ? createDate.split(' ')[0] : ''; if (todayStr === lastWateredDateStr) { this.log(`权益超市-浇花: 今日已浇水 (最后浇水时间: ${createDate})`, { notify: true }); return; } this.log("权益超市-浇花: 今日未浇水,执行浇水操作..."); // 3. Perform watering const waterOptions = { fn: "marketWatering", method: "post", url: "https://backward.bol.wo.cn/prod-api/promotion/activityTaskShare/checkWatering", headers: { 'Authorization': `Bearer ${userToken}`, 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 12; leijun Pro Build/SKQ1.22013.001);unicom{version:android@11.0702}', 'Content-Type': 'application/json' }, json: {} }; const { result: waterResult } = await this.request(waterOptions); if (waterResult?.code === 200) { this.log("权益超市-浇花: ✅ 浇水成功!"); } else { this.log(`权益超市-浇花: ❌ 浇水失败: ${waterResult?.msg || '未知错误'}`); } } catch (e) { this.log(`权益超市-浇花: 任务异常: ${e.message}`); } } async marketTask() { this.log("============= 权益超市 ============="); // The main `task` function already calls `await user.onLine()`. // So when `marketTask` is called, `this.ecs_token` should be available. const ecs_token = this.ecs_token; if (!ecs_token) { this.log("权益超市: ❌ 未获取到 ecs_token, 跳过任务"); this.log("============= 权益超市执行完毕 ============="); return; } // 1. Get ticket const ticket = await this.get_ticket(ecs_token); if (!ticket) { this.log("============= 权益超市执行完毕 ============="); return; } // 2. Get userToken const userToken = await this.get_userToken(ticket); if (!userToken) { this.log("============= 权益超市执行完毕 ============="); return; } // New: Execute watering task await this.marketWateringTask(userToken); await appName.wait(2000); // 3. Get and do tasks const shareList = await this.get_AllActivityTasks(ecs_token, userToken); if (shareList && shareList.length > 0) { await this.do_ShareList(shareList, userToken); } // 4. Check raffle and draw const canRaffle = await this.get_Raffle(userToken); if (canRaffle) { await this.get_raffle_count(userToken); } // 5. Query and claim prizes // await this.get_MyPrize(userToken); // For raffle prizes await this.queryGeneralPrizes(userToken); // For general prizes this.log("============= 权益超市执行完毕 ============="); } async openPlatLineNew(url, options = {}) { const defaultResult = { ticket: "", type: "", loc: "" }; let result = defaultResult; try { const queryParams = { to_url: url }; const requestOptions = { fn: "openPlatLineNew", method: "get", url: "https://m.client.10010.com/mobileService/openPlatform/openPlatLineNew.htm", searchParams: queryParams }; const { headers, statusCode } = await this.request(requestOptions); if (headers?.["location"]) { const locationUrl = new URL(headers.location); const type = locationUrl.searchParams.get("type") || "02"; const ticket = locationUrl.searchParams.get("ticket"); if (!ticket) { this.log("获取ticket失败"); } result = { loc: headers.location, ticket: ticket, type: type }; } else { this.log(`获取ticket失败[${statusCode}]`); } } catch (error) { console.log(error); } finally { return result; } } async gettaskip(options = {}) { const orderId = appName.randomString(32).toUpperCase(); try { const requestBody = { mobile: this.mobile, orderId: orderId }; const requestOptions = { fn: "gettaskip", method: "post", url: "https://m.client.10010.com/taskcallback/topstories/gettaskip", form: requestBody }; await this.request(requestOptions); } catch (error) { console.log(error); } finally { return orderId; } } async draw_28_queryChance(options = {}) { try { const requestConfig = { fn: "draw_28_queryChance", method: "post", url: "https://m.client.10010.com/AppMonthly/appMonth/queryChance" }; let { result: responseResult, statusCode: responseStatusCode } = await this.request(requestConfig), status = appName.get(responseResult, "status", responseStatusCode); if (status == "0000") { let remainingTimes = parseInt(responseResult?.["data"]?.["allRemainTimes"] || 0), drawTimes = Math.min(maxDrawTimes, remainingTimes); this.log("28日五折日可以抽奖" + remainingTimes + "次, 去抽" + drawTimes + "次"); let isFirstAttempt = false; while (drawTimes-- > 0) { if (isFirstAttempt) { await appName.wait(8000); } isFirstAttempt = true; await this.draw_28_lottery(); } } else { let errorMessage = responseResult?.["message"] || responseResult?.["msg"] || ""; this.log("28日五折日查询抽奖次数失败[" + status + "]: " + errorMessage); } } catch (error) { console.log(error); } } async draw_28_lottery(options = {}) { try { const requestOptions = { fn: "draw_28_lottery", method: "post", url: "https://m.client.10010.com/AppMonthly/appMonth/lottery" }; const { result: responseResult, statusCode: responseStatusCode } = await this.request(requestOptions); const status = appName.get(responseResult, "status", responseStatusCode); if (status === "0000") { const data = responseResult?.["data"]; const code = appName.get(data, "code", -1); if (data?.["uuid"]) { await appName.wait(2000); await this.draw_28_winningRecord(data.uuid); } else { const errorMessage = data?.["message"] || data?.["msg"] || ""; this.log(`28日五折日抽奖失败[${code}]: ${errorMessage}`); } } else { const errorMessage = responseResult?.["message"] || responseResult?.["msg"] || ""; this.log(`28日五折日抽奖失败[${status}]: ${errorMessage}`); } } catch (error) { console.log(error); } } async draw_28_winningRecord(requestId, options = {}) { try { const requestPayload = { requestId: requestId }; const requestOptions = { fn: "draw_28_winningRecord", method: "post", url: "https://m.client.10010.com/AppMonthly/appMonth/winningRecord", form: requestPayload }; const { result, statusCode } = await this.request(requestOptions); const status = appName.get(result, "status", statusCode); if (status === "0000") { const responseData = result?.["data"]; const resultCode = appName.get(responseData, "code", -1); if (resultCode === "0000") { const logOptions = { notify: true }; this.log("28日五折日抽奖: " + responseData?.["prizeName"]?.replace(/\t/g, ""), logOptions); } else { const errorMessage = responseData?.["message"] || responseData?.["msg"] || ""; this.log(`查询28日五折日抽奖结果失败[${resultCode}]: ${errorMessage}`); } } else { const errorMessage = result?.["message"] || result?.["msg"] || ""; this.log(`查询28日五折日抽奖结果失败[${status}]: ${errorMessage}`); } } catch (error) { console.log(error); } } async ttlxj_authorize(ticket, type, refererUrl, options = {}) { try { const requestConfig = { fn: "ttlxj_authorize", method: "post", url: "https://epay.10010.com/woauth2/v2/authorize", headers: { Origin: "https://epay.10010.com", Referer: refererUrl }, json: { response_type: "rptid", client_id: clientId, redirect_uri: "https://epay.10010.com/ci-mps-st-web/", login_hint: { credential_type: "st_ticket", credential: ticket, st_type: type, force_logout: true, source: "app_sjyyt" }, device_info: { token_id: "chinaunicom-pro-" + Date.now() + "-" + appName.randomString(13), trace_id: appName.randomString(32) } } }; const { result } = await this.request(requestConfig); const statusCode = appName.get(result, "status", -1); if (statusCode === 200) { await this.ttlxj_authCheck(); } else { const errorMessage = result?.["message"] || result?.["msg"] || ""; this.log(`天天领现金获取SESSION失败[${statusCode}]: ${errorMessage}`); } } catch (error) { console.log(error); } } async ttlxj_authCheck(options = {}) { try { const requestConfig = { fn: "ttlxj_authCheck", method: "post", url: "https://epay.10010.com/ps-pafs-auth-front/v1/auth/check", headers: { bizchannelinfo: this.get_bizchannelinfo() } }; const { result } = await this.request(requestConfig); const responseCode = appName.get(result, "code", -1); if (responseCode === "0000") { const { mobile, sessionId, tokenId, userId } = result?.["data"]?.["authInfo"]; const authInfo = { sessionId, tokenId, userId }; Object.assign(this, authInfo); await this.ttlxj_userDrawInfo(); await this.ttlxj_queryAvailable(); } else { if (responseCode === "2101000100") { const loginUrl = result?.["data"]?.["woauth_login_url"]; await this.ttlxj_login(loginUrl); } else { const errorMessage = result?.["msgInside"] || result?.["msg"] || ""; this.log(`天天领现金获取tokenId失败[${responseCode}]: ${errorMessage}`); } } } catch (error) { console.log(error); } } async ttlxj_login(loginUrl, options = {}) { try { const fullUrl = `${loginUrl}https://epay.10010.com/ci-mcss-party-web/clockIn/?bizFrom=${errorCode}&bizChannelCode=${errorNumber}`; const requestConfig = { fn: "ttlxj_login", method: "get", url: fullUrl }; const { headers, statusCode } = await this.request(requestConfig); if (headers?.["location"]) { const locationUrl = new URL(headers.location); this.rptId = locationUrl.searchParams.get("rptid"); if (this.rptId) { await this.ttlxj_authCheck(); } else { this.log("天天领现金获取rptid失败"); } } else { this.log(`天天领现金获取rptid失败[${statusCode}]`); } } catch (error) { console.log(error); } } async ttlxj_userDrawInfo(options = {}) { try { const requestConfig = { fn: "ttlxj_userDrawInfo", method: "post", url: "https://epay.10010.com/ci-mcss-party-front/v1/ttlxj/userDrawInfo", headers: { bizchannelinfo: this.get_bizchannelinfo(), authinfo: this.get_epay_authinfo() } }; const { result } = await this.request(requestConfig); const responseCode = appName.get(result, "code", -1); if (responseCode === "0000") { const dayOfWeek = result?.["data"]?.["dayOfWeek"]; const drawKey = `day${dayOfWeek}`; const hasNotClockedIn = result?.["data"]?.[drawKey] === "1"; const logOptions = { notify: true }; this.log(`天天领现金: 今天${hasNotClockedIn ? "未" : "已"}打卡`, logOptions); if (hasNotClockedIn) { const today = new Date().getDay(); const drawType = (today % 7 === 0) ? "C" : "B"; await this.ttlxj_unifyDrawNew(drawType); } } else { const errorMessage = result?.["msg"] || ""; this.log(`天天领现金: 查询失败[${responseCode}]: ${errorMessage}`); } } catch (error) { console.log(error); } } async ttlxj_unifyDrawNew(drawType, options = {}) { try { const requestData = { drawType: drawType, bizFrom: errorCode, activityId: "TTLXJ20210330" }; const requestConfig = { fn: "ttlxj_unifyDrawNew", method: "post", url: "https://epay.10010.com/ci-mcss-party-front/v1/ttlxj/unifyDrawNew", headers: { bizchannelinfo: this.get_bizchannelinfo(), authinfo: this.get_epay_authinfo() }, form: requestData }; const { result } = await this.request(requestConfig); const responseCode = appName.get(result, "code", -1); if (responseCode === "0000" && result?.["data"]?.["returnCode"] === 0) { const awardMessage = result?.["data"]?.["awardTipContent"]?.replace(/xx/, result?.["data"]?.["amount"]); const logOptions = { notify: true }; this.log("天天领现金: 打卡 " + awardMessage, logOptions); } else { const errorMessage = result?.["data"]?.["returnMsg"] || result?.["msg"] || ""; this.log(`天天领现金: 打卡失败[${result?.["data"]?.["returnCode"] || responseCode}]: ${errorMessage}`); } } catch (error) { console.log(error); } } async ttlxj_help(options = {}) { try { const requestBody = { bizFrom: errorCode, activityId: activityIds.ttlxj, uid: apiKey }; let requestConfig = { fn: "ttlxj_h", method: "post", url: "https://epay.10010.com/ci-mcss-party-front/v1/ttlxj/help", headers: { bizchannelinfo: this.get_bizchannelinfo(), authinfo: this.get_epay_authinfo() }, form: requestBody }; await this.request(requestConfig); } catch (error) { console.log(error); } } async ttlxj_queryAvailable(options = {}) { try { let requestConfig = { fn: "ttlxj_queryAvailable", method: "post", url: "https://epay.10010.com/ci-mcss-party-front/v1/ttlxj/queryAvailable", headers: { bizchannelinfo: this.get_bizchannelinfo(), authinfo: this.get_epay_authinfo() } }; let { result: responseResult } = await this.request(requestConfig); let responseCode = appName.get(responseResult, "code", -1); if (responseCode == "0000" && responseResult?.["data"]?.["returnCode"] == 0) { let availableAmount = responseResult?.["data"]?.["availableAmount"] || 0; let logMessage = `天天领现金: 可用立减金: ${(availableAmount / 100).toFixed(2)}元`; let expiringPrizes = []; let currentTime = Date.now(); for (let prize of responseResult?.["data"]?.["prizeList"]?.filter(p => p.status == "A")) { let endTimeStr = prize.endTime; let endTimeDate = new Date(endTimeStr.slice(0, 4) + "-" + endTimeStr.slice(4, 6) + "-" + endTimeStr.slice(6, 8) + " 00:00:00"); let endTimeMs = endTimeDate.getTime(); if (endTimeMs - currentTime < expiration_time * 24 * 60 * 60 * 1000) { let formattedDate = appName.time("yyyy-MM-dd", endTimeMs); const expiringPrize = { timestamp: endTimeMs, date: formattedDate, amount: prize.amount }; expiringPrizes.push(expiringPrize); } } if (expiringPrizes.length) { const defaultPrize = { timestamp: 0, amount: 0 }; let earliestExpiringPrize = defaultPrize; let totalExpiringAmount = expiringPrizes.reduce(function (total, currentPrize) { if (earliestExpiringPrize.timestamp == 0 || currentPrize.timestamp < earliestExpiringPrize.timestamp) { earliestExpiringPrize = currentPrize; } return total + parseFloat(currentPrize.amount); }, 0); logMessage += `, ${expiration_time}天内过期立减金: ${totalExpiringAmount.toFixed(2)}元`; logMessage += `, 最早过期立减金: ${earliestExpiringPrize.amount}元 -- ${earliestExpiringPrize.date}过期`; } else { logMessage += `, ${expiration_time}天内没有过期的立减金`; } this.log(logMessage, { notify: true }); } else { let errorMessage = responseResult?.["data"]?.["returnMsg"] || responseResult?.["msg"] || ""; this.log("天天领现金: 查询可用立减金失败[" + (responseResult?.["data"]?.["returnCode"] || responseCode) + "]: " + errorMessage); } } catch (error) { console.log(error); } } async epay_28_authCheck(options = {}) { try { let requestConfig = { fn: "epay_28_authCheck", method: "post", url: "https://epay.10010.com/ps-pafs-auth-front/v1/auth/check", headers: { bizchannelinfo: this.get_bizchannelinfo() } }; let { result: responseResult } = await this.request(requestConfig); let responseCode = appName.get(responseResult, "code", -1); if (responseCode == "0000") { let { mobile: mobile, sessionId: sessionId, tokenId: tokenId, userId: userId } = responseResult?.["data"]?.["authInfo"]; const authInfo = { sessionId: sessionId, tokenId: tokenId, userId: userId }; Object.assign(this, authInfo); await this.epay_28_queryUserPage(); } else { if (responseCode == "2101000100") { let loginUrl = responseResult?.["data"]?.["woauth_login_url"]; await this.epay_28_login(loginUrl); } else { let errorMessage = responseResult?.["msgInside"] || responseResult?.["msg"] || ""; this.log("联通支付日获取tokenId失败[" + responseCode + "]: " + errorMessage); } } } catch (error) { console.log(error); } } async epay_28_login(loginUrl, options = {}) { try { let templateName = appName.time("yyyyMM") + "28ZFR"; loginUrl += "https://epay.10010.com/ci-mcss-party-web/rainbow/?templateName=" + templateName + "&bizFrom=225&bizChannelCode=225&channelType=WDQB"; const requestConfig = { fn: "epay_28_login", method: "get", url: loginUrl }; let { headers: headers, statusCode: statusCode } = await this.request(requestConfig); if (headers?.["location"]) { let locationUrl = new URL(headers.location); this.rptId = locationUrl.searchParams.get("rptid"); this.rptId ? await this.epay_28_authCheck() : this.log("联通支付日获取rptid失败"); } else { this.log("联通支付日获取rptid失败[" + statusCode + "]"); } } catch (error) { console.log(error); } } async epay_28_queryUserPage(options = {}) { try { let templateName = appName.time("yyyyMM") + "28ZFR"; const requestBody = { templateName: templateName }; let requestConfig = { fn: "epay_28_queryUserPage", method: "post", url: "https://epay.10010.com/ci-mcss-party-front/v1/rainbow/queryUserPage", headers: { bizchannelinfo: this.get_bizchannelinfo(), authinfo: this.get_epay_authinfo() }, form: requestBody }; let { result: responseResult } = await this.request(requestConfig); let responseCode = appName.get(responseResult, "code", -1); if (responseCode == "0000" && responseResult?.["data"]?.["returnCode"] == 0) { for (let prizeInfo of responseResult?.["data"]?.["prizeList"]?.["rainbowMouldInfos"] || []) { prizeInfo?.["rainbowUnitInfos"]?.[0]?.["unitActivityId"] && (await this.epay_28_unifyDraw(prizeInfo.rainbowUnitInfos[0])); if (prizeInfo?.["day01DrawParam"]) { await this.epay_28_queryMiddleUnit(templateName, prizeInfo.mouldName); break; } } } else { let errorMessage = responseResult?.["message"] || responseResult?.["msg"] || ""; this.log("联通支付日进入主页失败[" + responseCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async epay_28_queryMiddleUnit(activityId, mouldName, options = {}) { try { const requestBody = { activityId: activityId, mouldName: mouldName }; let requestConfig = { fn: "epay_28_queryMiddleUnit", method: "post", url: "https://epay.10010.com/ci-mcss-party-front/v1/rainbow/queryMiddleUnit", headers: { bizchannelinfo: this.get_bizchannelinfo(), authinfo: this.get_epay_authinfo() }, form: requestBody }; let { result: responseResult } = await this.request(requestConfig); let responseCode = appName.get(responseResult, "code", -1); if (responseCode == "0000") { let currentDay = appName.time("dd"); responseResult?.["data"]?.[currentDay] == "1" ? this.log("联通支付日今日(" + currentDay + "号)已打卡") : await this.epay_28_unifyDrawNew(activityId, mouldName); } else { let errorMessage = responseResult?.["message"] || responseResult?.["msg"] || ""; this.log("联通支付日查询打卡失败[" + responseCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async epay_28_unifyDrawNew(activityId, mouldName, options = {}) { try { const requestBody = { bizFrom: errorCode, activityId: activityId, mouldName: mouldName }; let requestConfig = { fn: "epay_28_unifyDrawNew", method: "post", url: "https://epay.10010.com/ci-mcss-party-front/v1/rainbow/unifyDrawNew", headers: { bizchannelinfo: this.get_bizchannelinfo(), authinfo: this.get_epay_authinfo() }, form: requestBody }; let { result: responseResult } = await this.request(requestConfig); let responseCode = appName.get(responseResult, "code", -1); if (responseCode == "0000" && responseResult?.["data"]?.["returnCode"] == 0) { let awardMessage = responseResult?.["data"]?.["awardTipContent"]?.replace(/xx/, responseResult?.["data"]?.["amount"]); const notifyOptions = { notify: true }; this.log("联通支付日打卡:" + awardMessage, notifyOptions); } else { let errorMessage = responseResult?.["data"]?.["returnMsg"] || responseResult?.["msg"] || ""; this.log("联通支付日打卡失败[" + (responseResult?.["data"]?.["returnCode"] || responseCode) + "]: " + errorMessage); } } catch (error) { console.log(error); } } async epay_28_unifyDraw(unitInfo, options = {}) { try { const requestBody = { activityId: unitInfo.unitActivityId, isBigActivity: unitInfo.isBigActivity, bigActivityId: unitInfo.bigActivityId, bizFrom: errorCode }; let requestConfig = { fn: "epay_28_unifyDraw", method: "post", url: "https://epay.10010.com/ci-mcss-party-front/v1/rainbow/unifyDraw", headers: { bizchannelinfo: this.get_bizchannelinfo(), authinfo: this.get_epay_authinfo() }, form: requestBody }; let { result: responseResult } = await this.request(requestConfig); let responseCode = appName.get(responseResult, "code", -1); if (responseCode == "0000" && responseResult?.["data"]?.["returnCode"] == 0) { const notifyOptions = { notify: true }; this.log("联通支付日抽奖: " + (responseResult?.["data"]?.["prizeName"] || ""), notifyOptions); } else { let errorMessage = responseResult?.["data"]?.["returnMsg"] || responseResult?.["msg"] || ""; this.log("联通支付日抽奖失败[" + (responseResult?.["data"]?.["returnCode"] || responseCode) + "]: " + errorMessage); } } catch (error) { console.log(error); } } async appMonth_28_bind(shareCode, options = {}) { try { const requestBody = { shareCode: shareCode, cl: "WeChat" }; const requestConfig = { fn: "appMonth_28_bind", method: "post", url: "https://activity.10010.com/AppMonthly/appMonth/bind", form: requestBody, valid_code: [401] }; let { result: responseResult } = await this.request(requestConfig); } catch (error) { console.log(error); } } async appMonth_28_queryChance(params = {}) { try { const requestConfig = { fn: "appMonth_28_queryChance", method: "post", url: "https://activity.10010.com/AppMonthly/appMonth/queryChance" }; let { result: response } = await this.request(requestConfig), status = appName.get(response, "status", -1); if (status == "0000") { let { allRemainTimes: remainingTimes, isUnicom: isUnicomUser } = response?.["data"]; if (isUnicomUser) { let drawTimes = Math.min(appMonth_28_MaxTimes, remainingTimes); this.log("联通支付日可以开宝箱" + remainingTimes + "次, 去抽" + drawTimes + "次"); while (drawTimes-- > 0) { await this.appMonth_28_lottery(); } } } else { let errorMsg = response?.["msg"] || ""; this.log("联通支付日查询开宝箱次数失败[" + status + "]: " + errorMsg); } } catch (error) { console.log(error); } } async appMonth_28_lottery(options = {}) { try { const requestConfig = { fn: "appMonth_28_lottery", method: "post", url: "https://activity.10010.com/AppMonthly/appMonth/lottery" }; let { result: responseResult } = await this.request(requestConfig), status = appName.get(responseResult, "status", -1); if (status == "0000") { let { code: resultCode, uuid: uuid } = responseResult?.["data"]; uuid ? await this.appMonth_28_winningRecord(uuid) : this.log("联通支付日开宝箱失败[" + resultCode + "]"); } else { let errorMessage = responseResult?.["msg"] || ""; this.log("联通支付日开宝箱失败[" + status + "]: " + errorMessage); } } catch (error) { console.log(error); } } async appMonth_28_winningRecord(requestId, options = {}) { try { const requestBody = { requestId: requestId }; const requestConfig = { fn: "appMonth_28_winningRecord", method: "post", url: "https://activity.10010.com/AppMonthly/appMonth/winningRecord", form: requestBody }; let { result: responseResult } = await this.request(requestConfig), status = appName.get(responseResult, "status", -1); if (status == "0000") { let { code: resultCode, prizeName: prizeName } = responseResult?.["data"]; if (resultCode == "0000") { const notifyOptions = { notify: true }; this.log("联通支付日开宝箱: " + prizeName, notifyOptions); } else { let errorMessage = responseResult?.["data"]?.["message"] || ""; this.log("联通支付日开宝箱[" + resultCode + "]: " + errorMessage); } } else { let errorMessage = responseResult?.["msg"] || ""; this.log("联通支付日查询中奖奖品错误[" + status + "]: " + errorMessage); } } catch (error) { console.log(error); } } // 签到区相关方法 async sign_getContinuous(imei, options = {}) { try { const requestConfig = { fn: "sign_getContinuous", method: "get", url: "https://activity.10010.com/sixPalaceGridTurntableLottery/signin/getContinuous", params: { taskId: "", channel: "wode", imei: imei } }; let { result: responseResult } = await this.request(requestConfig), responseCode = appName.get(responseResult, "code", -1); if (responseCode == "0000") { let todayIsSignIn = responseResult?.["data"]?.["todayIsSignIn"] || 'n'; this.log("签到区今天" + (todayIsSignIn == "n" ? "未" : "已") + "签到", { notify: true }); if (todayIsSignIn == "n") { await appName.wait(1000); await this.sign_daySign(); } } else { this.log("签到区查询签到状态失败[" + responseCode + "]: " + (responseResult?.["desc"] || "")); } } catch (error) { console.log(error); } } async sign_daySign(options = {}) { try { const requestConfig = { fn: "sign_daySign", method: "post", url: "https://activity.10010.com/sixPalaceGridTurntableLottery/signin/daySign", form: {} }; let { result: responseResult } = await this.request(requestConfig), responseCode = appName.get(responseResult, "code", -1); if (responseCode == "0000") { let { statusDesc: statusDesc, redSignMessage: redSignMessage } = responseResult?.["data"]; let logMessage = "签到区签到成功: "; if (statusDesc) logMessage += `[${statusDesc}]`; if (redSignMessage) logMessage += `${redSignMessage}`; this.log(logMessage); } else if (responseCode == "0002" && responseResult?.["desc"] && responseResult["desc"].includes('已经签到')) { // 今日已签到 this.log("签到区签到成功: 今日已完成签到!"); } else { this.log("签到区签到失败[" + responseCode + "]: " + (responseResult?.["desc"] || "")); } } catch (error) { console.log(error); } } async sign_getTaskReward(taskId, options = {}) { try { const requestConfig = { fn: "sign_getTaskReward", method: "get", url: "https://activity.10010.com/sixPalaceGridTurntableLottery/task/getTaskReward", searchParams: { taskId: taskId } }; let { result: responseResult } = await this.request(requestConfig); let responseCode = appName.get(responseResult, "code", -1); if (responseCode == "0000") { let data = responseResult?.["data"]; if (data?.code == '0000') { let prizeName = data?.prizeName || ''; let prizeNameRed = data?.prizeNameRed || ''; this.log(`签到区-领取奖励: [${prizeName}] ${prizeNameRed}`); } else { this.log("签到区-领取奖励失败[" + data?.code + "]: " + (responseResult?.["desc"] || data?.desc || "")); } } else { this.log("签到区-领取奖励失败[" + responseCode + "]: " + (responseResult?.["desc"] || "")); } } catch (error) { console.log(error); } } async sign_getTelephone(options = {}) { try { const requestConfig = { fn: "sign_getTelephone", method: "post", url: "https://act.10010.com/SigninApp/convert/getTelephone", form: {} }; let { result: responseResult } = await this.request(requestConfig); let status = appName.get(responseResult, "status", -1); if (status == "0000" && responseResult.data) { const currentAmount = parseFloat(responseResult.data.telephone) || 0; if (options.isInitial) { this.initialTelephoneAmount = currentAmount; this.log(`签到区-话费红包: 运行前总额 ${this.initialTelephoneAmount.toFixed(2)}元`); return; } if (this.initialTelephoneAmount !== null) { const increase = currentAmount - this.initialTelephoneAmount; this.log(`签到区-话费红包: 本次运行增加 ${increase.toFixed(2)}元`, { notify: true }); } let totalMessage = `签到区-话费红包: 总额 ${currentAmount.toFixed(2)}元`; if (parseFloat(responseResult.data.needexpNumber) > 0) { totalMessage += `,其中 ${responseResult.data.needexpNumber}元 将于 ${responseResult.data.month}月底到期`; } this.log(totalMessage, { notify: true }); } else { this.log(`签到区查询话费红包失败[${status}]: ${responseResult?.msg || ""}`); } } catch (error) { this.log(`签到区查询话费红包异常: ${error.message}`); } } async sign_getTaskList(options = {}) { try { const requestConfig = { fn: "sign_getTaskList", method: "get", url: "https://activity.10010.com/sixPalaceGridTurntableLottery/task/taskList", searchParams: { type: 2 }, headers: { "Referer": "https://img.client.10010.com/" } }; // Use a loop to handle tasks dynamically, similar to how bubble tasks are handled. // This allows us to claim rewards for tasks we've just completed in the same run. for (let i = 0; i < 30; i++) { // Loop with a max limit to prevent infinite loops. let { result: responseResult } = await this.request(requestConfig); let responseCode = appName.get(responseResult, "code", -1); if (responseCode != "0000") { this.log("签到区-任务中心: 获取任务列表失败[" + responseCode + "]: " + (responseResult?.desc || "")); return; } if (i === 0) { this.log("签到区-任务中心: 获取任务列表成功"); } const allTasks = [ ...(responseResult.data.tagList || []).flatMap(tag => tag.taskDTOList || []), ...(responseResult.data.taskList || []) ].filter(Boolean); if (allTasks.length === 0) { if (i === 0) this.log("签到区-任务中心: 当前无任何任务。"); break; // Exit loop if no tasks } // Priority 1: Execute actionable tasks (taskState: 1 and taskType: 5). const doTask = allTasks.find(task => task.taskState === "1" && task.taskType === "5"); if (doTask) { this.log(`签到区-任务中心: 开始执行任务 [${doTask.taskName}]`); await this.sign_doTaskFromList(doTask); await appName.wait(3000); continue; // Re-fetch task list, as the completed task might now be claimable. } // Priority 2: Claim rewards for completed tasks (taskState: 0). const claimTask = allTasks.find(task => task.taskState === "0"); if (claimTask) { this.log(`签到区-任务中心: 发现可领取奖励的任务 [${claimTask.taskName}]`); await this.sign_getTaskReward(claimTask.id); await appName.wait(2000); continue; // Re-fetch task list to get the next state. } // If we are here, no claimable or actionable tasks were found in this iteration. if (i === 0) { this.log("签到区-任务中心: 没有可执行或可领取的任务。"); } else { this.log("签到区-任务中心: 所有任务处理完毕。"); } break; // Exit the loop } } catch (error) { console.log(error); this.log("签到区-任务中心: 获取任务列表时发生异常: " + error.message); } } async sign_doTaskFromList(task, options = {}) { try { // this.log(`签到区-任务中心: 开始执行任务 [${task.taskName}]`); if (task.url && task.url !== "1" && task.url.startsWith("http")) { await this.request({ fn: "sign_doTaskFromList_visit", method: "get", url: task.url, headers: { "Referer": "https://img.client.10010.com/" } }); this.log(`签到区-任务中心: 浏览页面 [${task.taskName}]`); await appName.wait(5000 + Math.random() * 2000); } const orderId = await this.gettaskip(); const requestConfig = { fn: "sign_doTaskFromList_complete", method: "get", url: "https://activity.10010.com/sixPalaceGridTurntableLottery/task/completeTask", searchParams: { taskId: task.id, orderId: orderId, systemCode: "QDQD" } }; let { result: responseResult } = await this.request(requestConfig); let responseCode = appName.get(responseResult, "code", -1); if (responseCode == "0000") { this.log(`签到区-任务中心: ✅ 任务 [${task.taskName}] 已完成`); } else { this.log(`签到区-任务中心: ❌ 任务 [${task.taskName}] 完成失败[${responseCode}]: ${responseResult.desc || '未知错误'}`); } } catch (error) { console.log(error); this.log(`签到区-任务中心: 执行任务 [${task.taskName}] 时发生异常: ${error.message}`); } } async game_login(ticket, options = {}) { try { const requestBody = { identityType: "esToken", code: this.ecs_token, ticket: ticket, uuid: this.uuid }; const requestOptions = { fn: "game_login", method: "post", url: "https://game.wostore.cn/api/app//user/v2/login", headers: {}, json: requestBody }; requestOptions.headers.channelid = "GAMELTAPP_90005"; let { result: responseResult } = await this.request(requestOptions); let responseCode = appName.get(responseResult, "code", -1); if (responseCode == 200) { this.game_token = responseResult?.["data"]?.["access_token"]; this.got = this.got.extend({ headers: { Authorization: this.game_token } }); await this.game_getMemberInfo(); await this.game_signRecord(); await this.game_lottery(); await this.game_playSave(); await this.game_taskList(); await this.game_getMemberInfo(); const notifyOptions = { notify: true }; this.log("联通畅游币: " + this.point, notifyOptions); } else { let errorMessage = responseResult?.["msg"] || ""; this.log("联通畅游登录失败[" + responseCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async game_getMemberInfo(options = {}) { try { const requestOptions = { fn: "game_getMemberInfo", method: "get", url: "https://game.wostore.cn/api/app/user/v2/getMemberInfo" }; let { result: responseResult } = await this.request(requestOptions); let responseCode = appName.get(responseResult, "code", -1); if (responseCode == 200) { this.point = responseResult?.["data"]?.["userIntegral"]; } else { let errorMessage = responseResult?.["msg"] || ""; this.log("联通畅游查询积分失败[" + responseCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async game_signRecord(options = {}) { try { const requestOptions = { fn: "game_signRecord", method: "get", url: "https://game.wostore.cn/api/app/user/v2/signRecord" }; let { result: responseResult } = await this.request(requestOptions); let responseCode = appName.get(responseResult, "code", -1); if (responseCode == 200) { for (let record of responseResult?.["data"]) { if (record.now == 0) { continue; } this.log("联通畅游今天" + (record.signStatus == 2 ? "未" : "已") + "签到"); if (record.signStatus == 2) { await this.game_signIn(); } } } else { let errorMessage = responseResult?.["msg"] || ""; this.log("联通畅游查询签到失败[" + responseCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async game_signIn(options = {}) { try { const requestOptions = { fn: "game_signIn", method: "get", url: "https://game.wostore.cn/api/app/user/v2/signIn" }; let { result: responseResult } = await this.request(requestOptions); let responseCode = appName.get(responseResult, "code", -1); if (responseCode == 200) { this.log("联通畅游签到成功"); } else { let errorMessage = responseResult?.["msg"] || ""; this.log("联通畅游签到失败[" + responseCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async game_checkSlider(options = {}) { let isSuccess = false; try { const searchParams = { xPos: 234 }; const requestOptions = { fn: "game_checkSlider", method: "post", url: "https://game.wostore.cn/api/app/common/slider/checkSlider", searchParams: searchParams }; let { result: responseResult } = await this.request(requestOptions); let responseCode = appName.get(responseResult, "code", -1); if (responseCode == 200) { this.log("联通畅游滑块验证成功"); } else { let errorMessage = responseResult?.["msg"] || ""; this.log("联通畅游滑块验证失败[" + responseCode + "]: " + errorMessage); } } catch (error) { console.log(error); } finally { return isSuccess; } } async game_lottery(options = {}) { try { let requestOptions = { fn: "game_lottery", method: "get", url: "https://game.wostore.cn/api/app/user/v2/benefit/lottery", searchParams: { id: appName.get(options, "id", 1) } }; let { result: responseResult } = await this.request(requestOptions); let responseCode = appName.get(responseResult, "code", -1); if (responseCode == 200) { const notifyOptions = { notify: true }; this.log("联通畅游抽奖: " + responseResult?.["data"]?.["productName"], notifyOptions); } else { let errorMessage = responseResult?.["msg"] || ""; this.log("联通畅游抽奖失败[" + responseCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async game_taskList(options = {}) { try { const requestOptions = { fn: "game_taskList", method: "get", url: "https://game.wostore.cn/api/app/user/v2/task/list" }; let { result: responseResult } = await this.request(requestOptions); let responseCode = appName.get(responseResult, "code", -1); if (responseCode == 200) { for (let task of responseResult?.["data"]) { switch (task.receiveStatus) { case 0: break; case 1: await this.game_taskReceive(task); break; case 2: break; default: appName.log("任务[" + task.taskName + "]未知状态[" + task.receiveStatus + "]"); break; } } } else { let errorMessage = responseResult?.["msg"] || ""; this.log("联通畅游查询任务失败[" + responseCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async game_taskReceive(task, options = {}) { try { const searchParams = { productId: task.productId, taskId: task.id }; const requestOptions = { fn: "game_taskReceive", method: "get", url: "https://game.wostore.cn/api/app/user/v2/task/receive", searchParams: searchParams }; let { result: responseResult } = await this.request(requestOptions); let responseCode = appName.get(responseResult, "code", -1); if (responseCode == 200) { this.log("领取任务[" + task.taskName + "]奖励成功"); } else { let errorMessage = responseResult?.["msg"] || ""; this.log("领取任务[" + task.taskName + "]奖励失败[" + responseCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async game_playSave(options = {}) { try { let requestOptions = { fn: "game_playSave", method: "post", url: "https://game.wostore.cn/api/app/user/v2/play/save", json: { cpGameId: "15000199" + appName.randomString(2, "0123456789") } }; let { result: responseResult } = await this.request(requestOptions); let responseCode = appName.get(responseResult, "code", -1); if (!(responseCode == 200)) { let errorMessage = responseResult?.["msg"] || ""; this.log("联通畅游玩游戏失败[" + responseCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async flmf_login(loginUrl, options = {}) { try { const requestConfig = { fn: "flmf_login", method: "get", url: loginUrl }; let { headers: headers, statusCode: statusCode } = await this.request(requestConfig); if (headers?.["location"]) { let locationUrl = new URL(headers.location); this.flmf_sid = locationUrl.searchParams.get("sid"); this.flmf_sid ? (await this.flmf_signInInit(), await this.flmf_taskList(), await this.flmf_scanTask()) : this.log("福利魔方获取sid失败"); } else { this.log("福利魔方获取sid失败[" + statusCode + "]"); } } catch (error) { console.log(error); } } async flmf_signInInit(options = {}) { try { let requestConfig = { fn: "flmf_signInInit", method: "post", url: "https://weixin.linktech.hk/lv-apiaccess/welfareCenter/signInInit", form: this.get_flmf_data() }; let { result: responseResult } = await this.request(requestConfig); let resultCode = appName.get(responseResult, "resultCode", -1); if (resultCode == "0000") { this.log("福利魔方今天" + (responseResult?.["data"]?.["isSigned"] ? "已" : "未") + "签到, 已连续签到" + responseResult?.["data"]?.["consecutiveDays"] + "天"); if (!responseResult?.["data"]?.["isSigned"]) { await this.flmf_signIn(); } } else { let errorMessage = responseResult?.["resultMsg"] || ""; this.log("福利魔方查询签到失败[" + resultCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async flmf_signIn(options = {}) { try { let requestConfig = { fn: "flmf_signIn", method: "post", url: "https://weixin.linktech.hk/lv-apiaccess/welfareCenter/signIn", form: this.get_flmf_data() }; let { result: responseResult } = await this.request(requestConfig); let resultCode = appName.get(responseResult, "resultCode", -1); if (resultCode == "0000") { this.log("福利魔方签到成功"); } else { let errorMessage = responseResult?.["resultMsg"] || ""; this.log("福利魔方签到失败[" + resultCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async flmf_taskList(options = {}) { try { let requestConfig = { fn: "flmf_taskList", method: "post", url: "https://weixin.linktech.hk/lv-apiaccess/welfareCenter/taskList", form: this.get_flmf_data() }; let { result: responseResult } = await this.request(requestConfig); let resultCode = appName.get(responseResult, "resultCode", -1); if (resultCode == "0000") { for (let taskGroup of responseResult?.["data"]?.["taskInfoList"]) { for (let task of taskGroup.taskInfoList.filter(t => !t.done)) { for (let i = task.hascount; i < task.count; i++) { await this.flmf_gogLance(task.id); } } } } else { let errorMessage = responseResult?.["resultMsg"] || ""; this.log("福利魔方查询任务失败[" + resultCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async flmf_scanTask() { for (let taskId of someArray) { await this.flmf_gogLance(taskId); } } async flmf_gogLance(taskId, options = {}) { try { let requestConfig = { fn: "flmf_gogLance", method: "post", url: "https://weixin.linktech.hk/lv-apiaccess/welfareCenter/gogLance", form: { taskId: taskId, ...this.get_flmf_data() } }; let { result: responseResult } = await this.request(requestConfig); await appName.wait_gap_interval(this.t_flmf_task, delayMs); let resultCode = appName.get(responseResult, "resultCode", -1); this.t_flmf_task = Date.now(); if (resultCode == "0000") { this.log("完成任务[" + taskId + "]成功"); } else { let errorMessage = responseResult?.["resultMsg"] || ""; this.log("完成任务[" + taskId + "]失败[" + resultCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } // ============================================ // 联通阅读 NEW LOGIC START (移植自Python脚本) // ============================================ // 1. 设备预登录 (获取accesstoken) async woread_auth(options = {}) { let authSuccess = false; try { // Python: timestamp = round(time() * 1000) let timestamp = Date.now(); // Python: md5(f'100000027k1HcDL8RKvc{timestamp}') let signStr = productId + secretKey + timestamp; let md5Hash = cryptoJS.MD5(signStr).toString(); // Python: crypt_text = f'{{"timestamp":"{self.date}"}}' // self.date format: %Y%m%d%H%M%S let dateStr = appName.time("yyyyMMddhhmmss"); let cryptTextObj = { timestamp: dateStr }; // encrypt using AES (key="woreadst^&*12345") let encodedSign = this.encode_woread(cryptTextObj); const requestOptions = { fn: "woread_auth", method: "post", url: `https://10010.woread.com.cn/ng_woread_service/rest/app/auth/${productId}/${timestamp}/${md5Hash}`, json: { sign: encodedSign } }; let { result: responseData } = await this.request(requestOptions); let responseCode = appName.get(responseData, "code", -1); if (responseCode == "0000") { authSuccess = true; this.woread_accesstoken = responseData?.["data"]?.["accesstoken"]; // 设置Header中的accesstoken this.got = this.got.extend({ headers: { accesstoken: this.woread_accesstoken } }); // this.log("阅读专区: 设备认证成功"); } else { let errorMessage = responseData?.["message"] || ""; this.log("阅读专区: 设备认证失败[" + responseCode + "]: " + errorMessage); } } catch (error) { console.log(error); this.log("阅读专区: 设备认证异常:" + error.message); } finally { return authSuccess; } } // 2. 账号登录 (使用token_online) async woread_login(options = {}) { let loginSuccess = false; try { // 1. 确保设备认证已完成 if (!this.woread_accesstoken) { if(!await this.woread_auth()) return false; } // 2. 构造加密参数 if (!this.token_online) { this.log("阅读专区: 缺少 token_online,无法进行新版登录"); return false; } let token_enc = this.encode_woread_str(this.token_online); // 使用当前手机号,如果没获取到则用默认占位符 let phone_str = this.mobile || "13800000000"; let phone_enc = this.encode_woread_str(phone_str); let timestamp = appName.time("yyyyMMddhhmmss"); // 构造内层JSON字符串: crypt_text let innerJson = JSON.stringify({ tokenOnline: token_enc, phone: phone_enc, timestamp: timestamp }); // 3. 对内层JSON再次加密生成sign let encodedSign = this.encode_woread_str(innerJson); const requestOptions = { fn: "woread_login", method: "post", url: "https://10010.woread.com.cn/ng_woread_service/rest/account/login", json: { sign: encodedSign } }; let { result: responseData } = await this.request(requestOptions); let responseCode = appName.get(responseData, "code", -1); if (responseCode === "0000") { loginSuccess = true; let { userid, userindex, token, verifycode, phone } = responseData?.["data"]; this.woread_token = token; this.woread_verifycode = verifycode; this.woread_userid = userid; this.woread_userindex = userindex; // 如果返回了真实手机号,更新它 if (phone) { this.mobile = phone; this.name = phone; // Update display name } this.log(`阅读专区: 登录成功`); } else { let errorMessage = responseData?.["message"] || responseData?.["msg"] || "未知错误"; this.log(`阅读专区: 登录失败[${responseCode}]: ${errorMessage}`); } } catch (error) { console.log(error); this.log("阅读专区: 登录异常:" + error.message); } finally { return loginSuccess; } } // 3. 获取书籍信息 async woread_get_book_info() { try { // 1. 获取推荐位信息得到 cntindex let url1 = "https://10010.woread.com.cn/ng_woread_service/rest/basics/recommposdetail/14856"; let { result: res1 } = await this.request({ fn: "woread_book", method: "get", url: url1 }); if (res1?.code === '0000') { this.wr_catid = res1.data.booklist.message[0].catindex; this.wr_cardid = res1.data.bindinfo[0].recommposiindex; this.wr_cntindex = res1.data.booklist.message[0].cntindex; } else { this.log("阅读专区: 获取书籍列表失败"); return false; } // 2. 获取章节信息得到 chapterallindex if (!this.wr_cntindex) return false; let param = { curPage: 1, limit: 30, index: this.wr_cntindex, sort: 0, finishFlag: 1, ...this.get_woread_param() }; let sign = this.encode_woread(param); let url2 = "https://10010.woread.com.cn/ng_woread_service/rest/cnt/chalist"; let { result: res2 } = await this.request({ fn: "woread_chap", method: "post", url: url2, json: { sign } }); if (res2?.list && res2.list.length > 0) { this.wr_chapterallindex = res2.list[0].charptercontent[0].chapterallindex; this.wr_chapterid = res2.list[0].charptercontent[0].chapterid; return true; } return false; } catch (e) { this.log("阅读专区: 获取书籍信息异常"); return false; } } // 4. 阅读模拟 (心跳 + 增加时长) async woread_read_process() { if (!await this.woread_get_book_info()) { this.log("阅读专区: 无法获取书籍信息,跳过阅读"); return; } // Python脚本循环1次 let loopCount = 1; for (let i = 0; i < loopCount; i++) { try { // 4.1 发送阅读心跳 wordsDetail let param = { chapterAllIndex: this.wr_chapterallindex, cntIndex: this.wr_cntindex, cntTypeFlag: "1", ...this.get_woread_param() }; let sign = this.encode_woread(param); await this.request({ fn: "woread_heartbeat", method: "post", url: `https://10010.woread.com.cn/ng_woread_service/rest/cnt/wordsDetail?catid=${this.wr_catid}&cardid=${this.wr_cardid}&cntindex=${this.wr_cntindex}&chapterallindex=${this.wr_chapterallindex}&chapterseno=1`, json: { sign } }); // 4.2 增加阅读时长 addReadTime let addParam = { readTime: "2", cntIndex: this.wr_cntindex, cntType: "1", catid: "0", pageIndex: "", cardid: this.wr_cardid, cntindex: this.wr_cntindex, cnttype: "1", chapterallindex: this.wr_chapterallindex, chapterseno: "1", channelid: "", chapterid: this.wr_chapterid, readtype: 1, isend: "0", ...this.get_woread_param() }; let addSign = this.encode_woread(addParam); let { result: addRes } = await this.request({ fn: "woread_addTime", method: "post", url: "https://10010.woread.com.cn/ng_woread_service/rest/history/addReadTime", json: { sign: addSign } }); if (addRes?.code === '0000') { this.log(`阅读专区: 模拟阅读成功`); } else { this.log(`阅读专区: 模拟阅读失败: ${addRes?.msg}`); } await appName.wait(2000); } catch (e) { console.log(e); } } } // 5. 新版抽奖 async woread_draw_new() { try { let param = { activeindex: "8051", // Python脚本指定的活动ID ...this.get_woread_param() }; let sign = this.encode_woread(param); let { result: res } = await this.request({ fn: "woread_draw", method: "post", url: "https://10010.woread.com.cn/ng_woread_service/rest/basics/doDraw", json: { sign } }); if (res?.code === '0000') { this.log(`阅读专区: 抽奖成功: ${res.data.prizedesc}`, { notify: true }); } else { this.log(`阅读专区: 抽奖失败: ${res?.msg || res?.message}`); } } catch (e) { this.log(`阅读专区: 抽奖异常: ${e.message}`); } } async woread_queryTicketAccount(options = {}) { try { let requestParams = this.get_woread_param(), encodedSign = this.encode_woread(requestParams); const signData = { sign: encodedSign }; const requestOptions = { fn: "woread_queryTicketAccount", method: "post", url: "https://10010.woread.com.cn/ng_woread_service/rest/phone/vouchers/queryTicketAccount", json: signData }; let { result: responseData } = await this.request(requestOptions), responseCode = appName.get(responseData, "code", -1); if (responseCode == "0000") { let balance = (responseData?.["data"]?.["usableNum"] / 100).toFixed(2); const notifyOptions = { notify: true }; this.log("阅读区话费红包余额: " + balance, notifyOptions); } else { let errorMessage = responseData?.["message"] || ""; this.log("查询阅读区话费红包余额失败[" + responseCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } // ============================================ // 联通阅读 NEW LOGIC END // ============================================ async act_517_userAccount(options = {}) { try { const requestOptions = { fn: "act_517_userAccount", method: "get", url: "https://activity.10010.com/2024517charges/lottery/userAccount" }; { let { result: responseResult, statusCode: responseStatus } = await this.request(appName.copy(requestOptions)); let responseCode = appName.get(responseResult, "code", responseStatus); if (responseCode == "0000") { await this.act_517_taskList(); } else { let errorMessage = responseResult?.["message"] || responseResult?.["msg"] || ""; this.log("517活动进入主页失败[" + responseCode + "]: " + errorMessage); return; } } { let { result: responseResult, statusCode: responseStatus } = await this.request(appName.copy(requestOptions)); let responseCode = appName.get(responseResult, "code", responseStatus); if (responseCode == "0000") { let { chances: chances } = responseResult?.["data"]; this.log("517活动可以抽奖" + chances + "次"); let isFirstDraw = false; while (chances-- > 0) { if (isFirstDraw) { await appName.wait(3000); } isFirstDraw = true; await this.act_517_lottery(); } } else { let errorMessage = responseResult?.["message"] || responseResult?.["msg"] || ""; this.log("517活动查询抽奖次数失败[" + responseCode + "]: " + errorMessage); } } { let { result: responseResult, statusCode: responseStatus } = await this.request(appName.copy(requestOptions)); let responseCode = appName.get(responseResult, "code", responseStatus); if (responseCode == "0000") { let { amount: amount, targetAmount: targetAmount } = responseResult?.["data"]; const notifyOptions = { notify: true }; this.log("517活动现金进度: " + amount + "/" + targetAmount, notifyOptions); } else { let errorMessage = responseResult?.["message"] || responseResult?.["msg"] || ""; this.log("517活动查询进度失败[" + responseCode + "]: " + errorMessage); } } } catch (error) { console.log(error); } } async act_517_bind(shareCode, options = {}) { try { const requestOptions = { fn: "act_517_bind", method: "post", url: "https://activity.10010.com/2024517charges/openWindows/bind", json: {}, valid_code: [401] }; requestOptions.json.shareCode = shareCode; requestOptions.json.channel = "countersign"; let { result: responseResult } = await this.request(requestOptions); } catch (error) { console.log(error); } } async act_517_lottery(options = {}) { try { const requestOptions = { fn: "act_517_lottery", method: "get", url: "https://activity.10010.com/2024517charges/lottery/lottery" }; let { result: responseResult, statusCode: responseStatus } = await this.request(requestOptions); let responseCode = appName.get(responseResult, "code", responseStatus); if (responseCode == "0000") { responseResult?.["data"]?.["uuid"] ? (await appName.wait(2000), await this.act_517_winningRecord(responseResult.data.uuid)) : this.log("517活动抽奖失败, 没有返回uuid"); } else { let errorMessage = responseResult?.["message"] || responseResult?.["msg"] || ""; this.log("517活动抽奖失败[" + responseCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async act_517_winningRecord(requestId, options = {}) { try { const searchParams = { requestId: requestId }; const requestOptions = { fn: "act_517_winningRecord", method: "get", url: "https://activity.10010.com/2024517charges/lottery/winningRecord", searchParams: searchParams }; let { result: responseResult, statusCode: responseStatus } = await this.request(requestOptions); let responseCode = appName.get(responseResult, "code", responseStatus); if (responseCode == "0000") { if (responseResult?.["data"]?.["isWin"] === "1") { let { prizeAmount: prizeAmount, prizeList: prizeList, afterAmount: afterAmount, targetAmount: targetAmount, showAmount = "0" } = responseResult?.["data"], prizeNames = (prizeList || []).filter(p => p.prizeName).map(p => p.prizeName).join(", ") || ""; const notifyOptions = { notify: true }; if (prizeNames) { this.log("517活动抽奖: " + prizeNames, notifyOptions); } if (showAmount === "1") { this.log("517活动抽奖现金进度: +" + prizeAmount + " (" + afterAmount + "/" + targetAmount + ")"); } } else { this.log("517活动抽奖: 空气"); } } else { let errorMessage = responseResult?.["message"] || responseResult?.["msg"] || ""; this.log("查询517活动抽奖结果失败[" + responseCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async act_517_taskList(options = {}) { try { const requestOptions = { fn: "act_517_taskList", method: "get", url: "https://activity.10010.com/2024517charges/dotask/taskList" }; let { result: responseResult, statusCode: responseStatus } = await this.request(requestOptions); let responseCode = appName.get(responseResult, "code", responseStatus); if (responseCode == "0000") { let taskList = responseResult?.["data"]?.["taskList"] || []; for (let task of taskList) { let { completeNum = 0, maxNum: maxNum, isComplete: isComplete, taskType: taskType } = task; if (isComplete) { continue; } if (taskType == "5") { continue; } completeNum = parseInt(completeNum); maxNum = parseInt(maxNum); for (let i = completeNum; i < maxNum; i++) { await this.act_517_completeTask(task); } } } else { let errorMessage = responseResult?.["message"] || responseResult?.["msg"] || ""; this.log("查询517活动抽奖结果失败[" + responseCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async act_517_completeTask(task, options = {}) { try { let taskTitle = task.title; const searchParams = { taskId: task.taskId }; const requestOptions = { fn: "act_517_completeTask", method: "get", url: "https://activity.10010.com/2024517charges/dotask/completeTask", searchParams: searchParams }; let { result: responseResult, statusCode: responseStatus } = await this.request(requestOptions); let responseCode = appName.get(responseResult, "code", responseStatus); if (responseCode == "0000") { if (responseResult?.["data"]) { let { num: num, title: title } = responseResult.data; this.log("完成任务[" + title + "]成功: " + num + "次抽奖机会"); } else { this.log("完成任务[" + taskTitle + "]失败没有获得抽奖机会"); } } else { let errorMessage = responseResult?.["message"] || responseResult?.["msg"] || ""; this.log("完成任务[" + taskTitle + "]失败[" + responseCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } get_wocare_body(apiCode, requestData = {}) { const timestamp = appName.time("yyyyMMddhhmmssS"), encodedContent = Buffer.from(JSON.stringify(requestData)).toString("base64"); let body = { version: minRetries, apiCode: apiCode, channelId: anotherApiKey, transactionId: timestamp + appName.randomString(6, numbers), timeStamp: timestamp, messageContent: encodedContent }, paramsArray = []; Object.keys(body).sort().forEach(key => { paramsArray.push(key + "=" + body[key]); }); paramsArray.push("sign=" + anotherEncryptionKey); body.sign = cryptoJS.MD5(paramsArray.join("&")).toString(); return body; } async wocare_api(apiCode, requestData = {}) { let body = this.get_wocare_body(apiCode, requestData); const requestOptions = { fn: "wocare_" + apiCode, method: "post", url: "https://wocare.unisk.cn/api/v1/" + apiCode, form: body }; let response = await this.request(requestOptions); if (response?.["result"]?.["messageContent"]) { try { let decodedContent = JSON.parse(Buffer.from(response.result.messageContent, "base64").toString()); response.result.data = decodedContent?.["data"] || decodedContent; if (decodedContent?.["resultMsg"]) { response.result.resultMsg = decodedContent.resultMsg; } } catch (error) { this.log("联通祝福: 解析返回失败:"); console.log(error); } } return response; } async wocare_getToken(ticket, options = {}) { let isSuccess = false; try { let requestOptions = { fn: "wocare_getToken", method: "get", url: "https://wocare.unisk.cn/mbh/getToken", searchParams: { channelType: serviceLife, type: "02", ticket: ticket, version: appVersion, timestamp: appName.time("yyyyMMddhhmmssS"), desmobile: this.mobile, num: 0, postage: appName.randomString(32), homePage: "home", duanlianjieabc: "qAz2m", userNumber: this.mobile } }, { headers: headers, statusCode: statusCode } = await this.request(requestOptions); if (statusCode == 302) { if (headers?.["location"]) { let locationUrl = new URL(headers.location), sid = locationUrl.searchParams.get("sid"); sid ? (this.wocare_sid = sid, isSuccess = await this.wocare_loginmbh()) : this.log("联通祝福: 没有获取到sid"); } else { this.log("联通祝福: 没有获取到location"); } } else { this.log("联通祝福: 获取sid失败[" + statusCode + "]"); } } catch (error) { console.log(error); } finally { return isSuccess; } } async wocare_loginmbh(options = {}) { let isSuccess = false; try { let apiCode = "loginmbh"; const requestData = { sid: this.wocare_sid, channelType: serviceLife, apiCode: apiCode }; let { result: responseResult, statusCode: responseStatus } = await this.wocare_api(apiCode, requestData); let resultCode = appName.get(responseResult, "resultCode", responseStatus); if (resultCode == "0000") { isSuccess = true; let { token: token } = responseResult?.["data"]; this.wocare_token = token; } else { let errorMessage = responseResult?.["resultMsg"] || responseResult?.["resultDesc"] || ""; this.log("联通祝福: 登录失败[" + resultCode + "]: " + errorMessage); } } catch (error) { console.log(error); } finally { return isSuccess; } } async wocare_getSpecificityBanner(options = {}) { try { let apiCode = "getSpecificityBanner"; const requestData = { token: this.wocare_token, apiCode: apiCode }; let { result: responseResult, statusCode: responseStatus } = await this.wocare_api(apiCode, requestData); let resultCode = appName.get(responseResult, "resultCode", responseStatus); if (resultCode == "0000") { let bannerList = responseResult?.["data"] || []; for (let banner of bannerList.filter(b => b.activityStatus === "0" && b.isDeleted === "0")) { await this.wocare_getDrawTask(banner); await this.wocare_loadInit(banner); } } else { let errorMessage = responseResult?.["resultMsg"] || responseResult?.["resultDesc"] || ""; this.log("联通祝福: 进入活动失败[" + resultCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async wocare_loadInit(activity, options = {}) { try { let apiCode = "loadInit"; const requestData = { token: this.wocare_token, channelType: serviceLife, type: activity.id, apiCode: apiCode }; let { result: responseResult, statusCode: responseStatus } = await this.wocare_api(apiCode, requestData); let resultCode = appName.get(responseResult, "resultCode", responseStatus); if (resultCode == "0000") { let responseData = responseResult?.["data"], activeModuleGroupId = responseData?.["zActiveModuleGroupId"], drawCount = 0; switch (activity.id) { case 2: { let isPartake = responseData?.["data"]?.["isPartake"] || 0; !isPartake && (drawCount = 1); break; } case 3: { drawCount = parseInt(responseData?.["raffleCountValue"] || 0); break; } case 4: { drawCount = parseInt(responseData?.["mhRaffleCountValue"] || 0); break; } } while (drawCount-- > 0) { await appName.wait(5000); await this.wocare_luckDraw(activity, activeModuleGroupId); } } else { let errorMessage = responseResult?.["resultMsg"] || responseResult?.["resultDesc"] || ""; this.log("联通祝福: [" + activity.name + "]查询活动失败[" + resultCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async wocare_getDrawTask(activity, options = {}) { try { let apiCode = "getDrawTask"; const requestData = { token: this.wocare_token, channelType: serviceLife, type: activity.id, apiCode: apiCode }; let { result: responseResult, statusCode: responseStatus } = await this.wocare_api(apiCode, requestData); let resultCode = appName.get(responseResult, "resultCode", responseStatus); if (resultCode == "0000") { let taskList = responseResult?.["data"]?.["taskList"] || []; for (let task of taskList.filter(t => t.taskStatus == 0)) { await this.wocare_completeTask(activity, task); } } else { let errorMessage = responseResult?.["resultMsg"] || responseResult?.["resultDesc"] || ""; this.log("联通祝福: [" + activity.name + "]查询任务失败[" + resultCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async wocare_completeTask(activity, task, taskStep = "1", options = {}) { try { let taskTitle = task.title, action = taskStep == "1" ? "领取任务" : "完成任务", apiCode = "completeTask"; const requestData = { token: this.wocare_token, channelType: serviceLife, task: task.id, taskStep: taskStep, type: activity.id, apiCode: apiCode }; let { result: responseResult, statusCode: responseStatus } = await this.wocare_api(apiCode, requestData); let resultCode = appName.get(responseResult, "resultCode", responseStatus); if (resultCode == "0000") { this.log("联通祝福: " + action + "[" + taskTitle + "]成功"); taskStep == "1" && (await this.wocare_completeTask(activity, task, "4")); } else { let errorMessage = responseResult?.["resultMsg"] || responseResult?.["resultDesc"] || ""; this.log("联通祝福: [" + activity.name + "]" + action + "[" + taskTitle + "]失败[" + resultCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async wocare_luckDraw(activity, activeModuleGroupId, options = {}) { try { let apiCode = "luckDraw"; const requestData = { token: this.wocare_token, channelType: serviceLife, zActiveModuleGroupId: activeModuleGroupId, type: activity.id, apiCode: apiCode }; let { result: responseResult, statusCode: responseStatus } = await this.wocare_api(apiCode, requestData); let resultCode = appName.get(responseResult, "resultCode", responseStatus); if (resultCode == "0000") { let drawResultCode = appName.get(responseResult?.["data"], "resultCode", -1); if (drawResultCode == "0000") { let { prizeName: prizeName, prizeDesc: prizeDesc } = responseResult?.["data"]?.["data"]?.["prize"]; this.log("联通祝福: [" + activity.name + "]抽奖: " + prizeName + "[" + prizeDesc + "]"); } else { let errorMessage = responseResult?.["resultMsg"] || responseResult?.["resultDesc"] || ""; this.log("联通祝福: [" + activity.name + "]抽奖失败[" + drawResultCode + "]: " + errorMessage); } } else { let errorMessage = responseResult?.["resultMsg"] || responseResult?.["resultDesc"] || ""; this.log("联通祝福: [" + activity.name + "]抽奖错误[" + resultCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async card_618_authCheck(options = {}) { try { let requestConfig = { fn: "card_618_authCheck", method: "post", url: "https://epay.10010.com/ps-pafs-auth-front/v1/auth/check", headers: { bizchannelinfo: this.get_bizchannelinfo() } }; let { result: responseResult } = await this.request(requestConfig); let responseCode = appName.get(responseResult, "code", -1); if (responseCode == "0000") { let { mobile: mobile, sessionId: sessionId, tokenId: tokenId, userId: userId } = responseResult?.["data"]?.["authInfo"]; const authInfo = { sessionId: sessionId, tokenId: tokenId, userId: userId }; Object.assign(this, authInfo); await this.card_618_queryUserCardInfo(); } else { if (responseCode == "2101000100") { let loginUrl = responseResult?.["data"]?.["woauth_login_url"]; await this.card_618_login(loginUrl); } else { let errorMessage = responseResult?.["msgInside"] || responseResult?.["msg"] || ""; this.log("618集卡获取tokenId失败[" + responseCode + "]: " + errorMessage); } } } catch (error) { console.log(error); } } async card_618_login(loginUrl, options = {}) { try { let templateName = appName.time("yyyyMM") + "28ZFR"; loginUrl += "https://epay.10010.com/ci-mcss-party-web/rainbow/?templateName=" + templateName + "&bizFrom=225&bizChannelCode=225&channelType=WDQB"; const requestOptions = { fn: "card_618_login", method: "get", url: "https://epay.10010.com/woauth2/login", searchParams: {} }; requestOptions.searchParams.response_type = "web_token"; requestOptions.searchParams.source = "app_sjyyt"; requestOptions.searchParams.union_session_id = ""; requestOptions.searchParams.device_digest_token_id = this.tokenId_cookie; requestOptions.searchParams.target_client_id = anotherClientId; requestOptions.searchParams.position = null; requestOptions.searchParams.redirect_url = "https://epay.10010.com/ci-mcss-party-web/cardSelection/?activityId=NZJK618CJHD"; requestOptions.searchParams.bizFrom = errorCode; requestOptions.searchParams.bizChannelCode = errorNumber; requestOptions.searchParams.channelType = "WDQB"; let { headers: headers, statusCode: statusCode } = await this.request(requestOptions); if (headers?.["location"]) { let locationUrl = new URL(headers.location); this.rptId = locationUrl.searchParams.get("rptid"); this.rptId ? await this.card_618_authCheck() : this.log("618集卡获取rptid失败"); } else { this.log("618集卡获取rptid失败[" + statusCode + "]"); } } catch (error) { console.log(error); } } async card_618_queryUserCardInfo(options = {}) { try { const requestBody = { activityId: "NZJK618CJHD" }; let requestConfig = { fn: "card_618_queryUserCardInfo", method: "post", url: "https://epay.10010.com/ci-mcss-party-front/v1/mouldCard/queryUserCardInfo", headers: { bizchannelinfo: this.get_bizchannelinfo(), authinfo: this.get_epay_authinfo() }, form: requestBody }; let { result: responseResult } = await this.request(requestConfig); let responseCode = appName.get(responseResult, "code", -1); if (responseCode == "0000" && responseResult?.["data"]?.["returnCode"] == 0) { let { userRemain = 0, isFirst = true } = responseResult?.["data"]; if (isFirst) { await this.card_618_unifyDraw("首次进入"); } this.log("618集卡可以抽奖" + userRemain + "次"); while (userRemain-- > 0) { await this.card_618_unifyDraw("抽奖"); } } else { let errorMessage = responseResult?.["message"] || responseResult?.["msg"] || ""; this.log("618集卡进入主页失败[" + responseCode + "]: " + errorMessage); } } catch (error) { console.log(error); } } async card_618_unifyDraw(drawType, options = {}) { try { let requestConfig = { fn: "card_618_unifyDraw", method: "post", url: "https://epay.10010.com/ci-mcss-party-front/v1/mouldCard/unifyDraw", headers: { bizchannelinfo: this.get_bizchannelinfo(), authinfo: this.get_epay_authinfo() }, form: { bigActivityId: activityIds.card_618, activityId: activityIds.card_618 + card618DrawTypeSuffix[drawType], bizFrom: errorCode } }; let { result: responseResult } = await this.request(requestConfig); let responseCode = appName.get(responseResult, "code", -1); if (responseCode == "0000" && responseResult?.["data"]?.["returnCode"] == 0) { let prizeId = responseResult?.["data"]?.["prizeId"] || "空气", prizeName = card618PrizeMap[prizeId] || prizeId; const notifyOptions = { notify: true }; this.log("618集卡[" + drawType + "]: " + prizeName, notifyOptions); } else { let errorMessage = responseResult?.["data"]?.["returnMsg"] || responseResult?.["msg"] || ""; this.log("618集卡[" + drawType + "]失败[" + (responseResult?.["data"]?.["returnCode"] || responseCode) + "]: " + errorMessage); } } catch (error) { console.log(error); } } //联通安全管家 async securityButlerTask() { try { this.log("============= 联通安全管家 ============="); // This replaces getOnlineStatus from the original script, as data is already available. if (!this.ecs_token || !this.mobile) { this.log("安全管家任务缺少 ecs_token 或 mobile,跳过。"); return; } // Initialize points tracking this.sec_oldJFPoints = null; // Get all necessary tickets and tokens await this.getTicketByNative_sec(); await this.getAuthToken_sec(); await this.getTicketForJF_sec(); if (!this.sec_ticket || !this.sec_token) { this.log("安全管家获取票据失败,跳过任务。"); return; } // this.log("安全管家CK获取完毕,等待5秒..."); await appName.wait(5000); await this.getUserInfo_sec(); // Get initial points await this.executeAllTasks_sec(); await appName.wait(15000); await this.getUserInfo_sec(); // Get final points and log the difference } catch (e) { this.log(`联通安全管家任务出现错误: ${e.message}`); console.log(e); } } async getTicketByNative_sec() { let requestOptions = { "fn": "getTicketByNative_sec", "url": `https://m.client.10010.com/edop_ng/getTicketByNative?token=${this.ecs_token}&appId=edop_unicom_3a6cc75a`, "headers": { "Cookie": `PvSessionId=${appName.time("yyyyMMddhhmmss")}${this.unicomTokenId};c_mobile=${this.mobile}; c_version=iphone_c@11.0800; city=036|${this.city?.[0]?.cityCode || ''}|90063345|-99;devicedId=${this.unicomTokenId}; ecs_token=${this.ecs_token};t3_token=`, "Accept": "*", "Connection": "keep-alive", "Content-Type": "application/x-www-form-urlencoded", "Accept-Encoding": "gzip;q=1.0, compress;q=0.5", "Host": "m.client.10010.com", "User-Agent": "ChinaUnicom4.x/12.3.1 (com.chinaunicom.mobilebusiness; build:77; iOS 16.6.0) Alamofire/4.7.3 unicom{version:iphone_c@12.0301}", "Accept-Language": "zh-Hans-CN;q=1.0" } }; let { result } = await this.request(requestOptions); this.sec_ticket1 = result ? result.ticket : null; } async getAuthToken_sec() { if (!this.sec_ticket1) { this.log("安全管家 getAuthToken_sec 缺少 ticket1,跳过"); return; } let requestOptions = { "fn": "getAuthToken_sec", "url": "https://uca.wo116114.com/api/v1/auth/ticket?product_line=uasp&entry_point=h5&entry_point_id=edop_unicom_3a6cc75a", "method": "post", "headers": { "User-Agent": "ChinaUnicom4.x/12.3.1 (com.chinaunicom.mobilebusiness; build:77; iOS 16.6.0) Alamofire/4.7.3 unicom{version:iphone_c@12.0301}", "Accept": "*", "Accept-Encoding": "gzip;q=1.0, compress;q=0.5", "Content-Type": "application/json", "Accept-Language": "zh-Hans-CN;q=1.0", "clientType": "uasp_unicom_applet" }, "json": { "productId": "", "type": 1, "ticket": this.sec_ticket1 } }; let { result } = await this.request(requestOptions); if (result && result.data) { this.sec_token = result.data.access_token; } } async getTicketForJF_sec() { if (!this.sec_token) { this.log("安全管家 getTicketForJF_sec 缺少 token,跳过"); return; } let requestOptions = { "fn": "getTicketForJF_sec_1", "method": "post", "url": "https://uca.wo116114.com/api/v1/auth/getTicket?product_line=uasp&entry_point=h5&entry_point_id=edop_unicom_3a6cc75a", "headers": { "User-Agent": "ChinaUnicom4.x/12.3.1 (com.chinaunicom.mobilebusiness; build:77; iOS 16.6.0) Alamofire/4.7.3 unicom{version:iphone_c@12.0301}", "Content-Type": "application/json", "auth-sa-token": this.sec_token, "clientType": "uasp_unicom_applet" }, "json": { "productId": "91311616", "phone": this.mobile } }; let { result } = await this.request(requestOptions); if (result && result.data) { this.sec_ticket = result.data.ticket; } else { this.log("安全管家获取积分票据失败"); return; } let queryOptions = { "fn": "getTicketForJF_sec_2", "method": "post", "url": "https://m.jf.10010.com/jf-external-application/page/query", "headers": { "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 unicom{version:iphone_c@12.0301};ltst;OSVersion/16.6", "partnersid": "1702", "ticket": decodeURIComponent(this.sec_ticket), "Cookie": `_jea_id=${this.sec_jeaId}`, "clienttype": "uasp_unicom_applet", }, "json": { "activityId": "s747395186896173056", "partnersId": "1702" } }; let { headers } = await this.request(queryOptions); const setCookieHeader = headers?.["set-cookie"]; if (setCookieHeader) { const cookies = Array.isArray(setCookieHeader) ? setCookieHeader : [setCookieHeader]; const jeaCookie = cookies.find(cookie => cookie && cookie.startsWith("_jea_id=")); if (jeaCookie) { const newJeaId = jeaCookie.split(";")[0].split("=")[1]; if (newJeaId) { this.sec_jeaId = newJeaId; this.log("安全管家: 更新 jeaId: " + this.sec_jeaId); } } } } async operateBlacklist_sec(phoneNumber, type) { const typeName = type === 0 ? "添加" : "删除"; this.log(`安全管家: 正在执行${typeName}黑名单号码: ${phoneNumber}`); let requestOptions = { "fn": `operateBlacklist_sec_${typeName}`, "method": "post", "url": "https://uca.wo116114.com/sjgj/woAssistant/umm/configs/v1/config?product_line=uasp&entry_point=h5&entry_point_id=wxdefbc1986dc757a6", "headers": { "User-Agent": "ChinaUnicom4.x/12.3.1 (com.chinaunicom.mobilebusiness; build:77; iOS 16.6.0) Alamofire/4.7.3 unicom{version:iphone_c@12.0301}", "auth-sa-token": this.sec_token, "clientType": "uasp_unicom_applet", "token": this.sec_token, "Cookie": `devicedId=${this.unicomTokenId}` }, "json": { "productId": "91015539", "type": 1, "operationType": type, ...(type === 0 ? { "blacklistSource": 0 } : {}), "contents": [{ "content": phoneNumber, "contentTag": "", "nickname": null, "configTime": null }] } }; let { result } = await this.request(requestOptions); return result; } async addToBlacklist_sec() { const phoneNumberToOperate = "13088888888"; let response = await this.operateBlacklist_sec(phoneNumberToOperate, 0); // 检查多种成功条件: code 为 '0000' 或 0, 或者 msg 为 '成功' if (response && (response.code === '0000' || response.code === 0 || response.msg === '成功')) { this.log(`安全管家: ✅ 添加黑名单成功。`); return; } const isDuplicateError = response && response.msg && response.msg.includes("号码已存在"); if (isDuplicateError) { this.log(`安全管家: ⚠️ 检测到号码 ${phoneNumberToOperate} 已存在,执行先删除后添加流程。`); let delResponse = await this.operateBlacklist_sec(phoneNumberToOperate, 1); // 检查删除操作的多种成功/可接受条件 const isDelSuccess = delResponse && (delResponse.code === '0000' || delResponse.code === 0 || (delResponse.msg && (delResponse.msg.includes("成功") || delResponse.msg.includes("不在黑名单")))); if (isDelSuccess) { this.log(`安全管家: ✅ 删除旧记录成功,等待 2 秒后重新添加...`); await appName.wait(2000); let retryResponse = await this.operateBlacklist_sec(phoneNumberToOperate, 0); // 重新检查添加操作的多种成功条件 if (retryResponse && (retryResponse.code === '0000' || retryResponse.code === 0 || retryResponse.msg === '成功')) { this.log(`安全管家: ✅ 重新添加黑名单成功。`); } else { this.log(`安全管家: ❌ 重新添加失败: ${retryResponse ? retryResponse.msg : '无响应'}`); } } else { this.log(`安全管家: ❌ 删除旧记录失败,无法继续添加。`); } } else { // 其他未知的失败情况 this.log(`安全管家: ❌ 添加黑名单失败: ${response ? response.msg : '无响应'}`); } } async markPhoneNumber_sec() { let requestOptions = { "fn": "markPhoneNumber_sec", "method": "post", "url": "https://uca.wo116114.com/sjgj/unicomAssistant/uasp/configs/v1/addressBook/saveTagPhone?product_line=uasp&entry_point=h5&entry_point_id=wxdefbc1986dc757a6", "headers": { "User-Agent": "ChinaUnicom4.x/12.3.1 (com.chinaunicom.mobilebusiness; build:77; iOS 16.6.0) Alamofire/4.7.3 unicom{version:iphone_c@12.0301}", "auth-sa-token": this.sec_token, "clientType": "uasp_unicom_applet" }, "json": { "tagPhoneNo": "13088330789", "tagIds": [26], "status": 0, "productId": "91311616" } }; await this.request(requestOptions); this.log("安全管家: 执行号码标记。"); } async syncAddressBook_sec() { let requestOptions = { "fn": "syncAddressBook_sec", "method": "post", "url": "https://uca.wo116114.com/sjgj/unicomAssistant/uasp/configs/v1/addressBookBatchConfig?product_line=uasp&entry_point=h5&entry_point_id=edop_unicom_3a6cc75a", "headers": { "User-Agent": "ChinaUnicom4.x/12.3.1 (com.chinaunicom.mobilebusiness; build:77; iOS 16.6.0) Alamofire/4.7.3 unicom{version:iphone_c@12.0301}", "auth-sa-token": this.sec_token, "clientType": "uasp_unicom_applet" }, "json": { "addressBookDTOList": [{ "addressBookPhoneNo": "13088888888", "addressBookName": "水水" }], "productId": "91311616", "opType": "1" } }; await this.request(requestOptions); this.log("安全管家: 执行同步通讯录。"); } async setInterceptionRules_sec() { let requestOptions = { "fn": "setInterceptionRules_sec", "method": "post", "url": "https://uca.wo116114.com/sjgj/woAssistant/umm/configs/v1/config?product_line=uasp&entry_point=h5&entry_point_id=wxdefbc1986dc757a6", "headers": { "User-Agent": "ChinaUnicom4.x/12.3.1 (com.chinaunicom.mobilebusiness; build:77; iOS 16.6.0) Alamofire/4.7.3 unicom{version:iphone_c@12.0301}", "auth-sa-token": this.sec_token, "clientType": "uasp_unicom_applet" }, "json": { "contents": [{ "name": "rings-once", "contentTag": "8", "contentName": "响一声", "content": "0", "icon": "alerting" }], "operationType": 0, "type": 3, "productId": "91311616" } }; await this.request(requestOptions); this.log("安全管家: 执行设置拦截规则。"); } async viewWeeklyStatus_sec() { let requestOptions = { "fn": "viewWeeklyStatus_sec", "method": "post", "url": "https://uca.wo116114.com/sjgj/unicomAssistant/uasp/configs/v1/weeklySwitchStatus?product_line=uasp&entry_point=h5&entry_point_id=wxdefbc1986dc757a6", "headers": { "auth-sa-token": this.sec_token, "clientType": "uasp_unicom_applet" }, "json": { "productId": "91311616" } }; await this.request(requestOptions); } async queryKeyData_sec() { let requestOptions = { "fn": "queryKeyData_sec", "method": "post", "url": "https://uca.wo116114.com/sjgj/unicomAssistant/uasp/report/v1/queryKeyData?product_line=uasp&entry_point=h5&entry_point_id=wxdefbc1986dc757a6", "headers": { "auth-sa-token": this.sec_token, "clientType": "uasp_unicom_applet" }, "json": { "productId": "91311616" } }; await this.request(requestOptions); } async viewWeeklySummary_sec() { let requestOptions = { "fn": "viewWeeklySummary_sec", "method": "post", "url": "https://uca.wo116114.com/sjgj/unicomAssistant/uasp/report/v1/weeklySummary?product_line=uasp&entry_point=h5&entry_point_id=wxdefbc1986dc757a6", "headers": { "auth-sa-token": this.sec_token, "clientType": "uasp_unicom_applet" }, "json": { "productId": "91311616" } }; await this.request(requestOptions); this.log("安全管家: 执行查看周报。"); } async receivePoints_sec(taskCode) { let requestOptions = { "fn": "receivePoints_sec", "method": "post", "url": "https://m.jf.10010.com/jf-external-application/jftask/receive", "headers": { "ticket": decodeURIComponent(this.sec_ticket), "Cookie": `_jea_id=${this.sec_jeaId}`, "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 unicom{version:iphone_c@12.0301};ltst;OSVersion/16.6", "partnersid": "1702", "clienttype": "uasp_unicom_applet", }, "json": { "taskCode": taskCode } }; let { result } = await this.request(requestOptions); if (result && result.data && result.data.score) { this.log(`安全管家: ✅ 领取积分成功: +${result.data.score} (${result.msg})`); } else if (result) { this.log(`安全管家: ❌ 领取积分失败: ${result.msg}`); } else { this.log("安全管家: ❌ 领取积分API无响应"); } } async finishTask_sec(taskCode, taskName) { let requestOptions = { "fn": `finishTask_sec_${taskName}`, "method": "post", "url": "https://m.jf.10010.com/jf-external-application/jftask/toFinish", "headers": { "ticket": decodeURIComponent(this.sec_ticket), "Cookie": `_jea_id=${this.sec_jeaId}`, "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 unicom{version:iphone_c@12.0301};ltst;OSVersion/16.6", "partnersid": "1702", "clienttype": "uasp_unicom_applet", }, "json": { "taskCode": taskCode } }; await this.request(requestOptions); this.log(`安全管家: 开启任务 [${taskName}]`); switch (taskName) { case "联通助理-添加黑名单": await this.addToBlacklist_sec(); break; case "联通助理-号码标记": await this.markPhoneNumber_sec(); break; case "联通助理-同步通讯录": await this.syncAddressBook_sec(); break; case "联通助理-骚扰拦截设置": await this.setInterceptionRules_sec(); break; case "联通助理-查看周报": await this.viewWeeklyStatus_sec(); await this.queryKeyData_sec(); await this.viewWeeklySummary_sec(); break; default: // No action needed as filtering is done upstream break; } } async signIn_sec(taskCode) { let requestOptions = { "fn": "signIn_sec", "method": "post", "url": "https://m.jf.10010.com/jf-external-application/jftask/sign", "headers": { "ticket": decodeURIComponent(this.sec_ticket), "Cookie": `_jea_id=${this.sec_jeaId}`, "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 unicom{version:iphone_c@12.0301};ltst;OSVersion/16.6", "partnersid": "1702", "clienttype": "uasp_unicom_applet", }, "json": { "taskCode": taskCode } }; let { result } = await this.request(requestOptions); this.log(`安全管家: 完成签到: ${result?.msg || '状态未知'}`); } async executeAllTasks_sec() { let requestOptions = { "fn": "executeAllTasks_sec", "method": "post", "url": "https://m.jf.10010.com/jf-external-application/jftask/taskDetail", "headers": { "ticket": decodeURIComponent(this.sec_ticket), "Cookie": `_jea_id=${this.sec_jeaId}`, "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 unicom{version:iphone_c@12.0301};ltst;OSVersion/16.6", "partnersid": "1702", "clienttype": "uasp_unicom_applet", }, "json": {} }; let { result } = await this.request(requestOptions); if (!result || !result.data || !result.data.taskDetail) { this.log("安全管家: 查询任务列表失败或响应格式错误。"); return; } const taskList = result.data.taskDetail.taskList; const executableTaskNames = [ "联通助理-添加黑名单", "联通助理-号码标记", "联通助理-同步通讯录", "联通助理-骚扰拦截设置", "联通助理-查看周报" ]; const executableTasks = []; const skippedTasks = []; for (const task of taskList) { const isKnownExecutable = executableTaskNames.includes(task.taskName) || task.taskName.includes("签到"); if (isKnownExecutable) { executableTasks.push(task); } else { skippedTasks.push(task); } } const unfinishedSkipped = skippedTasks.filter(t => t.finishCount !== t.needCount); if (unfinishedSkipped.length > 0) { const skippedTaskNames = unfinishedSkipped.map(t => `[${t.taskName}]`).join(', '); this.log(`安全管家: 跳过: ${skippedTaskNames}`); } for (const task of executableTasks) { const { taskCode, taskName, finishCount, needCount, finishText } = task; this.log(`安全管家: [${taskName}]: ${finishCount}/${needCount} - ${finishText}`); if (finishCount !== needCount) { const remainingCount = needCount - finishCount; this.log(`安全管家: 任务未完成,需要再执行 ${remainingCount} 次`); for (let i = 0; i < remainingCount; i++) { await appName.wait(3000); try { if (taskName.includes("签到")) { await this.signIn_sec(taskCode); } else { await this.finishTask_sec(taskCode, taskName); } if (!taskName.includes("签到")) { await appName.wait(10000); await this.receivePoints_sec(taskCode); } else { await this.receivePoints_sec(taskCode); break; } } catch (error) { this.log(`安全管家: 执行 ${taskCode} 时出错: ${error.message}`); break; } } } else if (finishText === "待领取") { try { await appName.wait(3000); await this.receivePoints_sec(taskCode); } catch (error) { this.log(`安全管家: 领取 ${taskCode} 奖励时出错: ${error.message}`); } } else { this.log(`安全管家: [${taskName}] 任务已完成且奖励已领取`); } this.log("安全管家: ---------------------"); } } async getUserInfo_sec() { let requestOptions = { "fn": "getUserInfo_sec", "method": "post", "url": "https://m.jf.10010.com/jf-external-application/jftask/userInfo", "headers": { "ticket": decodeURIComponent(this.sec_ticket), "Cookie": `_jea_id=${this.sec_jeaId}`, "User-Agent": "Mozilla/5.0 (Linux; Android 9; ONEPLUS A5000 Build/PKQ1.180716.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/138.0.7204.179 Mobile Safari/537.36; unicom{version:android@11.0000,desmobile:0};devicetype{deviceBrand:OnePlus,deviceModel:ONEPLUS A5000}", "partnersid": "1702", "clienttype": "uasp_unicom_applet", }, "json": {} }; let { result } = await this.request(requestOptions); if (!result || result.code !== '0000' || !result.data || result.data.availableScore === undefined) { this.log(`安全管家: 查询积分失败或响应格式错误。错误信息: ${result ? result.msg : '无响应'}`); return; } const currentPoints = parseInt(result.data.availableScore, 10); const todayPoints = result.data.todayEarnScore; if (this.sec_oldJFPoints === null) { this.sec_oldJFPoints = currentPoints; this.log(`安全管家: 运行前积分:${currentPoints} (今日已赚 ${todayPoints})`); } else { if (isNaN(currentPoints) || isNaN(this.sec_oldJFPoints)) { this.log(`安全管家: 警告:积分值无法转换为数字进行计算。`); this.log(`安全管家: 运行后可用积分: ${result.data.availableScore}`, { notify: true }); } else { const pointsGained = currentPoints - this.sec_oldJFPoints; this.log(`安全管家: 运行后积分${currentPoints},本次运行获得${pointsGained}`, { notify: true }); } } } // 联通云盘任务 async ltyp_task() { try { this.log("============= 联通云盘任务 ============="); this.cloudDisk = {}; // Reset state for this run this.cloudDiskUrls = { 'onLine': "https://m.client.10010.com/mobileService/onLine.htm", 'getTicketByNative': "https://m.client.10010.com/edop_ng/getTicketByNative", 'userticket': "https://panservice.mail.wo.cn/api-user/api/user/ticket", 'ltypDispatcher': "https://panservice.mail.wo.cn/wohome/dispatcher", 'query': "https://m.jf.10010.com/jf-external-application/page/query", 'taskDetail': "https://m.jf.10010.com/jf-external-application/jftask/taskDetail", 'dosign': "https://m.jf.10010.com/jf-external-application/jftask/sign", 'doUpload': "https://b.smartont.net/openapi/transfer/quickTransfer", 'doPopUp': "https://m.jf.10010.com/jf-external-application/jftask/popUp", 'toFinish': "https://m.jf.10010.com/jf-external-application/jftask/toFinish", 'lottery': "https://panservice.mail.wo.cn/activity/lottery", 'activityList': "https://panservice.mail.wo.cn/activity/v1/activityList", 'userInfo': "https://m.jf.10010.com/jf-external-application/jftask/userInfo", 'ai_query': "https://panservice.mail.wo.cn/wohome/ai/assistant/query", 'lottery_times': "https://panservice.mail.wo.cn/activity/lottery/lottery-times", }; if (!this.ecs_token || !this.mobile) { this.log("云盘任务: 缺少 ecs_token 或 mobile,跳过。"); return; } const ticket = await this.getTicketByNative_cloud(); if (!ticket) { this.log("云盘任务: 获取ticket失败,跳过。"); return; } const token = await this.get_ltypDispatcher_cloud(ticket); if (!token) { this.log("云盘任务: 获取token失败,跳过。"); return; } await appName.wait(500); await this.get_userInfo_cloud(); // Initial points await appName.wait(500); await this.get_taskDetail_cloud(); const got_chance = await this.do_ai_query_for_lottery_cloud(); if (got_chance) { await appName.wait(5000); let times = await this.check_lottery_times_cloud(); if (times > 0) { for (let i = 0; i < times; i++) { this.log(`云盘第 ${i + 1}/${times} 次执行抽奖...`); await this.get_ltyplottery_cloud('MjI='); await appName.wait(5000); } } } await appName.wait(500); await this.get_userInfo_cloud(); // Final points } catch (e) { this.log(`云盘任务: 出现错误: ${e.message}`); console.log(e); } } encrypt_data_cloud(data, key, iv = "wNSOYIB1k1DjY5lA") { if (typeof data === 'object') { data = JSON.stringify(data); } const keyHex = cryptoJS.enc.Utf8.parse(key.slice(0, 16)); const ivHex = cryptoJS.enc.Utf8.parse(iv); const encrypted = cryptoJS.AES.encrypt(data, keyHex, { iv: ivHex, mode: cryptoJS.mode.CBC, padding: cryptoJS.pad.Pkcs7 }); return encrypted.toString(); } async getTicketByNative_cloud() { let requestOptions = { fn: "getTicketByNative_cloud", method: 'get', url: `${this.cloudDiskUrls.getTicketByNative}?appId=edop_unicom_d67b3e30&token=${this.ecs_token}`, headers: { 'User-Agent': "Dalvik/2.1.0 (Linux; U; Android 12; leijun Pro Build/SKQ1.22013.001);unicom{version:android@11.0702}", 'Connection': "Keep-Alive", 'Accept-Encoding': "gzip", } }; let { result } = await this.request(requestOptions); if (result?.ticket) { this.cloudDisk.ticket = result.ticket; return result.ticket; } return null; } async get_ltypDispatcher_cloud(ticket) { const timestamp = Date.now().toString(); const result = Math.floor(Math.random() * (199999 - 123456 + 1)) + 123456; const string_to_hash = "HandheldHallAutoLoginV2" + timestamp + result + "wohome"; const md5Hash = cryptoJS.MD5(string_to_hash).toString(); const payload = { "header": { "key": "HandheldHallAutoLoginV2", "resTime": timestamp, "reqSeq": result, "channel": "wohome", "version": "", "sign": md5Hash }, "body": { "clientId": "1001000003", "ticket": ticket } }; let requestOptions = { fn: "get_ltypDispatcher_cloud", method: 'post', url: this.cloudDiskUrls.ltypDispatcher, json: payload, headers: { 'User-Agent': "Dalvik/2.1.0 (Linux; U; Android 12; leijun Pro Build/SKQ1.22013.001);unicom{version:android@11.0702}" } }; let { result: res } = await this.request(requestOptions); const token = res?.RSP?.DATA?.token; if (token) { this.cloudDisk.userToken = token; return token; } this.log(`云盘任务: 获取token失败: ${JSON.stringify(res)}`); return null; } async get_userticket_cloud(is_changer = false) { if (!this.cloudDisk.userToken) { this.log("云盘任务: 获取userticket失败, userToken未获取"); return null; } let headers = {}; if (is_changer) { headers = { 'User-Agent': "LianTongYunPan/4.0.4 (Android 12)", 'app-type': "liantongyunpanapp", 'Client-Id': "1001000035", 'App-Version': "yp-app/4.0.4", 'Sys-Version': "Android/12", 'X-YP-Client-Id': "1001000035", 'X-YP-Access-Token': this.cloudDisk.userToken, }; } else { headers = { 'User-Agent': "Dalvik/2.1.0 (Linux; U; Android 12; leijun Pro Build/SKQ1.22013.001);unicom{version:android@11.0702}", 'Content-Type': 'application/json', 'X-YP-Access-Token': this.cloudDisk.userToken, 'accesstoken': this.cloudDisk.userToken, 'token': this.cloudDisk.userToken, 'clientId': "1001000003", 'X-YP-Client-Id': "1001000003", 'source-type': "woapi", 'app-type': "unicom" }; } let requestOptions = { fn: "get_userticket_cloud", method: 'post', url: this.cloudDiskUrls.userticket, json: {}, headers: headers }; let { result: res } = await this.request(requestOptions); const ticket = res?.result?.ticket; if (ticket) { this.cloudDisk.userticket = ticket; await appName.wait(1000); return ticket; } this.log(`云盘任务: 获取userticket失败: ${JSON.stringify(res)}`); return null; } async get_userInfo_cloud() { if (!await this.get_userticket_cloud(false)) return; let { result: res, headers } = await this.cloudRequest('userInfo', {}, false, 'post'); const setCookieHeader = headers?.["set-cookie"]; if (setCookieHeader) { const cookies = Array.isArray(setCookieHeader) ? setCookieHeader : [setCookieHeader]; const jeaCookie = cookies.find(cookie => cookie && cookie.startsWith("_jea_id=")); if (jeaCookie) { this.cloudDisk.jeaId = jeaCookie.split(";")[0].split("=")[1]; } } if (res?.data?.availableScore) { const availableScore = res.data.availableScore; const allEarnScore = res.data.allEarnScore; if (this.cloudDisk.initial_score === undefined) { this.cloudDisk.initial_score = parseInt(allEarnScore, 10); this.log(`云盘任务: 运行前 - 已赚积分: ${allEarnScore}, 可用积分: ${availableScore}`); } else { const earned_this_run = parseInt(allEarnScore, 10) - this.cloudDisk.initial_score; this.log(`云盘任务: 运行后 - 已赚: ${allEarnScore}, 可用: ${availableScore}, 本次获得: ${earned_this_run}积分`, { notify: true }); } } else { this.log(`云盘任务: 获取用户信息失败: ${JSON.stringify(res)}`); } } async get_taskDetail_cloud() { if (!await this.get_userticket_cloud(false)) return; let { result: res } = await this.cloudRequest('taskDetail', {}, false, 'post'); if (res?.data?.taskDetail?.taskList) { const taskList = res.data.taskDetail.taskList; const taskNameList = ["浏览活动中心", "分享文件", "签到", "与AI通通互动", "打开相册自动备份"]; for (const task of taskList) { await appName.wait(500); if (task.finishText === "未完成" && taskNameList.some(name => task.taskName.includes(name))) { this.log(`云盘任务: 开始执行 [${task.taskName}]`); if (task.taskName.includes("浏览活动中心")) { await this.toFinish_cloud(task.taskCode, task.taskName, true); await this.activityList_cloud(task.taskCode, task.taskName); } else if (task.taskName.includes("分享文件")) { await this.toFinish_cloud(task.taskCode, task.taskName, false); await this.get_ShareFileDispatcher_cloud(task.taskCode, task.taskName); } else if (task.taskName.includes("签到")) { await this.toFinish_cloud(task.taskCode, task.taskName, false); await this.dosign_cloud(task.taskCode, task.taskName); } else if (task.taskName.includes("与AI通通互动")) { await this.toFinish_cloud(task.taskCode, task.taskName, false); await this.do_ai_interaction_cloud(task.taskCode, task.taskName); } else if (task.taskName.includes("打开相册自动备份")) { await this.toFinish_cloud(task.taskCode, task.taskName, false); // Action to simulate opening the album backup page if (!await this.get_userticket_cloud(true)) return; const payload = { "bizKey": "activityCenterPipeline", "bizObject": { "pageNo": 1 } }; let { result: res } = await this.cloudRequest('activityList', payload, true); if (res?.meta?.code === 0 || res?.meta?.code === "0") { this.log(`云盘任务: ✅ [${task.taskName}] 打开成功`); await appName.wait(2000); } else { this.log(`云盘任务: ❌ [${task.taskName}] 打开失败: ${JSON.stringify(res)}`); } } } if (task.finishText === "未完成" && task.taskNameSubtitle && task.taskName.includes("手动上传文件")) { this.log(`云盘任务: 开始执行 [${task.taskName}]`); await this.toFinish_cloud(task.taskCode, task.taskName, false); const subtitle = task.taskNameSubtitle; const [current_count_str, target_count_str] = subtitle.replace(/[()]/g, "").split("/"); let current_count = parseInt(current_count_str, 10); let target_count = parseInt(target_count_str, 10); if (current_count < target_count) { const remaining_times = target_count - current_count; this.log(`云盘任务: [${task.taskName}] 需 ${remaining_times} 次`); for (let i = 0; i < remaining_times; i++) { if(await this.doUpload_cloud(task.taskCode, task.taskName)) { this.log(`云盘任务: [${task.taskName}] 第 ${current_count + i + 1} 次上传完成`); await appName.wait(500); } else { break; } } } } } } else { this.log(`云盘任务: 获取任务列表失败: ${JSON.stringify(res)}`); } } async cloudRequest(url_name, payload, is_changer = false, method = 'post') { const url = this.cloudDiskUrls[url_name]; if (!url) { this.log(`云盘无效的URL名称: ${url_name}`); return { result: null, headers: null }; } let headers = { 'User-Agent': "Dalvik/2.1.0 (Linux; U; Android 12; leijun Pro Build/SKQ1.22013.001);unicom{version:android@11.0702}", 'Connection': "Keep-Alive", 'Accept-Encoding': "gzip", }; if (['dosign', 'userInfo', 'doPopUp', 'toFinish', 'taskDetail'].includes(url_name)) { if (!this.cloudDisk.userticket) { this.log(`云盘 [${url_name}] userticket 未获取`); return { result: null, headers: null }; } headers['ticket'] = this.cloudDisk.userticket; headers['content-type'] = "application/json;charset=UTF-8"; headers['partnersid'] = "1649"; headers['origin'] = "https://m.jf.10010.com"; if (this.cloudDisk.jeaId) headers['Cookie'] = `_jea_id=${this.cloudDisk.jeaId}`; if (is_changer) { headers['clienttype'] = "yunpan_unicom_applet"; headers['x-requested-with'] = "com.sinovatech.unicom.ui"; if (url_name === 'toFinish') { headers['User-Agent'] = "Mozilla/5.0 (Linux; Android 12; Redmi K30 Pro Build/SKQ1.220303.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.39 Mobile Safari/537.36/woapp LianTongYunPan/4.0.4 (Android 12)"; headers['clienttype'] = "yunpan_android"; headers['x-requested-with'] = "com.chinaunicom.bol.cloudapp"; } } else { headers['clienttype'] = "yunpan_android"; headers['x-requested-with'] = "com.sinovatech.unicom.ui"; } } else if (url_name === 'activityList') { headers = { 'User-Agent': "Mozilla/5.0 (Linux; Android 12; Redmi K30 Pro Build/SKQ1.220303.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.39 Mobile Safari/537.36/woapp LianTongYunPan/4.0.4 (Android 12)", 'Accept': "application/json, text/plain, */*", 'Accept-Encoding': "gzip, deflate, br, zstd", 'Content-Type': "application/json", 'credentials': "include", 'sec-ch-ua-platform': '"Android"', 'sec-ch-ua': '"Android WebView";v="131", "Chromium";v="131", "Not_A Brand";v="24"', 'sec-ch-ua-mobile': "?1", 'Client-Id': "1001000035", 'App-Version': "yp-app/4.0.4", 'Access-Token': this.cloudDisk.userToken, 'Sys-Version': "android/12", 'Origin': "https://panservice.mail.wo.cn", 'X-Requested-With': "com.chinaunicom.bol.cloudapp", 'Sec-Fetch-Site': "same-origin", 'Sec-Fetch-Mode': "cors", 'Sec-Fetch-Dest': "empty", 'Referer': "https://panservice.mail.wo.cn/h5/mobile/wocloud/activityCenter/home", 'Accept-Language': "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7" }; } else if (url_name === 'doUpload') { headers = { 'User-Agent': "okhttp-okgo/jeasonlzy LianTongYunPan/4.0.4 (Android 12)", 'client-Id': "1001000035", 'app-version': "yp-app/4.0.4", 'access-token': this.cloudDisk.userToken, 'Content-Type': "application/json;charset=utf-8" }; } else if (url_name === 'ai_query') { const model_id = payload.modelId || 1; headers = { 'accept': 'text/event-stream', 'X-YP-Access-Token': this.cloudDisk.userToken, 'X-YP-App-Version': '5.0.12', 'X-YP-Client-Id': '1001000035', 'User-Agent': 'Mozilla/5.0 (Linux; Android 9; SM-N9810 Build/PQ3A.190705.11211540; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.114 Mobile Safari/537.36/woapp LianTongYunPan/5.0.12 (Android 9)', 'Content-Type': 'application/json', 'Origin': 'https://panservice.mail.wo.cn', 'X-Requested-With': 'com.chinaunicom.bol.cloudapp', 'Referer': `https://panservice.mail.wo.cn/h5/wocloud_ai/?modelType=${model_id}&clientId=1001000035&touchpoint=300300010001&token=${this.cloudDisk.userToken}`, }; } else if (url_name === 'lottery_times') { method = 'get'; payload = { activityId: 'MjI=' }; headers = { 'X-YP-Access-Token': this.cloudDisk.userToken, 'source-type': 'woapi', 'clientId': '1001000165', 'token': this.cloudDisk.userToken, 'X-YP-Client-Id': '1001000165', }; } else if (url_name === 'lottery') { const activity_id_b64 = payload.activityId || ''; const activity_id_b64_encoded = encodeURIComponent(activity_id_b64); headers = { 'User-Agent': 'Mozilla/5.0 (Linux; Android 9; SM-N9810 Build/PQ3A.190705.11211540; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.114 Mobile Safari/537.36/woapp LianTongYunPan/5.0.12 (Android 9)', 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json', 'X-Requested-With': 'com.chinaunicom.bol.cloudapp', 'requesttime': Date.now().toString(), 'clientid': '1001000165', 'x-yp-client-id': '1001000165', 'source-type': 'woapi', 'x-yp-access-token': this.cloudDisk.userToken, 'token': this.cloudDisk.userToken, 'origin': 'https://panservice.mail.wo.cn', 'Referer': `https://panservice.mail.wo.cn/h5/activitymobile/blindBox?activityId=${activity_id_b64_encoded}&touchpoint=300300010001&clientId=1001000035&token=${this.cloudDisk.userToken}`, }; } let requestOptions = { fn: `cloud_${url_name}`, method: method, url: method === 'get' ? `${url}?${new URLSearchParams(payload)}` : url, headers: headers, }; if (method === 'post') { requestOptions.json = payload; } if (url_name === 'ai_query') { const { result, headers } = await this.request(requestOptions); // The raw body is in `result` for text/event-stream. Return it as `body`. return { result: null, body: result, headers: headers }; } let { result, headers: resHeaders } = await this.request(requestOptions); return { result, headers: resHeaders }; } async dosign_cloud(taskcode, taskName) { if (!await this.get_userticket_cloud(false)) return; const payload = { "taskCode": taskcode }; let { result: res } = await this.cloudRequest('dosign', payload, false); if (res?.code?.includes('0000') && res?.data?.score) { this.log(`云盘任务: ✅ [${taskName}] 完成, 获得积分: ${res.data.score}`); } else { this.log(`云盘任务: ❌ [${taskName}] 失败: ${JSON.stringify(res)}`); } } async toFinish_cloud(taskcode, taskName, is_changer) { if (!await this.get_userticket_cloud(is_changer)) return null; const payload = { "taskCode": taskcode }; let { result: res } = await this.cloudRequest('toFinish', payload, is_changer); if (res?.code === "0000") return true; this.log(`云盘任务: ❌ [${taskName}] toFinish失败: ${JSON.stringify(res)}`); return false; } async doUpload_cloud(taskcode, taskName) { if (!await this.get_userticket_cloud(false)) return; const payload = { "batchNo": "D94628B6C8593D2C6A4B52D0A5F009F4", "deviceId": "", "directoryId": "0", "familyId": 0, "fileModificationTime": 1736861613000, "fileName": "mmexport1736861613242.jpg", "fileSize": "280800", "fileType": "1", "height": "1174", "lat": "", "lng": "", "psToken": "", "sha256": "9c75f5be16bbb4e17788180dfdf4b1d53ba590cb8f4c629e4b337f5f54565949", "spaceType": "0", "width": "986" }; let { result: res } = await this.cloudRequest('doUpload', payload, false); if (res?.meta?.code === "0000") { await appName.wait(1000); return await this.doPopUp_cloud(taskcode, taskName, false); } this.log(`云盘任务: ❌ [${taskName}] 上传失败: ${JSON.stringify(res)}`); return false; } async activityList_cloud(taskcode, taskName) { if (!await this.get_userticket_cloud(true)) return; const payload = { "bizKey": "activityCenterPipeline", "bizObject": { "pageNo": 1 } }; let { result: res } = await this.cloudRequest('activityList', payload, true); if (res?.meta?.code === 0 || res?.meta?.code === "0") { await appName.wait(2000); return await this.doPopUp_cloud(taskcode, taskName, true); } this.log(`云盘任务: ❌ [${taskName}] 浏览活动失败: ${JSON.stringify(res)}`); return false; } async doPopUp_cloud(taskcode, taskName, is_changer) { if (!await this.get_userticket_cloud(is_changer)) return; const payload = {}; await appName.wait(5500); let { result: res } = await this.cloudRequest('doPopUp', payload, is_changer); if ((res?.meta?.code === "0000" || res?.meta?.code === 0) || (res?.code === "0000" || res?.code === 0)) { const score = parseInt(res?.data?.score || "0", 10); this.log(`云盘任务: ✅ [${taskName}] 完成, ${score > 0 ? `获得积分: ${score}` : '未获得积分'}`); return true; } this.log(`云盘任务: ❌ [${taskName}] 领取奖励失败: ${JSON.stringify(res)}`); return false; } async get_ShareFileDispatcher_cloud(taskCode, taskName) { const timestamp = Date.now().toString(); const randomSeq = Math.floor(Math.random() * (199999 - 123456 + 1)) + 123456; const string_to_hash = "ShareFile" + timestamp + randomSeq + "wohome"; const md5Hash = cryptoJS.MD5(string_to_hash).toString(); const data = { "fileIds": "f89417024f2642a399fd33f2beebd7c2", "fileFolderIds": "", "days": 7, "clientId": "1001000003" }; const encrypted = this.encrypt_data_cloud(data, this.cloudDisk.userToken); const payload = { "header": { "key": "ShareFile", "resTime": timestamp, "reqSeq": randomSeq, "channel": "wohome", "version": "", "sign": md5Hash }, "body": { "clientId": "1001000003", "param": JSON.stringify(encrypted), "secret": true } }; const headers = { 'client-id': "1001000174", 'x-yp-client-id': "1001000174" }; let { result: res } = await this.cloudRequest('ltypDispatcher', payload, false, 'post', headers); if (res?.STATUS === "200" || res?.STATUS === 200) { await this.doPopUp_cloud(taskCode, taskName, false); } else { this.log(`云盘任务: ❌ [${taskName}] 分享失败: ${JSON.stringify(res)}`); } } async do_ai_interaction_cloud(taskCode, taskName) { this.log("云盘任务: 执行AI通通查询请求..."); const payload = { "input": "Hi", "platform": 1, "modelId": 0, "tag": 0, "conversationId": "", "knowledgeId": "", "referFileInfo": [] }; let { body } = await this.cloudRequest('ai_query', payload, false, 'post'); if (body && body.includes('"finish":1')) { this.log("云盘任务: AI通通查询请求成功"); return await this.doPopUp_cloud(taskCode, taskName, false); } this.log(`云盘任务: ❌ AI通通查询请求失败: ${body}`); return false; } async do_ai_query_for_lottery_cloud() { this.log("云盘任务: DeepSeek对话请求, 以获取抽奖资格..."); const payload = { "input": "Hi", "platform": 1, "modelId": 1, "tag": 0, "conversationId": "", "knowledgeId": "", "referFileInfo": [] }; let { body } = await this.cloudRequest('ai_query', payload, false, 'post'); if (body && body.includes('"finish":1')) { this.log("云盘任务: DeepSeek对话请求成功"); return true; } else { this.log(`云盘任务: ❌ DeepSeek对话请求失败: ${body}`); return false; } } async check_lottery_times_cloud() { this.log("云盘任务: 正在查询抽奖次数..."); let { result: res } = await this.cloudRequest('lottery_times', {}, false, 'get'); if (res?.meta?.code === "200") { const times = parseInt(res.result || "0", 10); this.log(`云盘任务: 查询成功,剩余抽奖次数: ${times}`); return times; } this.log(`云盘任务: ❌ 查询抽奖次数失败: ${JSON.stringify(res)}`); return 0; } async get_ltyplottery_cloud(activityId_b64) { const payload = { "bizKey": "newLottery", "activityId": activityId_b64, "bizObject": { "lottery": { "activityId": activityId_b64, "type": 3 } } }; let { result: res } = await this.cloudRequest('lottery', payload, false, 'post'); if (res?.meta?.code === '200' && res?.result?.prizeName) { this.log(`云盘任务: ✅ 抽奖获得: ${res.result.prizeName}`); return true; } this.log(`云盘任务: ❌ 抽奖失败: ${JSON.stringify(res)}`); return false; } async sign_task() { await this.sign_getTelephone({ isInitial: true }); await this.sign_getContinuous(); await this.sign_getTaskList(); await this.sign_getTelephone(); } async ltcy_task() { let targetUrl = "https://web.wostore.cn/web/flowGame/index.html?channelId=GAMELTAPP_90006&pushid=99", { ticket: ticket } = await this.openPlatLineNew(targetUrl); if (!ticket) { return; } await this.game_login(ticket); } async ttlxj_task() { this.rptId = ""; let targetUrl = "https://epay.10010.com/ci-mps-st-web/?webViewNavIsHidden=webViewNavIsHidden", { ticket: ticket, type: type, loc: location } = await this.openPlatLineNew(targetUrl); if (!ticket) { return; } await this.ttlxj_authorize(ticket, type, location); } async epay_28_task() { this.rptId = ""; let currentDay = new Date().getDate(); if (currentDay >= 26 && currentDay <= 28) { await this.epay_28_authCheck(); if (appMonth_28_share.length) { let randomShareCode = appName.randomList(appMonth_28_share); await this.appMonth_28_bind(randomShareCode); } await this.appMonth_28_queryChance(); } } async draw_28_task() { let currentDay = new Date().getDate(); currentDay == 28 && (await this.draw_28_queryChance()); } async act_517_task() { let startTime = new Date("2024-05-10 00:00:00"), endTime = new Date("2024-06-09 00:00:00"), currentTime = Date.now(); if (currentTime > startTime.getTime() && currentTime < endTime.getTime()) { if (act_517_share.length) { let randomShareCode = appName.randomList(act_517_share); await this.act_517_bind(randomShareCode); } await this.act_517_userAccount(); } } async card_618_task() { let startTime = new Date("2024-05-31 00:00:00"), endTime = new Date("2024-06-21 00:00:00"), currentTime = Date.now(); currentTime > startTime.getTime() && currentTime < endTime.getTime() && (this.rptId = "", await this.card_618_authCheck()); } async flmf_task() { if (this.city.filter(cityInfo => cityInfo.proCode == "091").length == 0) { return; } let targetUrl = "https://weixin.linktech.hk/lv-web/handHall/autoLogin?actcode=welfareCenter", { loc: location } = await this.openPlatLineNew(targetUrl); if (!location) { return; } await this.flmf_login(location); } async ltzf_task() { let targetUrl = new URL("https://wocare.unisk.cn/mbh/getToken"); targetUrl.searchParams.append("channelType", serviceLife); targetUrl.searchParams.append("homePage", "home"); targetUrl.searchParams.append("duanlianjieabc", "qAz2m"); let urlString = targetUrl.toString(), { ticket: ticket } = await this.openPlatLineNew(urlString); if (!ticket) { return; } if (!(await this.wocare_getToken(ticket))) { return; } for (let activity of wocareActivities) { await this.wocare_getDrawTask(activity); await this.wocare_loadInit(activity); } } // 重写后的联通阅读任务入口 async woread_task() { this.log("============= 联通阅读 ============="); // 1. 登录 (woread_login 内部已经包含了 woread_auth) if (!await this.woread_login()) { this.log("阅读专区: 登录失败,跳过任务"); return; } // 2. 执行阅读 (对应 Python 的 read_novel) await this.woread_read_process(); await appName.wait(3000); // 3. 抽奖 (对应 Python 的 cj) await this.woread_draw_new(); await appName.wait(3000); // 4. 查询红包余额 (对应 query_red) await this.woread_queryTicketAccount(); this.log("============= 联通阅读执行完毕 ============="); } // 旧的挂机任务,已废弃 async woread_reading_task() { } async userLoginTask() { if (!(await this.onLine())) { return; } return; } async userTask() { // 修改日志标题,包含手机号 appName.log(`\n------------------ 账号[${this.index}][${maskStr(this.name)}] ------------------`); // 在后续的日志中隐藏手机号 this.log = (message, options = {}) => super.log(message, { ...options, hideName: true }); if (!signDisabled) { await this.sign_task(); } await this.ttlxj_task(); if (!ltzfDisabled) { await this.ltzf_task(); } await this.marketTask(); // 添加新的联通阅读任务调用 await this.woread_task(); await this.securityButlerTask(); await this.ltyp_task(); } async userTestTask() { appName.log("\n------------------ 账号[" + this.index + "] ------------------"); } } !(async () => { // Read environment variables and create user instances. appName.read_env(CustomUserService); // Log the current configuration status. appName.log("\n------------------------------------"); appName.log("首页签到设置为: " + (signDisabled ? "不" : "") + "运行"); appName.log("联通祝福设置为: " + (ltzfDisabled ? "不" : "") + "运行"); appName.log("------------------------------------\n"); // Perform login tasks for all users. for (let user of appName.userList) { await user.userLoginTask(); } // Execute main tasks for all valid users. for (let validUser of appName.userList.filter(user => user.valid)) { await validUser.userTask(); } // 原有的 woread_reading_task 并发挂机逻辑已移除, // 因为新版逻辑是简单的单次阅读心跳,已集成在 userTask -> woread_task 中顺序执行。 })().catch(error => appName.log(error)).finally(() => appName.exitNow()); function createLogger(UserClass) { return new class { constructor(name) { this.name = name; this.startTime = Date.now(); this.log("[" + this.name + "]开始运行\n", { time: true }); this.notifyStr = []; this.notifyFlag = true; this.userIdx = 0; this.userList = []; this.userCount = 0; this.default_timestamp_len = 13; this.default_wait_interval = 1000; this.default_wait_limit = 3600000; this.default_wait_ahead = 0; } log(message, options = {}) { const defaultOptions = { console: true, ...options }; if (defaultOptions.time) { let format = defaultOptions.fmt || "hh:mm:ss"; message = "[" + this.time(format) + "]" + message; } if (defaultOptions.notify) { this.notifyStr.push(message); } if (defaultOptions.console) { console.log(message); } } get(object, key, defaultValue = "") { return object?.hasOwnProperty(key) ? object[key] : defaultValue; } pop(object, key, defaultValue = "") { if (object?.hasOwnProperty(key)) { const value = object[key]; delete object[key]; return value; } return defaultValue; } copy(source) { return { ...source }; } read_env(UserClass) { const envValues = cookieVars.map(varName => process.env[varName]); for (const envValue of envValues.filter(value => !!value)) { const delimitersFound = delimiters.filter(delimiter => envValue.includes(delimiter)); const delimiter = delimitersFound.length > 0 ? delimitersFound[0] : delimiters[0]; for (const userInfo of envValue.split(delimiter).filter(value => !!value)) { this.userList.push(new UserClass(userInfo)); } } this.userCount = this.userList.length; if (!this.userCount) { this.log("未找到变量,请检查变量" + cookieVars.map(varName => "[" + varName + "]").join("或"), { notify: true }); return false; } this.log("共找到" + this.userCount + "个账号"); return true; } async threads(methodName, context, options = {}) { while (context.idx < appName.userList.length) { const user = appName.userList[context.idx++]; if (user.valid) { await user[methodName](options); } } } async threadTask(methodName, count) { const tasks = []; const context = { idx: 0 }; while (count--) { tasks.push(this.threads(methodName, context)); } await Promise.all(tasks); } time(format, date = null) { const currentDate = date ? new Date(date) : new Date(); const timeElements = { "M+": currentDate.getMonth() + 1, "d+": currentDate.getDate(), "h+": currentDate.getHours(), "m+": currentDate.getMinutes(), "s+": currentDate.getSeconds(), "q+": Math.floor((currentDate.getMonth() + 3) / 3), S: this.padStr(currentDate.getMilliseconds(), 3) }; if (/(y+)/.test(format)) { format = format.replace(RegExp.$1, (currentDate.getFullYear() + "").substr(4 - RegExp.$1.length)); } for (const key in timeElements) { if (new RegExp("(" + key + ")").test(format)) { format = format.replace(RegExp.$1, RegExp.$1.length === 1 ? timeElements[key] : ("00" + timeElements[key]).substr(("" + timeElements[key]).length)); } } return format; } async showmsg() { let notifyBody = ""; // 遍历所有用户,聚合他们的通知日志 for (const user of this.userList) { if (user.notifyLogs.length > 0) { const userHeader = `------------------ 账号[${user.index}][${maskStr(user.name)}] ------------------`; // 移除每条日志中的手机号前缀,因为标题中已经包含了 const userLogs = user.notifyLogs.map(log => log.replace(`[${user.name}]`, '')).join("\n"); notifyBody += `${userHeader}\n${userLogs}\n`; } } if (this.notifyFlag && notifyBody) { const notify = require("./sendNotify"); this.log("\n============== 推送 =============="); await notify.sendNotify(this.name, notifyBody); } } padStr(value, length, options = {}) { const padding = options.padding || "0"; const mode = options.mode || "l"; let strValue = String(value); const paddingLength = length > strValue.length ? length - strValue.length : 0; const paddingStr = padding.repeat(paddingLength); return mode === "r" ? strValue + paddingStr : paddingStr + strValue; } json2str(json, delimiter, encode = false) { return Object.keys(json) .sort() .map(key => { let value = json[key]; return `${key}=${encode && value ? encodeURIComponent(value) : value}`; }) .join(delimiter); } str2json(str, decode = false) { const json = {}; str.split("&").forEach(pair => { if (pair) { const [key, value] = pair.split("="); json[key] = decode ? decodeURIComponent(value) : value; } }); return json; } randomPattern(pattern, charset = "abcdef0123456789") { return pattern.split("").map(char => { if (char === "x") { return charset.charAt(Math.floor(Math.random() * charset.length)); } else if (char === "X") { return charset.charAt(Math.floor(Math.random() * charset.length)).toUpperCase(); } return char; }).join(""); } randomUuid() { return appName.randomPattern("xxxxxxxx-xxxx-4xxx-4xxx-xxxxxxxxxxxx"); } randomString(length, charset = "abcdef0123456789") { return Array.from({ length }, () => charset.charAt(Math.floor(Math.random() * charset.length))).join(""); } randomList(list) { return list[Math.floor(Math.random() * list.length)]; } wait(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async exitNow() { await this.showmsg(); const endTime = Date.now(); const duration = (endTime - this.startTime) / 1000; this.log(""); this.log("[" + this.name + "]运行结束,共运行了" + duration + "秒", { time: true }); process.exit(0); } normalize_time(time, options = {}) { const length = options.len || this.default_timestamp_len; time = time.toString(); while (time.length < length) { time += "0"; } return parseInt(time.slice(0, 13)); } async wait_gap_interval(lastWaitTime, interval) { const elapsedTime = Date.now() - lastWaitTime; if (elapsedTime < interval) { await this.wait(interval - elapsedTime); } } }(UserClass); }