DeepSeek繁忙自动点击重试

DeepSeek提示繁忙,自动点击重试,并显示操作状态通知

目前为 2025-02-14 提交的版本。查看 最新版本

// ==UserScript==
// @name         DeepSeek繁忙自动点击重试
// @namespace    http://tampermonkey.net/
// @version      2025-02-14 02
// @license      MIT
// @description  DeepSeek提示繁忙,自动点击重试,并显示操作状态通知
// @author       Dingning
// @include      *://chat.deepseek.com/*
// @icon         https://registry.npmmirror.com/@lobehub/icons-static-png/latest/files/dark/deepseek-color.png
// @grant        none
// ==/UserScript==

(function () {
  "use strict";

  // 固定的检查间隔时间(秒)
  let CHECK_INTERVAL = 1;
  // 重试延迟时间(秒)
  let retryDelay = 1;
  // 最大重试延迟时间(秒)
  let maxRetryDelay = 60;
  // 重试计数器
  let retryCount = 0;
  // 重试次数阈值,达到该阈值后增加重试延迟
  let threshold = 5;
  // 每次增加的重试延迟时间(秒),正常情况增加2秒
  let normalDelayIncrement = 2;
  // 当检测到频率过快提示时每次增加的重试延迟时间(秒),即30秒
  let fastFrequencyDelayIncrement = 30;
  // 重试定时器
  let retryTimeoutId = null;
  // 配置面板
  let configPanel;

  const checkAndRetry = () => {
      // 检查是否没有 .ds-loading 元素
      const loadingElements = document.querySelectorAll(".ds-loading");
      const hasLoading = loadingElements.length > 0;

      // 检查最后一个回答是否存在繁忙提示
      const contentList = document.querySelectorAll(".ds-markdown");
      let hasBusyMessage = false;
      const busyMessages = [
          "<p>服务器繁忙,请稍后再试。</p>",
          "<p>The server is busy. Please try again later.</p>",
      ];
      const lastContent =
          contentList.length > 0
            ? contentList[contentList.length - 1].innerHTML
              : "";
      if (busyMessages.includes(lastContent)) {
          hasBusyMessage = true;
      }

      // 如果没有 loading 且没有繁忙提示,重置重试计数并隐藏配置面板
      if (!hasLoading &&!hasBusyMessage) {
          if (retryCount > 0) {
              createNotification("已重置重试次数和重试延迟", "success");
          }
          retryCount = 0;
          retryDelay = 1;
          if (configPanel) {
              configPanel.style.display = 'none';
          }
      } else if (hasBusyMessage) {
          // 显示配置面板
          if (configPanel) {
              configPanel.style.display = 'block';
          }
      }

      if (hasBusyMessage &&!retryTimeoutId) {
          // 延迟时间后点击重试
          retryTimeoutId = setTimeout(() => {
              console.log("点击重试", retryCount, retryDelay);

              const retryBtn = Array.from(
                  document.querySelectorAll(".ds-icon-button")
              )
                .reverse()
                .find((btn) => {
                      const svg = btn.querySelector("svg");
                      return svg && svg.querySelector("#重新生成");
                  });

              if (retryBtn) {
                  retryBtn.click();
                  clearTimeout(retryTimeoutId);
                  retryTimeoutId = null;
                  retryCount++;
                  createNotification(`已点击重试,重试次数: ${retryCount}`, "success");

                  // 检查是否有频率过快的提示
                  const toastContents = document.querySelectorAll(".ds-toast__content");
                  for (let i = 0; i < toastContents.length; i++) {
                      if (
                          toastContents[i].textContent ===
                          "你发送消息的频率过快,请稍后再发"
                      ) {
                          retryDelay += fastFrequencyDelayIncrement;
                          if (retryDelay > maxRetryDelay) {
                              retryDelay = maxRetryDelay;
                          }
                          createNotification(
                              `检测到频率过快提示,重试延迟已调整为 ${retryDelay} 秒`,
                              "warning"
                          );
                          break;
                      }
                  }

                  // 当重试次数达到阈值时,增加重试延迟时间
                  if (retryCount >= threshold) {
                      retryDelay += normalDelayIncrement;
                      if (retryDelay > maxRetryDelay) {
                          retryDelay = maxRetryDelay;
                      }
                      createNotification(
                          `重试次数过多,重试延迟已调整为 ${retryDelay} 秒`,
                          "warning"
                      );
                  }
              }
          }, retryDelay * 1000);
      }
  };

  // 创建通知容器
  const createNotificationContainer = () => {
      const container = document.createElement("div");
      container.id = "retry-notifications";
      container.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            z-index: 10000;
            display: flex;
            flex-direction: column;
            gap: 10px;
            max-width: 300px;
        `;
      document.body.appendChild(container);
      return container;
  };

  // 创建单个通知
  const createNotification = (message, type = "info") => {
      const notification = document.createElement("div");
      notification.className = `retry-notification ${type}`;
      notification.style.cssText = `
            padding: 12px 16px;
            background: white;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
            font-size: 14px;
            color: #333;
            opacity: 0;
            transform: translateX(100%);
            transition: all 0.3s ease;
            display: flex;
            align-items: center;
            gap: 8px;
        `;

      // 添加图标
      const icon = document.createElement("span");
      icon.style.cssText = `
            font-size: 16px;
            font-weight: bold;
        `;

      switch (type) {
          case "success":
              icon.textContent = "✅";
              notification.style.borderLeft = "4px solid #52c41a";
              break;
          case "warning":
              icon.textContent = "⚠️";
              notification.style.borderLeft = "4px solid #faad14";
              break;
          default:
              icon.textContent = "ℹ️";
              notification.style.borderLeft = "4px solid #1890ff";
      }

      notification.appendChild(icon);

      const text = document.createElement("span");
      text.textContent = message;
      notification.appendChild(text);

      // 添加到容器
      const container =
          document.getElementById("retry-notifications") ||
          createNotificationContainer();
      container.appendChild(notification);

      // 触发动画
      setTimeout(() => {
          notification.style.opacity = "1";
          notification.style.transform = "translateX(0)";
      }, 50);

      // 自动移除
      setTimeout(() => {
          notification.style.opacity = "0";
          notification.style.transform = "translateX(100%)";
          setTimeout(() => notification.remove(), 300);
      }, 3000);
  };

  // 创建配置面板
  const createConfigPanel = () => {
      const panel = document.createElement("div");
      panel.id = "config-panel";
      panel.style.cssText = `
          position: fixed;
          bottom: 20px;
          right: 20px;
          z-index: 10000;
          background: #f8faff;
          color: #414158;
          border-radius: 8px;
          box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
          padding: 16px;
          display: flex;
          flex-direction: column;
          gap: 12px;
          max-width: 300px;
          display: none;
      `;

      const title = document.createElement("h3");
      title.textContent = "配置项";
      title.style.margin = 0;
      panel.appendChild(title);

      const createInputRow = (labelText, value, onInput) => {
          const row = document.createElement("div");
          row.style.display = "flex";
          row.style.alignItems = "center";
          row.style.justifyContent = "space-between";

          const label = document.createElement("label");
          label.textContent = labelText;
          row.appendChild(label);

          const input = document.createElement("input");
          input.type = "number";
          input.value = value;
          input.style.width = "80px";
          input.addEventListener("input", onInput);
          row.appendChild(input);

          return row;
      };

      panel.appendChild(createInputRow("检查间隔 (秒)", CHECK_INTERVAL, (e) => {
          CHECK_INTERVAL = parseInt(e.target.value);
          clearInterval(checkIntervalId);
          checkIntervalId = setInterval(checkAndRetry, CHECK_INTERVAL * 1000);
      }));
      panel.appendChild(createInputRow("初始重试延迟 (秒)", retryDelay, (e) => {
          retryDelay = parseInt(e.target.value);
      }));
      panel.appendChild(createInputRow("最大重试延迟 (秒)", maxRetryDelay, (e) => {
          maxRetryDelay = parseInt(e.target.value);
      }));
      panel.appendChild(createInputRow("重试次数阈值", threshold, (e) => {
          threshold = parseInt(e.target.value);
      }));
      panel.appendChild(createInputRow("正常延迟增量 (秒)", normalDelayIncrement, (e) => {
          normalDelayIncrement = parseInt(e.target.value);
      }));
      panel.appendChild(createInputRow("频率过快延迟增量 (秒)", fastFrequencyDelayIncrement, (e) => {
          fastFrequencyDelayIncrement = parseInt(e.target.value);
      }));

      const saveButton = document.createElement("button");
      saveButton.textContent = "保存配置";
      saveButton.style.padding = "8px 16px";
      saveButton.style.border = "none";
      saveButton.style.borderRadius = "4px";
      saveButton.style.background = "#007aff";
      saveButton.style.color = "white";
      saveButton.style.cursor = "pointer";
      saveButton.addEventListener("click", () => {
          createNotification("配置已保存", "success");
      });
      panel.appendChild(saveButton);

      document.body.appendChild(panel);
      return panel;
  };

  // 以固定间隔运行检查
  let checkIntervalId = setInterval(checkAndRetry, CHECK_INTERVAL * 1000);

  // 页面卸载时清除定时器
  window.addEventListener("beforeunload", () => {
      clearInterval(checkIntervalId);
  });

  // 创建配置面板
  configPanel = createConfigPanel();
})();