// # Source: https://github.com/smallfawn/QLScriptPublic/blob/main/wxapp/wx_xlxyh.js
// # Raw: https://raw.githubusercontent.com/smallfawn/QLScriptPublic/main/wxapp/wx_xlxyh.js
// # Repo: smallfawn/QLScriptPublic
// # Path: wxapp/wx_xlxyh.js
// # UploadedAt: 2026-04-07T07:52:51Z
// # SHA256: 5479729628c6fef0cd258e6be563d3d0c8a66d541ba8f0decbd55a6bb61ce1ef
// # Category: 微信小程序/抓包版
// # Evidence: appid/openid/session_key/encryptedData等小程序字段
// 

const ckName = "wx_xlxyh";

// 工具类
class Env {
    constructor(name) {
        this.name = name;
        this.logs = [];
    }

    log(...args) {
        const msg = args.join(" ");
        this.logs.push(msg);
        console.log(msg);
    }

    isNode() {
        return typeof process !== "undefined" && process.release && process.release.name === 'node';
    }

    getdata(key) {
        if (this.isNode()) {
            return process.env[key] || "";
        }
        return localStorage.getItem(key) || "";
    }

    wait(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    async httpRequest(config) {
        if (this.isNode()) {
            const axios = require('axios');
            return axios(config);
        } else {
            return new Promise((resolve, reject) => {
                const xhr = new XMLHttpRequest();
                xhr.open(config.method || 'GET', config.url);
                
                if (config.headers) {
                    for (const [key, value] of Object.entries(config.headers)) {
                        xhr.setRequestHeader(key, value);
                    }
                }
                
                xhr.onload = () => {
                    if (xhr.status >= 200 && xhr.status < 300) {
                        try {
                            const data = JSON.parse(xhr.responseText);
                            resolve({ data });
                        } catch (e) {
                            resolve({ data: xhr.responseText });
                        }
                    } else {
                        reject(new Error(`HTTP ${xhr.status}: ${xhr.statusText}`));
                    }
                };
                
                xhr.onerror = () => reject(new Error('Network error'));
                xhr.send(config.data);
            });
        }
    }

    done() {
        if (this.isNode()) {
            process.exit(0);
        }
    }
}

// 初始化环境
const $ = new Env("骁龙骁友会");

class XLXYH {
    constructor(ck) {
        const parts = ck.split("#");
        this.ck = (parts[0] || "").trim();
        this.userId = (parts[1] || "").trim();
        this.openId = "";
        this.valid = !!(this.ck && this.userId);
    }

    generateSign(timestamp, requestId, body = "") {
        const crypto = require("crypto");
        return crypto.createHash("md5")
            .update(`${timestamp}${requestId}${body}boysup`)
            .digest("hex");
    }

    uuid() {
        return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, c => {
            const r = Math.random() * 16 | 0;
            return (c === "x" ? r : (r & 0x3 | 0x8)).toString(16);
        });
    }

    async request(method, path, data = null, extraHeaders = {}, skipSign = false) {
        if (!this.valid) {
            return { code: 400, message: "CK无效" };
        }

        const timestamp = Date.now().toString();
        const requestId = this.uuid().replace(/-/g, "");
        const sign = skipSign ? "" : this.generateSign(timestamp, requestId, data || "");

        const headers = {
            "Host": "qualcomm.boysup.cn",
            "Connection": "keep-alive",
            "Content-Type": "application/x-www-form-urlencoded",
            "timestamp": timestamp,
            "sign": sign,
            "xweb_xhr": "1",
            "openId": this.openId,
            "requestId": requestId,
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090a13) UnifiedPCWindowsWechat(0xf254162e) XWEB/18151",
            "userId": this.userId,
            "sessionKey": this.ck,
            "Referer": "https://servicewechat.com/wx026c06df6adc5d06/644/page-frame.html",
            "Accept": "*/*",
            "Sec-Fetch-Site": "cross-site",
            "Sec-Fetch-Mode": "cors",
            "Sec-Fetch-Dest": "empty",
            ...extraHeaders
        };

        if (skipSign) {
            delete headers.sign;
        }

        try {
            const config = {
                url: `https://qualcomm.boysup.cn${path}`,
                method,
                headers
            };

            if (data && method !== "GET") {
                config.data = data;
            }

            const resp = await $.httpRequest(config);
            
            if (typeof resp.data === "object") {
                return resp.data;
            } else {
                return JSON.parse(resp.data);
            }
        } catch (e) {
            const msg = e.response?.data?.message || e.message || "网络错误";
            $.log(`❌ 请求失败: ${msg} (路径: ${path})`);
            if (e.response) {
                $.log(`📄 响应数据: ${JSON.stringify(e.response.data)}`);
            }
            return { 
                code: e.response?.status || 500, 
                message: msg,
                response: e.response
            };
        }
    }

    async getOpenId() {
        $.log("🔍 尝试获取openId...");
        const openIdRes = await this.request(
            "GET", 
            `/qualcomm-app/api/user/info?userId=${this.userId}`,
            null,
            {},
            true
        );
        
        if (openIdRes.code === 200 && openIdRes.data) {
            this.openId = openIdRes.data.openId || "";
            $.log(`✅ 获取到openId: ${this.openId || "空"}`);
            return true;
        } else {
            $.log(`❌ 获取openId失败: ${openIdRes.message}`);
            return false;
        }
    }

    async run() {
        if (!this.valid) {
            $.log(`❌ CK格式错误，请使用: sessionKey#userId`);
            return;
        }

        if (!(await this.getOpenId())) {
            $.log("❌ 获取openId失败，可能sessionKey已过期");
            return;
        }

        $.log("🔍 获取用户信息...");
        const userInfo = await this.request("GET", `/qualcomm-app/api/user/info?userId=${this.userId}`);
        if (userInfo.code !== 200) {
            $.log(`❌ 账号[${this.userId}] 获取用户信息失败: ${userInfo.message}`);
            if (userInfo.message.includes("登录过期") || userInfo.code === 401) {
                $.log("⚠️ 登录已过期，请重新获取sessionKey和userId");
                return;
            }
            return;
        }

        $.log(`✅ 【${userInfo.data.nick}】等级${userInfo.data.level} | 积分: ${userInfo.data.coreCoin}`);

        $.log("🔍 检查签到状态...");
        const signList = await this.request("GET", `/qualcomm-app/api/user/signList?userId=${this.userId}`);
        if (signList.code === 200) {
            if (signList.data?.isSignToday !== 1) {
                $.log("🔍 开始签到...");
                const signResult = await this.request("POST", `/qualcomm-app/api/user/signIn?userId=${this.userId}`);
                if (signResult.code === 200) {
                    $.log(`✅ 签到成功 +${signResult.data.coreCoin}积分`);
                } else {
                    $.log(`❌ 签到失败: ${signResult.message}`);
                }
            } else {
                $.log("✅ 今日已签到");
            }
        } else {
            $.log(`❌ 获取签到状态失败: ${signList.message}`);
        }

        await this.handleDrawTask();

        await this.handleReadTask();

        await this.handleVlogTask();
    }

    async handleDrawTask() {
        $.log("🔍 开始抽奖任务...");
        
        // 修改为使用正确的抽奖接口
        const drawResult = await this.request(
            "POST", 
            "/qualcomm-app/api/luckDraw/getLuck", 
            `userId=${this.userId}&activityId=7`
        );
        
        if (drawResult.code === 200) {
            if (drawResult.data && drawResult.data.name) {
                $.log(`✅ 抽奖成功: ${drawResult.data.name}`);
            } else {
                $.log(`✅ 抽奖成功: 获得奖励`);
            }
            
            // 如果有积分信息，也显示出来
            if (drawResult.data.coreCoin) {
                $.log(`💰 获得积分: ${drawResult.data.coreCoin}`);
            }
        } else if (drawResult.code === 201) {
            $.log(`ℹ️ ${drawResult.message || '抽奖提示'}`);
        } else {
            $.log(`❌ 抽奖失败: ${drawResult.message || '接口请求错误'}`);
        }
    }

    async handleReadTask() {
        $.log("🔍 获取文章列表...");
        const articleRes = await this.request(
            "GET", 
            `/qualcomm-app/api/home/articles?page=1&size=10&userId=${this.userId}&type=0&searchDate=&articleShowPlace=骁友资讯列表页`
        );

        if (articleRes.code === 200 && articleRes.data?.articleList?.length) {
            const article = articleRes.data.articleList[0];
            $.log(`📖 开始阅读: ${article.title.substring(0, 20)}...`);

            const enterRes = await this.request("POST", 
                "/qualcomm-app/api/article/enterReadDaily", 
                `articleId=${article.id}&userId=${this.userId}`
            );
            
            if (enterRes.code !== 200) {
                $.log(`⚠️ 进入阅读失败: ${enterRes.message}`);
            }

            const likeRes = await this.request("GET", 
                `/qualcomm-app/api/article/like?articleId=${article.id}&userId=${this.userId}`
            );
            
            if (likeRes.code === 200) {
                $.log("👍 点赞成功");
            } else {
                $.log(`⚠️ 点赞失败: ${likeRes.message}`);
            }

            const shareRes = await this.request("POST", 
                "/qualcomm-app/api/article/shareDaily", 
                `articleId=${article.id}&userId=${this.userId}`
            );
            
            if (shareRes.code === 200) {
                $.log("🔗 分享成功");
            } else {
                $.log(`⚠️ 分享失败: ${shareRes.message}`);
            }

            $.log("⏳ 模拟阅读65秒...");
            await $.wait(65000);

            const exitRes = await this.request("POST", 
                "/qualcomm-app/api/article/exitReadDaily", 
                `articleId=${article.id}&userId=${this.userId}`
            );
            
            if (exitRes.code === 200) {
                $.log("✅ 阅读任务完成");
            } else {
                $.log(`⚠️ 退出阅读失败: ${exitRes.message}`);
            }
        } else {
            $.log("ℹ️ 未获取到文章，跳过阅读任务");
        }
    }

    async handleVlogTask() {
        $.log("🔍 获取VLOG列表...");
        
        const vlogRes = await this.request(
            "GET",
            `/qualcomm-app/api/article/vlogList?page=1&size=20&userId=${this.userId}&sortBy=1`
        );

        if (vlogRes.code === 200 && vlogRes.data?.records?.length) {
            const vlogs = vlogRes.data.records;
            $.log(`✅ 获取到 ${vlogs.length} 个VLOG`);
            
            // 只获取第一个VLOG，不管是否已观看
            const targetVlog = vlogs[0];
            $.log(`🎬 开始观看第一个VLOG: ${targetVlog.title.substring(0, 20)}...`);
            $.log(`📊 时长: ${targetVlog.videoDuration} | 播放: ${targetVlog.playCountFormat} | 点赞: ${targetVlog.likeCount}`);

            const enterRes = await this.request(
                "POST",
                "/qualcomm-app/api/article/enterReadDaily",
                `articleId=${targetVlog.id}&userId=${this.userId}`
            );

            if (enterRes.code === 200) {
                $.log("✅ 进入VLOG观看成功");
                
                // 固定观看70秒，不管视频时长
                const waitTime = 70000;
                
                $.log(`⏳ 模拟观看VLOG 70秒...`);
                await $.wait(waitTime);

                const exitRes = await this.request(
                    "POST",
                    "/qualcomm-app/api/article/exitReadDaily",
                    `articleId=${targetVlog.id}&userId=${this.userId}`
                );

                if (exitRes.code === 200) {
                    $.log("✅ VLOG观看任务完成");
                    
                    await this.request(
                        "GET",
                        `/qualcomm-app/api/article/like?articleId=${targetVlog.id}&userId=${this.userId}`
                    );
                    
                    await this.request(
                        "POST",
                        "/qualcomm-app/api/article/shareDaily",
                        `articleId=${targetVlog.id}&userId=${this.userId}`
                    );
                    
                    $.log("✅ VLOG点赞和分享完成");
                } else {
                    $.log(`⚠️ 退出VLOG观看失败: ${exitRes.message}`);
                }
            } else {
                $.log(`❌ 进入VLOG观看失败: ${enterRes.message}`);
            }
        } else {
            $.log(`❌ 获取VLOG列表失败: ${vlogRes.message || '未知错误'}`);
        }
    }

    async batchHandleVlogs(count = 1) {
        // 修改默认只处理1个VLOG
        $.log(`🔍 开始批量处理${count}个VLOG任务...`);
        
        const vlogRes = await this.request(
            "GET",
            `/qualcomm-app/api/article/vlogList?page=1&size=20&userId=${this.userId}&sortBy=1`
        );

        if (vlogRes.code === 200 && vlogRes.data?.records?.length) {
            const vlogs = vlogRes.data.records;
            
            // 只处理前count个VLOG，不筛选是否已观看
            const tasks = Math.min(count, vlogs.length);
            let completed = 0;

            for (let i = 0; i < tasks; i++) {
                const vlog = vlogs[i];
                $.log(`\n🎬 处理第 ${i + 1}/${tasks} 个VLOG: ${vlog.title.substring(0, 20)}...`);

                try {
                    const enterRes = await this.request(
                        "POST",
                        "/qualcomm-app/api/article/enterReadDaily",
                        `articleId=${vlog.id}&userId=${this.userId}`
                    );

                    if (enterRes.code === 200) {
                        // 固定观看70秒
                        const waitTime = 70000;

                        $.log(`⏳ 观看中... (70秒)`);
                        await $.wait(waitTime);

                        const exitRes = await this.request(
                            "POST",
                            "/qualcomm-app/api/article/exitReadDaily",
                            `articleId=${vlog.id}&userId=${this.userId}`
                        );

                        if (exitRes.code === 200) {
                            completed++;
                            $.log(`✅ 第 ${i + 1} 个VLOG观看完成`);
                            
                            await this.request(
                                "GET",
                                `/qualcomm-app/api/article/like?articleId=${vlog.id}&userId=${this.userId}`
                            );
                            await this.request(
                                "POST",
                                "/qualcomm-app/api/article/shareDaily",
                                `articleId=${vlog.id}&userId=${this.userId}`
                            );
                        }
                    }
                } catch (error) {
                    $.log(`❌ 处理VLOG失败: ${error.message}`);
                }

                if (i < tasks - 1) {
                    await $.wait(2000);
                }
            }

            $.log(`\n🎉 批量VLOG任务完成: ${completed}/${tasks} 个VLOG观看成功`);
            return completed;
        } else {
            $.log("❌ 无法获取VLOG列表");
            return 0;
        }
    }
}

async function main() {
    let cookies = [];
    
    if ($.isNode()) {
        const raw = process.env[ckName] || "";
        cookies = raw.split(/[#&\n]/).filter(Boolean);
        
        if (!cookies.length) {
            const fs = require('fs');
            try {
                if (fs.existsSync(`${ckName}.txt`)) {
                    const content = fs.readFileSync(`${ckName}.txt`, 'utf8');
                    cookies = content.split(/[#&\n]/).filter(Boolean);
                }
            } catch (e) {
            }
        }
    } else {
        const raw = $.getdata(ckName) || "";
        cookies = raw.split(/[#&\n]/).filter(Boolean);
    }

    if (!cookies.length) {
        $.log(`🔔 未找到变量【${ckName}】，请添加`);
        $.log(`💡 CK格式: sessionKey#userId`);
        $.log(`📝 配置方法:`);
        $.log(`   1. Node.js: 设置环境变量 ${ckName}="sessionKey#userId"`);
        $.log(`   2. 浏览器: 设置 localStorage.${ckName}="sessionKey#userId"`);
        $.log(`   3. 本地文件: 创建 ${ckName}.txt 文件，每行一个 sessionKey#userId`);
        return;
    }

    const accounts = [];
    for (let i = 0; i < cookies.length; i += 2) {
        if (cookies[i] && cookies[i + 1]) {
            accounts.push(`${cookies[i]}#${cookies[i + 1]}`);
        } else if (cookies[i] && cookies[i].includes('#')) {
            accounts.push(cookies[i]);
        }
    }

    if (!accounts.length) {
        $.log("❌ CK格式错误，请检查是否为 'sessionKey#userId' 格式");
        return;
    }

    $.log(`🎯 共加载 ${accounts.length} 个账号`);

    for (let i = 0; i < accounts.length; i++) {
        const account = accounts[i];
        $.log(`\n📱 开始处理账号 ${i + 1}/${accounts.length}`);
        
        try {
            const xlxyh = new XLXYH(account);
            
            await xlxyh.run();
            
            const vlogCount = 1; // 只观看1个VLOG
            await xlxyh.batchHandleVlogs(vlogCount);
            
            if (i < accounts.length - 1) {
                await $.wait(3000);
            }
        } catch (error) {
            $.log(`❌ 账号 ${i + 1} 处理失败: ${error.message}`);
        }
    }

    if ($.isNode()) {
        try {
            if (process.env.NOTIFY_TOKEN || process.env.PUSH_PLUS_TOKEN || process.env.SERVER_CHAN_TOKEN) {
                await sendNotify($.name, $.logs.join("\n"));
            }
        } catch (error) {
        }
    }

    $.log("\n🎉 所有账号处理完成！");
}

main().catch(e => {
    $.log(`❌ 脚本异常: ${e.message || e}`);
    console.error(e.stack);
}).finally(() => {
    $.done();
});

async function sendNotify(title, content) {
    if (!content) return;
    
    const notifyTokens = [
        process.env.NOTIFY_TOKEN,
        process.env.PUSH_PLUS_TOKEN,
        process.env.SERVER_CHAN_TOKEN
    ].filter(token => token);

    for (const token of notifyTokens) {
        try {
            const notify = require('sendNotify');
            await notify.sendNotify(title, content);
            break;
        } catch (error) {
        }
    }
}
