Auto Regenerate on Server Busy (DeepSeek)

Automatically regenerates messages on DeepSeek when the server is busy.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Auto Regenerate on Server Busy (DeepSeek)
// @name:ar       مُجَدِّد ديب سيك (DeepSeek Regenerator)
// @namespace    Violentmonkey Scripts
// @version      1.5
// @description  Automatically regenerates messages on DeepSeek when the server is busy.
// @description:ar   سكربت مدعوم بالذكاء الاصطناعي لتحسين تجربة المستخدم على ديب سيك من خلال التجديد التلقائي، واكتشاف الأخطاء، والمحاولات الذكية.
// @author       Ezio Auditore
// @license      MIT
// @icon         https://i.imgur.com/3RqMFdM.png
// @match        https://chat.deepseek.com/*
// @grant        none
// ==/UserScript==

(function () {
  "use strict";

  // -----------------------
  // Configuration Settings
  // -----------------------
  // This XPath query checks for a <p> element that contains either the English or Chinese busy message.
  const BUSY_MESSAGE_XPATH = `//p[contains(text(), "The server is busy. Please try again later.") or contains(text(), "服务器繁忙")]`;
  const REGENERATE_SVG_ID = "重新生成"; // The id of the <rect> element within the regenerate button
  const DEBOUNCE_DELAY = 500; // Debounce delay in milliseconds
  const CLICK_COOLDOWN = 3000; // Minimum interval between clicks (in ms)
  const POLLING_INTERVAL = 3000; // Fallback polling interval (in ms)
  const DEBUG = true; // Set to false to disable debug logging

  // -----------------------
  // Internal State Variables
  // -----------------------
  let lastClickTime = 0;
  let debounceTimer = null;

  // -----------------------
  // Utility: Debug Logging
  // -----------------------
  function log(...args) {
    if (DEBUG) {
      console.log("[AutoRegenerate]", ...args);
    }
  }

  // -----------------------
  // Core: Check for Busy Message & Click Regenerate
  // -----------------------
  function checkForServerBusy() {
    log("Checking for busy message...");

    // Use XPath to locate a <p> element that contains either the English or Chinese busy message.
    const busyMessage = document.evaluate(
      BUSY_MESSAGE_XPATH,
      document,
      null,
      XPathResult.FIRST_ORDERED_NODE_TYPE,
      null
    ).singleNodeValue;

    if (busyMessage) {
      log("Busy message detected:", busyMessage.textContent);

      // Enforce click cooldown to prevent rapid, repeated clicks.
      const now = Date.now();
      if (now - lastClickTime < CLICK_COOLDOWN) {
        log("Click cooldown active; skipping click.");
        return;
      }

      // Locate the regenerate button by finding the <rect> element with the specified id.
      const regenerateSvg = document.querySelector(
        `rect[id="${REGENERATE_SVG_ID}"]`
      );
      if (regenerateSvg) {
        const buttonElement = regenerateSvg.closest("div.ds-icon-button");
        if (buttonElement) {
          log("Regenerate button found. Clicking...");
          buttonElement.click();
          lastClickTime = now;
          log("Clicked regenerate button.");
        } else {
          console.error(
            "Regenerate button container (div.ds-icon-button) not found."
          );
        }
      } else {
        console.error(
          "Regenerate SVG element not found with id:",
          REGENERATE_SVG_ID
        );
      }
    } else {
      log("No busy message detected.");
    }
  }

  // -----------------------
  // Debounce Wrapper
  // -----------------------
  function debouncedCheck() {
    if (debounceTimer) clearTimeout(debounceTimer);
    debounceTimer = setTimeout(checkForServerBusy, DEBOUNCE_DELAY);
  }

  // -----------------------
  // MutationObserver Setup
  // -----------------------
  const observer = new MutationObserver((mutations) => {
    debouncedCheck();
  });

  function startObserver() {
    if (document.body) {
      observer.observe(document.body, { childList: true, subtree: true });
      log("MutationObserver started on document.body.");
    } else {
      document.addEventListener("DOMContentLoaded", () => {
        observer.observe(document.body, { childList: true, subtree: true });
        log("MutationObserver started after DOMContentLoaded.");
      });
    }
  }

  // -----------------------
  // Fallback Polling
  // -----------------------
  function startPolling() {
    setInterval(checkForServerBusy, POLLING_INTERVAL);
    log("Fallback polling started (every", POLLING_INTERVAL, "ms).");
  }

  // -----------------------
  // Initialization
  // -----------------------
  function init() {
    startObserver();
    startPolling();
    // Also perform an initial check once the window loads.
    window.addEventListener("load", checkForServerBusy);
  }

  init();
})();