ChatGPT Message Queue

Queue messages when ChatGPT is still composing responses

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

  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.  
  7. // @version 0.0.1.20250318094810
  8. // @namespace https://greasyfork.org/users/1435046
  9. // ==/UserScript==
  10. (function() {
  11. 'use strict';
  12. let messageQueue = [];
  13. let queueIndicator = null;
  14. let isProcessing = false;
  15. function createQueueIndicator() {
  16. if (queueIndicator) return;
  17. queueIndicator = document.createElement('div');
  18. queueIndicator.style.position = 'absolute';
  19. queueIndicator.style.bottom = '60px';
  20. queueIndicator.style.right = '20px';
  21. queueIndicator.style.backgroundColor = '#343541';
  22. queueIndicator.style.color = 'white';
  23. queueIndicator.style.padding = '8px 12px';
  24. queueIndicator.style.borderRadius = '8px';
  25. queueIndicator.style.fontSize = '14px';
  26. queueIndicator.style.fontWeight = 'bold';
  27. queueIndicator.style.zIndex = '1000';
  28. queueIndicator.style.display = 'none';
  29. queueIndicator.textContent = 'Queued: 0';
  30. document.body.appendChild(queueIndicator);
  31. }
  32. function updateQueueDisplay() {
  33. if (!queueIndicator) createQueueIndicator();
  34. if (messageQueue.length > 0) {
  35. queueIndicator.textContent = `Queued: ${messageQueue.length}`;
  36. queueIndicator.style.display = 'block';
  37. } else {
  38. queueIndicator.style.display = 'none';
  39. }
  40. }
  41. function isComposing() {
  42. return !!document.querySelector('[data-testid="stop-button"]');
  43. }
  44. // Main observer to watch for ChatGPT's state changes
  45. const stateObserver = new MutationObserver(() => {
  46. // If not composing and we have messages, process the next one
  47. if (!isComposing() && messageQueue.length > 0 && !isProcessing) {
  48. processNextMessage();
  49. }
  50. });
  51.  
  52. function processNextMessage() {
  53. if (messageQueue.length === 0 || isComposing()) return;
  54. isProcessing = true;
  55. const message = messageQueue.shift();
  56. updateQueueDisplay();
  57. const textarea = document.getElementById('prompt-textarea');
  58. if (!textarea) {
  59. isProcessing = false;
  60. return;
  61. }
  62. // Set the message in the textarea
  63. textarea.value = message;
  64. // Trigger input event to ensure ChatGPT recognizes the value
  65. const inputEvent = new Event('input', { bubbles: true });
  66. textarea.dispatchEvent(inputEvent);
  67. // Click the send button
  68. setTimeout(() => {
  69. const sendButton = document.querySelector('[data-testid="send-button"]');
  70. if (sendButton) {
  71. sendButton.click();
  72. }
  73. isProcessing = false;
  74. }, 10);
  75. }
  76. // Setup observer to initialize the textarea listener
  77. const setupObserver = new MutationObserver(() => {
  78. const textarea = document.getElementById('prompt-textarea');
  79. if (textarea && !textarea.dataset.queueEnabled) {
  80. textarea.dataset.queueEnabled = 'true';
  81. createQueueIndicator();
  82. textarea.addEventListener('keydown', (e) => {
  83. // Check if Enter pressed without modifiers
  84. if (e.key === 'Enter' && !e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
  85. // Only queue if ChatGPT is composing
  86. if (isComposing()) {
  87. e.preventDefault();
  88. e.stopPropagation();
  89. // Add message to queue
  90. if (textarea.value.trim()) {
  91. messageQueue.push(textarea.value);
  92. textarea.value = '';
  93. updateQueueDisplay();
  94. }
  95. }
  96. }
  97. });
  98. // Start observing state changes once we've set up the textarea
  99. stateObserver.observe(document.body, { childList: true, subtree: true });
  100. }
  101. });
  102. // Start the setup observer
  103. setupObserver.observe(document.body, { childList: true, subtree: true });
  104. })();