DeepSeek 自动重试 & 点击次数上限

当页面中出现“服务器繁忙,请稍后再试”的提示时,自动点击 id 为“重新生成”的元素进行重试。页面右下角显示一个大盒子,包含自动重试开关及点击次数上限设置(含当前计数显示),点击次数达到上限时自动关闭重试。适用于 deepseek 页面。

目前為 2025-02-28 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         DeepSeek 自动重试 & 点击次数上限
// @namespace    http://tampermonkey.net/
// @version      1.8.2
// @description  当页面中出现“服务器繁忙,请稍后再试”的提示时,自动点击 id 为“重新生成”的元素进行重试。页面右下角显示一个大盒子,包含自动重试开关及点击次数上限设置(含当前计数显示),点击次数达到上限时自动关闭重试。适用于 deepseek 页面。
// @author       Loki2077
// @match        https://chat.deepseek.com/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // 自动重试是否启用,默认开启
    let autoRetryEnabled = true;
    // 记录当前自动点击重试的次数
    let retryClickCount = 0;
    // 定义间隔时间变量(单位:秒)
    let jgtime = 10;
    // 定义倒计时变量
    let countdown = jgtime;

    // 定义多个错误提示关键词
    const errorPhrases = [
        "服务器繁忙,请稍后再试",
        "服务器繁忙",
        "The server is busy. Please try again later."
    ];

    // 创建 UI 大盒子,包含开关按钮和点击次数上限设置
    function createUIBox() {
        const container = document.createElement('div');
        container.id = 'auto-retry-box';
        container.style.position = 'fixed';
        container.style.bottom = '10px';
        container.style.right = '10px';
        container.style.zIndex = 9999;
        container.style.background = 'rgba(120, 241, 104, 0.79)';
        container.style.color = '#fff';
        container.style.padding = '10px';
        container.style.borderRadius = '5px';
        container.style.fontSize = '14px';

        // 开关按钮
        const toggleBtn = document.createElement('button');
        toggleBtn.id = 'auto-retry-toggle';
        toggleBtn.style.width = '100%';
        toggleBtn.style.padding = '8px';
        toggleBtn.style.backgroundColor = '#007BFF';
        toggleBtn.style.color = '#FFFFFF';
        toggleBtn.style.border = 'none';
        toggleBtn.style.borderRadius = '5px';
        toggleBtn.style.cursor = 'pointer';
        toggleBtn.textContent = autoRetryEnabled ? '关闭自动重试' : '开启自动重试';

        toggleBtn.addEventListener('click', () => {
            autoRetryEnabled = !autoRetryEnabled;
            toggleBtn.textContent = autoRetryEnabled ? '关闭自动重试' : '开启自动重试';
            countdown = autoRetryEnabled ? jgtime : '关闭';
            console.log(`自动重试功能已${autoRetryEnabled ? '开启' : '关闭'}`);
            // 每次点击更新容器背景颜色
            container.style.backgroundColor = autoRetryEnabled ? 'rgba(120, 241, 104, 0.79)' : 'rgba(0, 0, 0, 0.3)';
        });

        container.appendChild(toggleBtn);

        // 点击次数上限和当前计数显示
        const limitBox = document.createElement('div');
        limitBox.style.marginTop = '10px';

        const limitLabel = document.createElement('label');
        limitLabel.htmlFor = 'max-click-input';
        limitLabel.textContent = '点击次数上限: ';

        const maxClickInput = document.createElement('input');
        maxClickInput.id = 'max-click-input';
        maxClickInput.type = 'number';
        maxClickInput.value = '5';
        maxClickInput.min = '0';
        maxClickInput.style.width = '50px';
        maxClickInput.style.marginRight = '10px';

        // 当前点击次数显示
        const countDisplay = document.createElement('span');
        countDisplay.id = 'click-count';
        countDisplay.textContent = retryClickCount;

        // 组合 limitBox
        limitBox.appendChild(limitLabel);
        limitBox.appendChild(maxClickInput);
        limitBox.appendChild(document.createTextNode(' 当前点击次数: '));
        limitBox.appendChild(countDisplay);

        container.appendChild(limitBox);

        // 间隔时间设置
        const intervalBox = document.createElement('div');
        intervalBox.style.marginTop = '10px';

        const intervalLabel = document.createElement('label');
        intervalLabel.htmlFor = 'interval-input';
        intervalLabel.textContent = '间隔时间 (秒): ';

        const intervalInput = document.createElement('input');
        intervalInput.id = 'interval-input';
        intervalInput.type = 'number';
        intervalInput.value = jgtime;
        intervalInput.min = '1';
        intervalInput.style.width = '80px';
        intervalInput.style.marginRight = '10px';

        intervalInput.addEventListener('change', () => {
            jgtime = Number(intervalInput.value) || jgtime;
            countdown = jgtime;
            clearInterval(checkInterval);
            checkInterval = setInterval(checkAndRetry, jgtime * 1000);
            console.log(`间隔时间已修改为 ${jgtime} 秒`);
        });

        const countdownDisplay = document.createElement('span');
        countdownDisplay.id = 'countdown-display';
        countdownDisplay.textContent = `倒计时: ${countdown} 秒`;

        intervalBox.appendChild(intervalLabel);
        intervalBox.appendChild(intervalInput);
        intervalBox.appendChild(countdownDisplay);

        container.appendChild(intervalBox);

        document.body.appendChild(container);
    }

    // 新增弹窗提示函数
    function showPopup(message) {
        // 若容器不存在,则创建一个固定在屏幕右上角的容器,子项将从下往上排列
        let container = document.getElementById('popup-container');
        if (!container) {
            container = document.createElement('div');
            container.id = 'popup-container';
            container.style.position = 'fixed';
            container.style.top = '20px';
            container.style.right = '20px';
            container.style.display = 'flex';
            container.style.flexDirection = 'column';
            container.style.alignItems = 'flex-end';
            container.style.gap = '5px';
            container.style.zIndex = 10000;
            document.body.appendChild(container);
        }
        
        // 创建提示弹窗
        const popup = document.createElement('div');
        popup.textContent = message;
        popup.style.backgroundColor = '#d0f0c040'; // 淡绿色背景
        popup.style.color = '#000';
        popup.style.padding = '10px 20px';
        popup.style.borderRadius = '5px';
        popup.style.fontSize = '14px';
        popup.style.opacity = 0;
        popup.style.transform = 'translateY(20px)';
        popup.style.transition = 'transform 0.5s ease, opacity 0.5s ease';
        
        container.appendChild(popup);
        
        // 增加延迟,让每个弹窗之间有间隔,延迟时间根据当前容器中的弹窗数量计算(每个延迟200ms)
        const delay = container.children.length * 500;
        
        // 触发动画:自下而上渐显(延迟启动)
        setTimeout(() => {
           popup.style.opacity = 1;
           popup.style.transform = 'translateY(0)';
        }, delay);
        
        // 2秒后开始淡出并向上移动,然后移除该提示(考虑延迟后再计时)
        setTimeout(() => {
           popup.style.opacity = 0;
           popup.style.transform = 'translateY(-20px)';
           // 动画结束后移除元素
           setTimeout(() => {
               popup.remove();
           }, 1000);
        }, 5000 + delay*3);
    }

    // 给msg参数,调用showPopup函数,和console.log函数
    function showMsg(msg){
        console.log(msg);
        showPopup(msg);
    }

    // 检查页面是否出现错误提示,并执行自动重试操作(带点击次数上限判断)
    function checkAndRetry() {
        if (!autoRetryEnabled) return;

        const maxClickInput = document.getElementById('max-click-input');
        const maxClickCount = Number(maxClickInput.value) || 0;
        if (retryClickCount >= maxClickCount && maxClickCount > 0) {
            showMsg("点击次数上限,自动重试关闭。");
            autoRetryEnabled = false;
            // 更新容器背景颜色
            container.style.backgroundColor = autoRetryEnabled ? 'rgba(120, 241, 104, 0.79)' : 'rgba(0, 0, 0, 0.3)';
            document.getElementById('auto-retry-toggle').textContent = '开启自动重试';
            return;
        }

        

        // 查找 class 包含 "d7dc56a8" 的 div
        const targetDivs = document.querySelectorAll('div[class*="d7dc56a8"]');
        for (let i = 0; i < targetDivs.length; i++) {
            // 检查 div 内容是否包含错误提示关键词
            const textContent = targetDivs[i].textContent;
            // 如果找到错误提示,就模拟点击“重新生成”按钮
            if (errorPhrases.some(phrase => textContent.includes(phrase))) {
                // 找到错误提示,弹窗提示
                showMsg("检测到错误提示");
                // 提取textContext中的错误提示;
                showMsg(errorPhrases.find(phrase => textContent.includes(phrase)));
                // 当前错误提示是什么
                showMsg("开始寻找重新生成按钮");
                const retryElement = targetDivs[i].querySelector('#重新生成');
                if (retryElement) {
                    showMsg("找到重新生成按钮");
                    showMsg("模拟点击 重新生成 按钮");
                    if (typeof retryElement.click === "function") {
                        retryElement.click();
                        // 模拟点击成功后,重置倒计时
                        countdown = jgtime;
                        showMsg("模拟点击 成功");
                    } else {
                        const event = new MouseEvent("click", {
                            view: window,
                            bubbles: true,
                            cancelable: true
                        });
                        retryElement.dispatchEvent(event);
                    }
                    retryClickCount++;
                    document.getElementById('click-count').textContent = retryClickCount;
                } else {
                    showMsg("检测到错误提示,但未找到 '重新生成' 按钮。")
                }
                break;
            }
        }


        // 更新容器背景颜色
        container.style.backgroundColor = autoRetryEnabled ? 'rgba(120, 241, 104, 0.79)' : 'rgba(0, 0, 0, 0.3)';
    }

    // 初始化 UI
    createUIBox();

    // 每隔 jgtime 秒检测页面内容
    let checkInterval = setInterval(checkAndRetry, jgtime * 1000);

    // 更新倒计时显示
    setInterval(() => {
        // 如果启用了自动重试功能,并且倒计时减到 0,就重置倒计时
        if (countdown === 0 && autoRetryEnabled) {
            countdown = jgtime;
        }
        // 如果倒计时大于 0 并且自动重试功能开启,则继续倒计时
        if (countdown > 0 && autoRetryEnabled) {
            countdown--;
        } else {
            countdown = "关闭";
        }
        // 更新倒计时显示
        if (countdown === "关闭") {
            document.getElementById('countdown-display').textContent = ` ${countdown} `;
        }else{
            document.getElementById('countdown-display').textContent = `倒计时: ${countdown} 秒`;
        }
    }, 1000);

    // 如有需要,可以使用 MutationObserver 监听 DOM 变化(可选)
    /*
    const observer = new MutationObserver(checkAndRetry);
    observer.observe(document.body, { childList: true, subtree: true });
    */
})();