DeepSeek Native Setter Injector

Listens for postMessage events on chat.deepseek.com and logs them

目前為 2025-08-13 提交的版本,檢視 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name        DeepSeek Native Setter Injector
// @description  Listens for postMessage events on chat.deepseek.com and logs them
// @match       https://chat.deepseek.com/*
// @version 0.0.1.20250813114445
// @namespace https://greasyfork.org/users/1435046
// ==/UserScript==

(function () {
  'use strict';

  let queueArray = [];
  let cycleInProgress = false;

  // Cache the native setter for HTMLTextAreaElement.value
  const valueSetter = Object.getOwnPropertyDescriptor(
    HTMLTextAreaElement.prototype, 'value'
  ).set;

  window.addEventListener('message', event => {

    // find all primary filled buttons
    const buttons = document.querySelectorAll(
      'div[role="button"].ds-button--primary.ds-button--filled'
    );

    if (event.data && event.data.type === 'searchButtonClicked') {

      // click the one whose visible label is “Search”
      for (const btn of buttons) {
        if (btn.textContent.trim() === 'Search') {
          btn.click();
          break;
        }
      }
      return;
    }

    if (event.data && event.data.type === 'reasonButtonClicked') {

      // click the one whose visible label is “DeepThink (R1)”
      for (const btn of buttons) {
        if (btn.textContent.trim() === 'DeepThink (R1)') {
          btn.click();
          break;
        }
      }
      return;
    }

    //new chat
    if (event.data?.type === 'newChatButtonClicked') {
      document.querySelector('svg path[d^="M9.10999"]').closest('div').click();
      queueArray = [];
      cycleInProgress = false;
      return;
    }

    let deepseekCssStyleId = document.getElementById('deepseekCssStyleId');

    let chatMessageInput = document.querySelector('div:has(> div > div > div > div > textarea[id="chat-input"])');
    let chatMessageInputRule = 'div:has(> div > div > div > div > textarea[id="chat-input"]) {display: none !important;}';

    let header = document.querySelector('div:has(> div > div > svg > path[d^="M23.7222 4H4.27776C3.57207 4"])');
    let headerRule = 'div:has(> div > div > svg > path[d^="M23.7222 4H4.27776C3.57207 4"]) {display: none !important;}';

    //if event data type is defaultChatMessageInputDisplay
    if (event.data?.type === 'defaultChatMessageInputDisplay') {
      console.log('default');
      if (chatMessageInput) {

        deepseekCssStyleId.innerHTML = deepseekCssStyleId.innerHTML.replace(`${chatMessageInputRule}`, '');

        deepseekCssStyleId.innerHTML = deepseekCssStyleId.innerHTML.replace(`${headerRule}`, '');


        //return
        return;
      }
    }

    if (event.data?.type === 'customizeChatMessageInputDisplay') {
      console.log('customize');
      if (chatMessageInput) {

        deepseekCssStyleId.innerHTML += `${chatMessageInputRule}`
        deepseekCssStyleId.innerHTML += `${headerRule}`


        //return
        return;
      }
    }

    //on prompt
    if (event.data.type !== 'prompt') return;

    queueArray.push(event.data.content);
    console.log(queueArray);

    function queue() {

      //if theres a cycle in progress return
      //if theres nothing in the queue return
      console.log('cycleInProgress: ' + cycleInProgress)
      if (cycleInProgress || queueArray.length === 0) { return };

      //start the cycle
      cycleInProgress = true;
      //locate the textarea
      const textarea = document.getElementById('chat-input');
      //if theres no text area return
      if (!textarea) return;
      //inject the text
      // 1. Update both DOM and React state without shifting focus
      valueSetter.call(textarea, queueArray[0]);

      // 2. Notify React/Vue/etc. of the change
      textarea.dispatchEvent(new InputEvent('input', { bubbles: true }));

      //send the text
      const sendBtn = document.querySelector('div[role="button"][aria-disabled="false"]');
      if (
        sendBtn &&
        sendBtn.querySelector('path[d^="M7 16c-.595 0-1.077-.462-1.077"]')
      ) {
        sendBtn.click();
      }
      //now wait for the stop button to disappear
      //create an observer
      //let the function take the mutation record array as a parameter / argument
      //and define the function
      let observer = new MutationObserver(function (mutationRecordArray) {
        //for each mutation
        mutationRecordArray.forEach(function (mutationRecord) {
          console.log('mutation record old value: ', mutationRecord.oldValue);
          console.log('mutation record: ', mutationRecord);
          console.log('mutation record target: ', mutationRecord.target);

          if (mutationRecord.oldValue === 'false' && mutationRecord.target.matches('div[role="button"][aria-disabled="true"]:has(> div > div.ds-icon > svg)')) {

            //if (mutationRecord.oldValue === 'true') {
            console.log('button with true aria disabled has been removed');
            //disconect the observer since the cycle has finished and a response has been generated
            observer.disconnect();
            //as the response has completed lets remove the first value in the queue which we presumably just got a
            //response for
            console.log(queueArray.shift())
            //lets indicate theat the cycle has ended
            cycleInProgress = false;
            //lets call the queue function again to see if there are more items in the queue array
            queue();
          };
        })
      })
      //observe aria disabled attribute
      observer.observe(document.body, { subtree: true, attributeFilter: ["aria-disabled"], attributeOldValue: true })
    }
    queue();
  });
})();