DeepSeek Native Setter Injector

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

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

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

您需要先安裝使用者腳本管理器擴充功能,如 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.20250929093627
// @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^="M10 1.22949C5.15604"]').closest('div').click();
      queueArray = [];
      cycleInProgress = false;
      return;
    }

    //toggle display of distractions

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

    let chatMessageInput = document.querySelector('div:has(> div > div > div > div > textarea[placeholder="Message DeepSeek"])');
    let chatMessageInputRule = 'div:has(> div > div > div > div > textarea[placeholder="Message DeepSeek"]) {display: none !important;}';

    let header = document.querySelector('div:has( > div > div[role="button"] > div.ds-icon > svg > path[d*="M17.2028 4.90042V6.43663H2"])');
    let headerRule = 'div:has( > div > div[role="button"] > div.ds-icon > svg > path[d*="M17.2028 4.90042V6.43663H2"]) {display: none !important;}';

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

        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;
      console.log('cycle started');
      //locate the textarea
      const textarea = document.querySelector('textarea[placeholder="Message DeepSeek"]');
      //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"]:has(> div.ds-icon > svg > path[d*="M8.3125 0.981648C8.66767"])');
      console.log(sendBtn)
      if (sendBtn) {
        sendBtn.click();
        console.log('button found')
      }
      //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.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();
  });
})();