忘川夜游抽卡回收脚本

2024年7月斗鱼活动忘川夜游脚本。安装后会在直播间标题右侧有一个自动抽卡按钮。每次十连抽并自动分解抽到的战魂。脚本后台运行,抽卡次数不够自动退出。

// ==UserScript==
// @name         忘川夜游抽卡回收脚本
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description   2024年7月斗鱼活动忘川夜游脚本。安装后会在直播间标题右侧有一个自动抽卡按钮。每次十连抽并自动分解抽到的战魂。脚本后台运行,抽卡次数不够自动退出。
// @author       You
// @match			*://*.douyu.com/0*
// @match			*://*.douyu.com/1*
// @match			*://*.douyu.com/2*
// @match			*://*.douyu.com/3*
// @match			*://*.douyu.com/4*
// @match			*://*.douyu.com/5*
// @match			*://*.douyu.com/6*
// @match			*://*.douyu.com/7*
// @match			*://*.douyu.com/8*
// @match			*://*.douyu.com/9*
// @match			*://*.douyu.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=douyu.com
// @grant        none
// @license        MIT License
// ==/UserScript==


(function() {
    'use strict';

    const currentUrl = window.location.href;

    // 创建 URL 对象
    const urlObj = new URL(currentUrl);

    // 使用 URLSearchParams 获取查询参数
    const params = new URLSearchParams(urlObj.search);

    // 获取 rid 参数的值
    const rid = params.get('rid');
    let allCharacters = [];
    const waitInterval = 1000; // 每次检查之间等待时间(毫秒)
    const actInteractiveButton = '.actAnnual202311Interactive-container';
    const actIframe = 'iframe[class="Live-Act-Annual-Panel-iframe"]';


    let intervalId;
    let timerId;
    let lotteryFailed = false;
    let ctn = '';
    // 函数:向字典中添加新对象


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

    async function randomSleep(minSeconds, maxSeconds) {
        const ms = Math.floor(Math.random() * (maxSeconds - minSeconds + 1) + minSeconds) * 1000;
        await sleep(ms);
    }


    function getCookie(name) {
        let matches = document.cookie.match(new RegExp(
            "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
        ));
        return matches ? decodeURIComponent(matches[1]) : undefined;
    }


    // Get cookies
    // 模拟请求


    function sendRecycleRequest(index) {

        ctn = getCookie('acf_ccn');
        const payload = `ctn=${ctn}&activity_id=2026&rid=${rid}&index=${index}&ext1=2`;
        fetch('https://www.douyu.com/japi/revenuenc/web/actqzs/immortalCultivation/recycle', {
            method: 'POST',
            headers: {
                'Accept': 'application/json, text/plain, */*',
                'Accept-Encoding': 'gzip, deflate, br, zstd',
                'Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,ja;q=0.6',
                'Content-Type': 'application/x-www-form-urlencoded',
                'Cookie': document.cookie,
                'User-Agent': navigator.userAgent
            },
            body: payload,
            credentials: 'include'
        })
            .then(response => {
            if (response.ok) {

            }
            return response.json();
        })
            .then(data => {
            console.log('Recycle request successful:', data);
        })
            .catch(error => console.error('Recycle request failed:', error));
    }

    async function wearAndRecycleCharacters(toWearCharacter, toRecycleCharacters){

        console.log("toWearCharacter", toWearCharacter);
        console.log("toRecycleCharacters", toRecycleCharacters);
        const payload = `ctn=${ctn}&activity_id=2026&rid=${rid}&index=${toWearCharacter.index}`;
        const response = await fetch('https://www.douyu.com/japi/revenuenc/web/actqzs/immortalCultivation/wear', {
            method: 'POST',
            headers: {
                'Accept': 'application/json, text/plain, */*',
                'Accept-Encoding': 'gzip, deflate, br, zstd',
                'Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,ja;q=0.6',
                'Content-Type': 'application/x-www-form-urlencoded',
                'Cookie': document.cookie,
                'User-Agent': navigator.userAgent
            },
            body: payload,
            credentials: 'include'
        });

        if (response.ok) {
            for (const char of toRecycleCharacters) {
                await randomSleep(0.5, 2); // 每个角色之间等待0.5-2秒
                // 执行回收请求
                await sendRecycleRequest(char.index);
            }
        }
        return response.json();
    }


    function processCharacters(characters) {
        // 找到等级最小并且wear为0的角色
        let minLevelWear0Character = characters.filter(char => char.wear === 0)
        .reduce((minChar, currentChar) => {
            return currentChar.level < minChar.level ? currentChar : minChar;
        }, characters[0]);

        // 排除掉找到的等级最小且wear为0的角色
        let filteredCharacters = characters.filter(char => char !== minLevelWear0Character);

        // 执行筛选逻辑


        // 找到等级大于等于3且不为偶数或者大于等于10的角色
        let specificCharacters = filteredCharacters.filter(char => {
            //return (char.level >= 3 && char.level % 2 !== 0) || char.level >= 10;{
            return (char.level >= 1);
        });


        wearAndRecycleCharacters(minLevelWear0Character, specificCharacters);
        // 执行特定条件角色的逻辑

    }

    function queryCharacters() {
        fetch(`https://www.douyu.com/japi/revenuenc/web/actqzs/immortalCultivation/panelInfo?activity_id=2026&rid=${rid}`, {
            method: 'GET',
            headers: {
                'Accept': 'application/json, text/plain, */*',
                'Accept-Encoding': 'gzip, deflate, br, zstd',
                'Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,ja;q=0.6',
                'User-Agent': navigator.userAgent,
                'Cookie': document.cookie
            },
            credentials: 'include'
        })
            .then(response => {
            if (!response.ok) {
                throw new Error('Network response was not ok ' + response.statusText);
            }
            return response.json();
        })
            .then(data => {
            if (data.error === 0 && data.msg === 'ok') {
                allCharacters = data.data.characters;
                console.log('Characters data saved:', allCharacters);
                processCharacters(data.data.characters);
                getCtn();
            } else {
                console.error('Error in response:', data);
            }
        })
            .catch(error => console.error('Request failed:', error));
    }
    function getCtn(){
        ctn = getCookie('acf_ccn');
        console.log(ctn);
    }

    function sendLotteryRequest() {
        if (lotteryFailed) {
            clearInterval(timerId);
            console.log("Lottery failed, stopping timer.");
            return;
        }
        const payload = `ctn=${ctn}&activity_id=2026&rid=${rid}&batchNum=10`;
        console.log(payload)
        fetch('https://www.douyu.com/japi/revenuenc/web/actqzs/userLottery/lottery', {
            method: 'POST',
            headers: {
                'Accept': 'application/json, text/plain, */*',
                'Accept-Encoding': 'gzip, deflate, br, zstd',
                'Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,ja;q=0.6',
                'Content-Type': 'application/x-www-form-urlencoded',
                'Cookie': document.cookie,
                'User-Agent': navigator.userAgent
            },
            body: payload,
            credentials: 'include'
        })
            .then(response => {
            if (response.ok) {
                randomSleep(0.5, 2).then(() => {
                    queryCharacters();
                });
            } else {

                lotteryFailed = true;
                clearInterval(timerId);
            }
            return response.json();
        })
            .then(data => {
            console.log('Lottery request successful:', data);
        })
            .catch(error => {
            lotteryFailed = true;
            clearInterval(timerId);
            console.error('Lottery request failed:', error);
        });
    }


    function processSteps(){
        getCtn();
        timerId = setInterval(() => {
            if (!lotteryFailed) {
                sendLotteryRequest();
            }
        }, 10000);
    }



    function addButton(text, className, idx, onclick) {
        const elements = Array.from(document.querySelectorAll(className));
        const container = elements[idx];
        const buttonDiv = document.createElement('div');
        buttonDiv.className = 'DiamondFansMatchEntrance';
        const label = document.createElement('label');
        label.textContent = text;
        label.style.cursor = 'pointer';
        label.onclick = onclick;
        buttonDiv.appendChild(label);
        container.appendChild(buttonDiv);
    }


    function checkAndAddButtons() {
        // 检查页面中是否存在指定的div
        const giftNamingEntranceExists = document.querySelector('.DiamondFansMatchEntrance');
        const cardBodyExists = document.querySelector(actInteractiveButton);

        // 如果两个div都存在,则添加按钮
        if (giftNamingEntranceExists && cardBodyExists) {
            console.log("找到了指定的div,添加按钮。");
            //addButton('test','.Title-col.is-left', 0, sendRecycleRequest(2));
            addButton('自动抽卡','.Title-col.is-left', 0, processSteps);
            clearInterval(checkInterval); // 停止定时器
        }
    }


    const checkInterval = setInterval(checkAndAddButtons, waitInterval);

    // Your code here...
})();