ChatGPT Smart Message Queue

Queue messages based on input field state

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

  1. // ==UserScript==
  2. // @name ChatGPT Smart Message Queue
  3. // @match https://chat.openai.com/*
  4. // @match https://chatgpt.com/*
  5. // @description Queue messages based on input field state
  6. // @version 0.0.1.20250318144238
  7. // @namespace https://greasyfork.org/users/1435046
  8. // ==/UserScript==
  9.  
  10. (function() {
  11. 'use strict';
  12. let queueCount = 0;
  13. let queueDisplay;
  14. let isWaitingForClear = false;
  15. let originalMessage = '';
  16.  
  17. function createQueueDisplay() {
  18. queueDisplay = document.createElement('div');
  19. queueDisplay.style.position = 'fixed';
  20. queueDisplay.style.bottom = '100px';
  21. queueDisplay.style.right = '20px';
  22. queueDisplay.style.background = 'rgba(0,0,0,0.7)';
  23. queueDisplay.style.color = 'white';
  24. queueDisplay.style.padding = '8px 16px';
  25. queueDisplay.style.borderRadius = '8px';
  26. queueDisplay.style.zIndex = '9999';
  27. queueDisplay.innerHTML = `
  28. <div style="display: flex; gap: 12px; align-items: center">
  29. <span>Queue: ${queueCount}</span>
  30. <button style="
  31. background: transparent;
  32. border: none;
  33. color: white;
  34. cursor: pointer;
  35. padding: 4px 8px;
  36. border-radius: 4px;
  37. " id="clear-queue">Clear</button>
  38. </div>
  39. `;
  40. queueDisplay.querySelector('#clear-queue').addEventListener('click', () => {
  41. queueCount = 0;
  42. queueDisplay.querySelector('span').textContent = `Queue: ${queueCount}`;
  43. });
  44.  
  45. document.body.appendChild(queueDisplay);
  46. }
  47.  
  48. function trySendMessage() {
  49. const textarea = document.getElementById('prompt-textarea');
  50. const sendButton = document.querySelector('[data-testid="send-button"]');
  51. if (textarea && sendButton && !sendButton.disabled && textarea.value === '') {
  52. const queuedMessage = originalMessage;
  53. textarea.value = queuedMessage;
  54. textarea.dispatchEvent(new Event('input', { bubbles: true }));
  55. // Use small timeout to ensure UI updates
  56. setTimeout(() => {
  57. if (sendButton && !sendButton.disabled) {
  58. originalMessage = queuedMessage;
  59. sendButton.click();
  60. isWaitingForClear = true;
  61. }
  62. }, 50);
  63. }
  64. }
  65.  
  66. function handleKeyDown(e) {
  67. if (e.key === 'Enter' && !e.shiftKey && !e.altKey && !e.ctrlKey && !e.metaKey) {
  68. const textarea = e.target;
  69. if (textarea.value.trim() === '') return;
  70.  
  71. // Store original message before submission
  72. originalMessage = textarea.value.trim();
  73. // Check if message was accepted within 500ms
  74. setTimeout(() => {
  75. if (textarea.value !== '') {
  76. queueCount++;
  77. queueDisplay.querySelector('span').textContent = `Queue: ${queueCount}`;
  78. isWaitingForClear = true;
  79. }
  80. }, 500);
  81. }
  82. }
  83.  
  84. function init() {
  85. createQueueDisplay();
  86. // Observe textarea for clearing events
  87. const textareaObserver = new MutationObserver((mutations) => {
  88. mutations.forEach(mutation => {
  89. if (mutation.target.value === '' && isWaitingForClear) {
  90. isWaitingForClear = false;
  91. if (queueCount > 0) {
  92. queueCount--;
  93. queueDisplay.querySelector('span').textContent = `Queue: ${queueCount}`;
  94. trySendMessage();
  95. }
  96. }
  97. });
  98. });
  99.  
  100. const textarea = document.getElementById('prompt-textarea');
  101. if (textarea) {
  102. textarea.addEventListener('keydown', handleKeyDown);
  103. textareaObserver.observe(textarea, {
  104. attributes: true,
  105. attributeFilter: ['value']
  106. });
  107. }
  108. }
  109.  
  110. // Start the script
  111. init();
  112. })();