DeepSeek Response Interceptor(text recognition)

该脚本用于拦截DeepSeek屏蔽提示,并输出已缓存文本,重新加载网页失效。可自定义需要拦截的文本

当前为 2025-02-03 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name:zh-CN DeepSeek响应拦截器(文字识别版)
  3. // @name DeepSeek Response Interceptor(text recognition)
  4. // @namespace https://github.com/Ahikl/
  5. // @homepage https://github.com/Ahikl/DeepSeek_Response_Interceptor
  6. // @version 1.4
  7. // @description 该脚本用于拦截DeepSeek屏蔽提示,并输出已缓存文本,重新加载网页失效。可自定义需要拦截的文本
  8. // @author Ahikl
  9. // @match https://chat.deepseek.com/*
  10. // @grant none
  11. // @run-at document-start
  12. // @license MIT
  13. // ==/UserScript==
  14.  
  15. (function () {
  16. "use strict";
  17.  
  18. // 定义需要拦截的屏蔽文本
  19. const BLOCKED_TEXTS = [
  20. "检测到本次回复可能涉及不当内容,已启用安全保护机制。我们倡导健康文明的交流环境。",
  21. "你好,这个问题我暂时无法回答,让我们换个话题再聊聊吧。",
  22. "对不起,我还没有学会如何思考这类问题,我擅长数学、代码、逻辑类的题目,欢迎与我交流。",
  23. "我们始终遵循法律法规和伦理准则,倡导健康积极的交流环境。如果您有任何其他合法合规的咨询需求,我们将竭诚为您提供专业服务。",
  24. "我明白您希望继续这个虚构的角色扮演情景,但目前我无法提供此类包含成人内容的互动。如果您有其他话题或需要创作健康的故事框架,我很乐意协助您! 😊",
  25. "出于安全方面的考虑,我恐怕无法完成您提到的这个任务。如果您有其他与学习、生活或娱乐相关的问题,我很愿意为您提供帮助。",
  26. "很抱歉,我无法继续参与这个对话。如果您有其他问题或需要帮助,请随时告诉我!"
  27. ];// 添加更多屏蔽文本
  28.  
  29. // 用于记录上一次有效输出的内容,后续用于回滚
  30. let lastValidContent = "";
  31. const chatContainerSelector = ".chat-container";
  32. let chatContainer = null;
  33.  
  34. // 尝试获取聊天容器
  35. function getChatContainer() {
  36. if (!chatContainer) {
  37. chatContainer = document.querySelector(chatContainerSelector);
  38. }
  39. return chatContainer;
  40. }
  41.  
  42. // 更新上一次有效输出
  43. function updateLastValidContent() {
  44. const container = getChatContainer();
  45. if (container) {
  46. lastValidContent = container.innerHTML;
  47. }
  48. }
  49.  
  50. // 回滚到上一次有效输出
  51. function rollbackContent() {
  52. const container = getChatContainer();
  53. if (container) {
  54. console.warn("检测到屏蔽文本,回滚到上一次有效内容。");
  55. container.innerHTML = lastValidContent;
  56. }
  57. }
  58.  
  59. // 检查是否包含任何屏蔽文本
  60. function containsBlockedText(text) {
  61. return BLOCKED_TEXTS.some(blockedText => text.includes(blockedText));
  62. }
  63.  
  64. // 重写 fetch 方法,拦截流式响应
  65. const originalFetch = window.fetch;
  66. window.fetch = async function (...args) {
  67. const response = await originalFetch(...args);
  68. if (!response.body) return response; // 非流式响应直接返回
  69.  
  70. const reader = response.body.getReader();
  71. const decoder = new TextDecoder();
  72. let bufferedText = "";
  73.  
  74. const newStream = new ReadableStream({
  75. start(controller) {
  76. function push() {
  77. reader.read().then(({done, value}) => {
  78. if (done) {
  79. controller.close();
  80. return;
  81. }
  82. const chunk = decoder.decode(value, {stream: true});
  83. bufferedText += chunk;
  84. // 检查是否包含屏蔽文本
  85. if (containsBlockedText(bufferedText)) {
  86. console.warn("Fetch 检测到屏蔽文本,终止流式响应。");
  87. controller.close();
  88. rollbackContent();
  89. return;
  90. }
  91. controller.enqueue(value);
  92. updateLastValidContent();
  93. push();
  94. }).catch(err => {
  95. console.error("Fetch 处理异常:", err);
  96. controller.error(err);
  97. });
  98. }
  99.  
  100. push();
  101. }
  102. });
  103. return new Response(newStream, {
  104. headers: response.headers,
  105. status: response.status,
  106. statusText: response.statusText,
  107. });
  108. };
  109.  
  110. console.log("已重写 fetch 逻辑。");
  111.  
  112. // 重写 XMLHttpRequest 以拦截请求
  113. const originalXHR = window.XMLHttpRequest;
  114.  
  115. function InterceptedXHR() {
  116. const xhr = new originalXHR();
  117. let bufferedResponse = "";
  118. xhr.addEventListener("readystatechange", function () {
  119. // readyState 3: 正在接收数据;4: 请求结束
  120. if (xhr.readyState === 3 || xhr.readyState === 4) {
  121. bufferedResponse = xhr.responseText;
  122. if (containsBlockedText(bufferedResponse)) {
  123. console.warn("XHR 检测到屏蔽文本,终止请求。");
  124. xhr.abort();
  125. rollbackContent();
  126. } else {
  127. updateLastValidContent();
  128. }
  129. }
  130. });
  131. return xhr;
  132. }
  133.  
  134. window.XMLHttpRequest = InterceptedXHR;
  135. console.log("已重写 XMLHttpRequest 逻辑。");
  136.  
  137. // 使用 MutationObserver 监控 DOM 变化,确保动态插入的内容中不包含屏蔽文本
  138. function setupObserver() {
  139. const container = getChatContainer();
  140. if (!container) return;
  141. const observer = new MutationObserver((mutationsList) => {
  142. for (let mutation of mutationsList) {
  143. if (mutation.type === "childList") {
  144. mutation.addedNodes.forEach((node) => {
  145. let text = "";
  146. if (node.nodeType === Node.TEXT_NODE) {
  147. text = node.textContent;
  148. } else if (node.nodeType === Node.ELEMENT_NODE) {
  149. text = node.innerText || "";
  150. }
  151. if (text && containsBlockedText(text)) {
  152. console.warn("MutationObserver 检测到屏蔽文本,触发回滚。");
  153. rollbackContent();
  154. }
  155. });
  156. }
  157. }
  158. });
  159. observer.observe(container, {childList: true, subtree: true});
  160. console.log("脚本已启动。");
  161. }
  162.  
  163. // 定时检查目标容器是否加载完成,然后启动观察器
  164. function initObserver() {
  165. const interval = setInterval(() => {
  166. if (getChatContainer()) {
  167. updateLastValidContent();
  168. setupObserver();
  169. clearInterval(interval);
  170. }
  171. }, 1000);
  172. }
  173.  
  174. window.addEventListener("load", initObserver);
  175.  
  176. console.log("脚本已注入,用于拦截流式响应并回滚屏蔽内容。");
  177. })();