ChatGPT Message Queue

Queue messages when ChatGPT is still composing responses

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

  1. // ==UserScript==
  2. // @name ChatGPT Message Queue
  3. // @match https://chat.openai.com/*
  4. // @match https://chatgpt.com/*
  5. // @description Queue messages when ChatGPT is still composing responses
  6. // @version 0.0.1.20250319105457
  7. // @namespace https://greasyfork.org/users/1435046
  8. // ==/UserScript==
  9.  
  10. (function() {
  11. 'use strict';
  12. let queueCount = 0;
  13. let queueObserver;
  14. let processingMessage = false;
  15. const queueDisplay = document.createElement('div');
  16. // Minimal UI setup
  17. queueDisplay.innerHTML = `
  18. <span>Queue: ${queueCount}</span>
  19. <button id="queue-reset">×</button>
  20. `;
  21. queueDisplay.style.cssText = `
  22. position:fixed; bottom:100px; right:20px;
  23. background:rgba(0,0,0,0.7); color:white;
  24. padding:5px 10px; border-radius:4px; display:flex; gap:8px;
  25. `;
  26. document.body.appendChild(queueDisplay);
  27. // Reset queue count when button is clicked
  28. document.getElementById('queue-reset').addEventListener('click', () => {
  29. queueCount = 0;
  30. queueDisplay.children[0].textContent = `Queue: ${queueCount}`;
  31. });
  32. // Function to start queue processing
  33. function startQueueObserver() {
  34. if (queueObserver) return; // Prevent duplicate observers
  35. queueObserver = new MutationObserver(() => {
  36. // Only proceed if we have messages in queue and we're not currently processing
  37. if (queueCount > 0 && !processingMessage) {
  38. const sendButton = document.querySelector('[data-testid="send-button"]');
  39. const textArea = document.getElementById('prompt-textarea');
  40. // Only click if the send button is enabled and textarea is accessible
  41. if (sendButton && !sendButton.disabled && textArea) {
  42. processingMessage = true;
  43. // Wait for the current response to complete
  44. const checkCompletion = setInterval(() => {
  45. // Look for indicators that the AI has finished responding
  46. const isResponding = document.querySelector('.result-streaming') ||
  47. document.querySelector('[data-testid="stop-generating"]');
  48. if (!isResponding) {
  49. clearInterval(checkCompletion);
  50. // Wait a bit for the UI to fully update
  51. setTimeout(() => {
  52. // Now we can send the next message
  53. sendButton.click();
  54. queueCount--;
  55. queueDisplay.children[0].textContent = `Queue: ${queueCount}`;
  56. processingMessage = false;
  57. // Stop observing when queue is empty
  58. if (queueCount === 0) {
  59. queueObserver.disconnect();
  60. queueObserver = null;
  61. }
  62. }, 500);
  63. }
  64. }, 1000);
  65. }
  66. }
  67. });
  68. queueObserver.observe(document.body, {childList: true, subtree: true});
  69. }
  70. // Core logic: Monitor input field
  71. new MutationObserver((_, observer) => {
  72. const textarea = document.getElementById('prompt-textarea');
  73. if (textarea && !textarea.dataset.queuer) {
  74. textarea.dataset.queuer = true;
  75. textarea.addEventListener('keydown', e => {
  76. if (e.key === 'Enter' && !e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
  77. // Allow DOM update
  78. setTimeout(() => {
  79. if (textarea.textContent.trim()) {
  80. queueCount++;
  81. queueDisplay.children[0].textContent = `Queue: ${queueCount}`;
  82. startQueueObserver(); // Start processing queue
  83. }
  84. }, 100);
  85. }
  86. });
  87. }
  88. }).observe(document.body, {childList: true, subtree: true});
  89. })();