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. // @version 0.0.1.20250318133653
  7. // @namespace https://greasyfork.org/users/1435046
  8. // ==/UserScript==
  9.  
  10. (function() {
  11. 'use strict';
  12. let queueCount = 0;
  13. let queueObserver;
  14. let queueDisplay;
  15.  
  16. function createQueueDisplay() {
  17. queueDisplay = document.createElement('div');
  18. queueDisplay.style.position = 'fixed';
  19. queueDisplay.style.bottom = '100px';
  20. queueDisplay.style.right = '20px';
  21. queueDisplay.style.background = 'rgba(0,0,0,0.7)';
  22. queueDisplay.style.color = 'white';
  23. queueDisplay.style.padding = '5px 10px';
  24. queueDisplay.style.borderRadius = '4px';
  25. queueDisplay.style.display = 'flex';
  26. queueDisplay.style.gap = '8px';
  27. queueDisplay.style.alignItems = 'center';
  28.  
  29. const text = document.createElement('span');
  30. text.textContent = `Queue: ${queueCount}`;
  31. const clearBtn = document.createElement('button');
  32. clearBtn.textContent = '×';
  33. clearBtn.style.cursor = 'pointer';
  34. clearBtn.style.background = 'transparent';
  35. clearBtn.style.border = 'none';
  36. clearBtn.style.color = 'inherit';
  37. clearBtn.style.fontSize = '18px';
  38. clearBtn.style.padding = '0 4px';
  39. clearBtn.onclick = () => {
  40. queueCount = 0;
  41. text.textContent = `Queue: ${queueCount}`;
  42. };
  43.  
  44. queueDisplay.appendChild(text);
  45. queueDisplay.appendChild(clearBtn);
  46. document.body.appendChild(queueDisplay);
  47. }
  48.  
  49. function handleSendButton() {
  50. const sendButton = document.querySelector('[data-testid="send-button"]');
  51. if (sendButton && queueCount > 0) {
  52. sendButton.click();
  53. queueCount--;
  54. queueDisplay.querySelector('span').textContent = `Queue: ${queueCount}`;
  55. }
  56. }
  57.  
  58. const textareaObserver = new MutationObserver(() => {
  59. const textarea = document.getElementById('prompt-textarea');
  60. if (textarea && !textarea.dataset.queueEnabled) {
  61. textarea.dataset.queueEnabled = 'true';
  62. textarea.addEventListener('keyup', (e) => {
  63. if (e.key === 'Enter' && !e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
  64. // Changed to check for streaming class
  65. if (document.querySelector('.result-streaming')) {
  66. e.preventDefault();
  67. queueCount++;
  68. queueDisplay.querySelector('span').textContent = `Queue: ${queueCount}`;
  69. if (!queueObserver) {
  70. queueObserver = new MutationObserver(handleSendButton);
  71. queueObserver.observe(document.body, {
  72. childList: true,
  73. subtree: true
  74. });
  75. }
  76. }
  77. }
  78. });
  79. }
  80. });
  81.  
  82. // Initialize
  83. createQueueDisplay();
  84. textareaObserver.observe(document.body, {
  85. childList: true,
  86. subtree: true
  87. });
  88. })();