From b5623b40f94b125f4d00453a10f761a97e3eaa16 Mon Sep 17 00:00:00 2001 From: cc892786825 <72603353+cc892786825@users.noreply.github.com> Date: Sat, 20 Dec 2025 10:26:47 +0800 Subject: [PATCH] Add files via upload --- zgltzhb.js | 4953 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 4953 insertions(+) create mode 100644 zgltzhb.js diff --git a/zgltzhb.js b/zgltzhb.js new file mode 100644 index 0000000..cee8256 --- /dev/null +++ b/zgltzhb.js @@ -0,0 +1,4953 @@ +/* +中国联通 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); + } \ No newline at end of file