Greasy Fork is available in English.
Queue messages when ChatGPT is still composing responses
// ==UserScript== // @name ChatGPT Message Queue // @match https://chat.openai.com/* // @match https://chatgpt.com/* // @description Queue messages when ChatGPT is still composing responses // @version 0.0.1.20250319105457 // @namespace https://greasyfork.org/users/1435046 // ==/UserScript== (function() { 'use strict'; let queueCount = 0; let queueObserver; let processingMessage = false; const queueDisplay = document.createElement('div'); // Minimal UI setup queueDisplay.innerHTML = ` <span>Queue: ${queueCount}</span> <button id="queue-reset">×</button> `; queueDisplay.style.cssText = ` position:fixed; bottom:100px; right:20px; background:rgba(0,0,0,0.7); color:white; padding:5px 10px; border-radius:4px; display:flex; gap:8px; `; document.body.appendChild(queueDisplay); // Reset queue count when button is clicked document.getElementById('queue-reset').addEventListener('click', () => { queueCount = 0; queueDisplay.children[0].textContent = `Queue: ${queueCount}`; }); // Function to start queue processing function startQueueObserver() { if (queueObserver) return; // Prevent duplicate observers queueObserver = new MutationObserver(() => { // Only proceed if we have messages in queue and we're not currently processing if (queueCount > 0 && !processingMessage) { const sendButton = document.querySelector('[data-testid="send-button"]'); const textArea = document.getElementById('prompt-textarea'); // Only click if the send button is enabled and textarea is accessible if (sendButton && !sendButton.disabled && textArea) { processingMessage = true; // Wait for the current response to complete const checkCompletion = setInterval(() => { // Look for indicators that the AI has finished responding const isResponding = document.querySelector('.r###lt-streaming') || document.querySelector('[data-testid="stop-generating"]'); if (!isResponding) { clearInterval(checkCompletion); // Wait a bit for the UI to fully update setTimeout(() => { // Now we can send the next message sendButton.click(); queueCount--; queueDisplay.children[0].textContent = `Queue: ${queueCount}`; processingMessage = false; // Stop observing when queue is empty if (queueCount === 0) { queueObserver.disconnect(); queueObserver = null; } }, 500); } }, 1000); } } }); queueObserver.observe(document.body, {childList: true, subtree: true}); } // Core logic: Monitor input field new MutationObserver((_, observer) => { const textarea = document.getElementById('prompt-textarea'); if (textarea && !textarea.dataset.queuer) { textarea.dataset.queuer = true; textarea.addEventListener('keydown', e => { if (e.key === 'Enter' && !e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) { // Allow DOM update setTimeout(() => { if (textarea.textContent.trim()) { queueCount++; queueDisplay.children[0].textContent = `Queue: ${queueCount}`; startQueueObserver(); // Start processing queue } }, 100); } }); } }).observe(document.body, {childList: true, subtree: true}); })();