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.20250318094033
  8. // @namespace https://greasyfork.org/users/1435046
  9. // ==/UserScript==
  10. (function() {
  11. 'use strict';
  12. let messageQueue = [];
  13. let queueIndicator = null;
  14. function createQueueIndicator() {
  15. if (queueIndicator) return;
  16. queueIndicator = document.createElement('div');
  17. queueIndicator.style.position = 'absolute';
  18. queueIndicator.style.bottom = '60px';
  19. queueIndicator.style.right = '20px';
  20. queueIndicator.style.backgroundColor = '#343541';
  21. queueIndicator.style.color = 'white';
  22. queueIndicator.style.padding = '8px 12px';
  23. queueIndicator.style.borderRadius = '8px';
  24. queueIndicator.style.fontSize = '14px';
  25. queueIndicator.style.fontWeight = 'bold';
  26. queueIndicator.style.zIndex = '1000';
  27. queueIndicator.style.display = 'none';
  28. queueIndicator.textContent = 'Queued: 0';
  29. document.body.appendChild(queueIndicator);
  30. }
  31. function updateQueueDisplay() {
  32. if (!queueIndicator) createQueueIndicator();
  33. if (messageQueue.length > 0) {
  34. queueIndicator.textContent = `Queued: ${messageQueue.length}`;
  35. queueIndicator.style.display = 'block';
  36. } else {
  37. queueIndicator.style.display = 'none';
  38. }
  39. }
  40. function processQueue() {
  41. if (messageQueue.length === 0) return;
  42. const textarea = document.getElementById('prompt-textarea');
  43. if (!textarea) return;
  44. // Wait until ChatGPT is not composing
  45. if (document.querySelector('[data-testid="stop-button"]')) return;
  46. const message = messageQueue.shift();
  47. textarea.value = message;
  48. // Trigger input event to ensure ChatGPT recognizes the value
  49. const inputEvent = new Event('input', { bubbles: true });
  50. textarea.dispatchEvent(inputEvent);
  51. // Click the send button
  52. const sendButton = document.querySelector('[data-testid="send-button"]');
  53. if (sendButton) {
  54. sendButton.click();
  55. }
  56. updateQueueDisplay();
  57. }
  58. // Set up a mutation observer to detect when the textarea is added to the DOM
  59. const setupObserver = new MutationObserver(() => {
  60. const textarea = document.getElementById('prompt-textarea');
  61. if (textarea && !textarea.dataset.queueEnabled) {
  62. textarea.dataset.queueEnabled = 'true';
  63. createQueueIndicator();
  64. textarea.addEventListener('keydown', (e) => {
  65. // Check if Enter pressed without modifiers
  66. if (e.key === 'Enter' && !e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
  67. // Check if ChatGPT is composing (stop button exists)
  68. if (document.querySelector('[data-testid="stop-button"]')) {
  69. e.preventDefault();
  70. e.stopPropagation();
  71. // Add message to queue
  72. messageQueue.push(textarea.value);
  73. textarea.value = '';
  74. updateQueueDisplay();
  75. }
  76. }
  77. });
  78. }
  79. });
  80. // Observer to detect when ChatGPT finishes composing
  81. const composingObserver = new MutationObserver(() => {
  82. // Process queue when ChatGPT is not composing
  83. if (!document.querySelector('[data-testid="stop-button"]')) {
  84. processQueue();
  85. }
  86. });
  87. // Start observing
  88. setupObserver.observe(document.body, { childList: true, subtree: true });
  89. composingObserver.observe(document.body, { childList: true, subtree: true });
  90. })();