Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The script just doesnt load somehow #12

Open
MoritzHinterleitner opened this issue Jan 9, 2024 · 7 comments
Open

The script just doesnt load somehow #12

MoritzHinterleitner opened this issue Jan 9, 2024 · 7 comments

Comments

@MoritzHinterleitner
Copy link

MoritzHinterleitner commented Jan 9, 2024

I have tried everything. changing the port, running as admin, disabling content security policy, using firefox edge chrome, etc.. but the script will not show any error in console, say anything in console or display any text. sometimes it randomly says error for a second or so but i cant find any pattern when that happens

edit: i found the error that sometimes pops up but only once then its gone for some time again doesnt matter what i do "Uncaught NS_ERROR_CONTENT_BLOCKED:"

edit2: the websocket works fine on other sites google etc just not on chatgpt

edit3: lol :) the problem seems to be that the script waits until the page is loaded but that never seems to happen according to the code to do that. i removed it and its kinda hacky and i dont get a response but the script loads in the first place

@codisfy
Copy link

codisfy commented Feb 28, 2024

You will need to 1 disable CSP - you can look for a CSP disabling extension on the chrome store.

Also the document selectors have changed since the UI on CGPT has changed quite a bit.
I tweaked the tampermonkey script to work with the latest UI.
I have tested with gpt 4 only

// ==UserScript==
// @name         ChatGPT API By Browser Script
// @namespace    http://tampermonkey.net/
// @version      1
// @match        https://chat.openai.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=openai.com
// @grant        GM_webRequest
// @license MIT
// ==/UserScript==
console.log('starting');

const WS_URL = `ws://localhost:8765`;

function getTextFromNode(node) {
  let result = '';

  if (!node) return result;
  const childNodes = node.childNodes;

  for (let i = 0; i < childNodes.length; i++) {
    let childNode = childNodes[i];
    if (childNode.nodeType === Node.TEXT_NODE) {
      result += childNode.textContent;
    } else if (childNode.nodeType === Node.ELEMENT_NODE) {
      result += getTextFromNode(childNode);
    }
  }

  return result;
}

function sleep(time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

// Main app class
class App {
  constructor() {
    this.socket = null;
    this.observer = null;
    this.stop = false;
    this.dom = null;
    this.queue = [];
    this.isProcessing = false;
  }

  async start(data) {
    return new Promise(async (resolve, reject) => {
      const { text, model, newChat } = data;
      this.stop = false
      const textarea = document.querySelector('textarea');
      textarea.value = text;
      const event = new Event('input', { bubbles: true });
      textarea.dispatchEvent(event);
      await sleep(500);
      const send = document.querySelectorAll('button[data-testid="send-button"]')[0];
      if (send) {
        send.click();
        // wait for the message to be sent
        await sleep(1000);
      } else {
        console.log('Send button not found');
      }

      this.observeMutations(resolve);
    });
  }

  observeMutations(resolve) {
    this.observer = new MutationObserver(async (mutations) => {
      const list = [...document.querySelectorAll('div.agent-turn')];
      const last = list[list.length - 1];
      if (!last) {
        console.log('No last message found');
        return;
      }
      let codeNode = last.querySelector('div[data-message-author-role="assistant"] code');
      let lastText = ''

        if (codeNode) {
            lastText = getTextFromNode(codeNode);
        } else {
            lastText = getTextFromNode(last.querySelector('div[data-message-author-role="assistant"]'));
        }
      console.log('send', {
        text: lastText,
      })
      this.socket.send(
        JSON.stringify({
          type: 'answer',
          text: lastText,
        })
      );
      await sleep(1000);
      const button = document.querySelector('button[aria-label="Stop generating"]');
      if (button) return
      if (
        !button
      ) {
        if (this.stop) return
        this.stop = true
        console.log('send', {
          type: 'stop',
        })
        this.socket.send(
          JSON.stringify({
            type: 'stop',
          })
        );
        this.observer.disconnect();
        await sleep(1000);
        resolve();
      }
    });

    const observerConfig = { childList: true, subtree: true };
    this.observer.observe(document.body, observerConfig);
  }

  sendHeartbeat() {
    if (this.socket.readyState === WebSocket.OPEN) {
      this.socket.send(JSON.stringify({ type: 'heartbeat' }));
    }
  }

  connect() {
    this.socket = new WebSocket(WS_URL);
    this.socket.onopen = () => {
      console.log('Server connected, can process requests now.');
      this.dom.innerHTML = '<div style="color: green; ">API Connected !</div>';
    }
    this.socket.onclose = () => {
      console.log('The server connection has been disconnected, the request cannot be processed.');
      this.dom.innerHTML = '<div style="color: red; ">API Disconnected !</div>';

      setTimeout(() => {
        console.log('Attempting to reconnect...');
        this.connect();
      }, 2000);
    }
    this.socket.onerror = () => {
      console.log('Server connection error, please check the server.');
      this.dom.innerHTML = '<div style="color: red; ">API Error !</div>';
    }
    this.socket.onmessage = (event) => {
      const data = JSON.parse(event.data)
      console.log('params', data)
      this.queue.push(data);
      this.processQueue();
    };
  }

  processQueue() {
    console.log('Processing queue ', this.isProcessing);
    if (!this.isProcessing && this.queue.length > 0) {
      this.isProcessing = true;
      const data = this.queue.shift();
      this.start(data).then(() => {
        this.isProcessing = false;
        this.processQueue();
      });
    }
  }


  init() {
    window.addEventListener('load', () => {
      this.dom = document.createElement('div');
      this.dom.style = 'position: fixed; top: 10px; right: 10px; z-index: 9999; display: flex; justify-content: center; align-items: center;';
      document.body.appendChild(this.dom);

      this.connect();

      setInterval(() => this.sendHeartbeat(), 30000);
    });
  }

}

(function () {
  'use strict';
  const app = new App();
  app.init();
})();

@yuligesec
Copy link

You will need to 1 disable CSP - you can look for a CSP disabling extension on the chrome store.

Also the document selectors have changed since the UI on CGPT has changed quite a bit. I tweaked the tampermonkey script to work with the latest UI. I have tested with gpt 4 only

// ==UserScript==
// @name         ChatGPT API By Browser Script
// @namespace    http://tampermonkey.net/
// @version      1
// @match        https://chat.openai.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=openai.com
// @grant        GM_webRequest
// @license MIT
// ==/UserScript==
console.log('starting');

const WS_URL = `ws://localhost:8765`;

function getTextFromNode(node) {
  let result = '';

  if (!node) return result;
  const childNodes = node.childNodes;

  for (let i = 0; i < childNodes.length; i++) {
    let childNode = childNodes[i];
    if (childNode.nodeType === Node.TEXT_NODE) {
      result += childNode.textContent;
    } else if (childNode.nodeType === Node.ELEMENT_NODE) {
      result += getTextFromNode(childNode);
    }
  }

  return result;
}

function sleep(time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

// Main app class
class App {
  constructor() {
    this.socket = null;
    this.observer = null;
    this.stop = false;
    this.dom = null;
  }

  async start({ text, model, newChat }) {
    this.stop = false
    const textarea = document.querySelector('textarea');
    textarea.value = text;
    const event = new Event('input', { bubbles: true });
    textarea.dispatchEvent(event);
    await sleep(500);
    const send = document.querySelectorAll('button[data-testid="send-button"]')[0];
    if (send) {
      send.click();
    } else {
      console.log('Send button not found');
    }

    this.observeMutations();
  }

  observeMutations() {
    this.observer = new MutationObserver(async (mutations) => {
      const list = [...document.querySelectorAll('div.agent-turn')];
      const last = list[list.length - 1];
      if (!last) { 
        console.log('No last message found');
        return;
      }
      const lastText = getTextFromNode(last.querySelector('div[data-message-author-role="assistant"]'));
      console.log('send', {
        text: lastText,
      })
      this.socket.send(
        JSON.stringify({
          type: 'answer',
          text: lastText,
        })
      );
      await sleep(1000);
      const button = document.querySelector('button[aria-label="Stop generating"]');
      if (button) return
      if (
        !button
      ) {
        if (this.stop) return
        this.stop = true
        console.log('send', {
          type: 'stop',
        })
        this.socket.send(
          JSON.stringify({
            type: 'stop',
          })
        );
        this.observer.disconnect();
      }
    });

    const observerConfig = { childList: true, subtree: true };
    this.observer.observe(document.body, observerConfig);
  }

  sendHeartbeat() {
    if (this.socket.readyState === WebSocket.OPEN) {
      this.socket.send(JSON.stringify({ type: 'heartbeat' }));
    }
  }

  connect() {
    this.socket = new WebSocket(WS_URL);
    this.socket.onopen = () => {
      console.log('Server connected, can process requests now.');
      this.dom.innerHTML = '<div style="color: green; ">API Connected !</div>';
    }
    this.socket.onclose = () => {
      console.log('The server connection has been disconnected, the request cannot be processed.');
      this.dom.innerHTML = '<div style="color: red; ">API Disconnected !</div>';

      setTimeout(() => {
        console.log('Attempting to reconnect...');
        this.connect();
      }, 2000);
    }
    this.socket.onerror = () => {
      console.log('Server connection error, please check the server.');
      this.dom.innerHTML = '<div style="color: red; ">API Error !</div>';
    }
    this.socket.onmessage = (event) => {
      const data = JSON.parse(event.data)
      console.log('params', data)
      this.start(data);
    };
  }

  init() {
    window.addEventListener('load', () => {
      this.dom = document.createElement('div');
      this.dom.style = 'position: fixed; top: 10px; right: 10px; z-index: 9999; display: flex; justify-content: center; align-items: center;';
      document.body.appendChild(this.dom);

      this.connect();

      setInterval(() => this.sendHeartbeat(), 30000);
    });
  }

}

(function () {
  'use strict';
  const app = new App();
  app.init();
})();

Utilizing your script, I can only retrieve a response to the previous message, not the one currently being sent.

@codisfy
Copy link

codisfy commented Mar 21, 2024

I have made a few tweaks lately, mainly around queueing up multiple asynchronous calls and how it extracts Markdown.
I have updated the original comment see if that works for you.

@yuligesec
Copy link

I have made a few tweaks lately, mainly around queueing up multiple asynchronous calls and how it extracts Markdown. I have updated the original comment see if that works for you.

good job! Thank you for your assistance. However, have you conducted tests under GPT-4? I have consistently been unable to receive user responses.

@codisfy
Copy link

codisfy commented Mar 28, 2024

Yes - I use it almost daily.
Make sure you see the "API Connected" message in green on top (I had to disable CSP for that)

@mzywl
Copy link

mzywl commented May 18, 2024

Yes - I use it almost daily. Make sure you see the "API Connected" message in green on top (I had to disable CSP for that)

Is there an latest version can you share with me Thank you very much

@SantoshSrinivas79
Copy link

Hi @codisfy do you have a new script for the latest chatgpt.com interface by any chance?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants