Greasy Fork 支持简体中文。

ChatGPT Text Splitter

Automatically split long messages into parts for ChatGPT, inspired by jjdiaz.dev, created with ❤️.

目前為 2025-02-19 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name ChatGPT Text Splitter
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1
  5. // @description Automatically split long messages into parts for ChatGPT, inspired by jjdiaz.dev, created with ❤️.
  6. // @author JOHNNYDAN
  7. // @match https://chatgpt.com/*
  8. // @icon https://chatgpt-prompt-splitter.jjdiaz.dev/favicon.ico
  9. // @grant none
  10. // @license GNU GENERAL PUBLIC LICENSE
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. // Constants
  17. const MAX_CHUNK_SIZE = 15000;
  18. const SCISSOR_EMOJI = '✂️';
  19. const PAPER_EMOJI = '📄';
  20. let longContent = '';
  21. let splitParts = [];
  22. let currentPartIndex = 0;
  23.  
  24. // Function to create styled buttons
  25. function createButton(text, left, top, bgColor) {
  26. const button = document.createElement('button');
  27. button.innerHTML = text;
  28. Object.assign(button.style, {
  29. position: 'fixed',
  30. left: `${left}px`,
  31. top: `${top}px`,
  32. padding: '8px 12px',
  33. fontSize: '14px',
  34. fontWeight: 'bold',
  35. backgroundColor: bgColor,
  36. color: 'white',
  37. border: 'none',
  38. borderRadius: '8px',
  39. cursor: 'pointer',
  40. zIndex: '1000',
  41. transition: '0.2s ease-in-out',
  42. boxShadow: '0px 2px 5px rgba(0,0,0,0.2)'
  43. });
  44.  
  45. button.addEventListener('mouseenter', () => button.style.opacity = '0.8');
  46. button.addEventListener('mouseleave', () => button.style.opacity = '1');
  47.  
  48. document.body.appendChild(button);
  49. return button;
  50. }
  51.  
  52. // Create UI Buttons
  53. const scissorButton = createButton(SCISSOR_EMOJI + " Split", 1600, 10, '#f39c12'); // Orange
  54. const paperButton = createButton(PAPER_EMOJI + " Paste", 1600, 50, '#3498db'); // Blue
  55.  
  56. // Function to show notifications (extended to 5s)
  57. function showNotification(message) {
  58. const notification = document.createElement('div');
  59. notification.textContent = message;
  60. Object.assign(notification.style, {
  61. position: 'fixed',
  62. top: '50px',
  63. left: '50%',
  64. transform: 'translateX(-50%)',
  65. backgroundColor: '#2f2f2f',
  66. color: 'white',
  67. padding: '10px 15px',
  68. borderRadius: '6px',
  69. fontSize: '14px',
  70. fontWeight: 'bold',
  71. zIndex: '999',
  72. boxShadow: '0px 2px 5px rgba(0,0,0,0.2)'
  73. });
  74. document.body.appendChild(notification);
  75. setTimeout(() => notification.remove(), 5000); // Extended to 5 seconds
  76. }
  77.  
  78. // Function to split text into chunks
  79. function splitText(content) {
  80. let parts = [];
  81. let numParts = Math.ceil(content.length / MAX_CHUNK_SIZE);
  82. for (let i = 0; i < numParts; i++) {
  83. let start = i * MAX_CHUNK_SIZE;
  84. let end = start + MAX_CHUNK_SIZE;
  85. parts.push(content.slice(start, end));
  86. }
  87. return parts;
  88. }
  89.  
  90. // Event listener for the scissors button (Step 1)
  91. scissorButton.addEventListener('click', () => {
  92. const editableDiv = document.querySelector('#prompt-textarea');
  93. if (!editableDiv) {
  94. alert('Unable to find the input field!');
  95. return;
  96. }
  97.  
  98. longContent = editableDiv.innerText.trim();
  99. splitParts = splitText(longContent);
  100. currentPartIndex = 0;
  101.  
  102. const instructionText = `
  103. The total length of the content I want to send you is too large to send in one piece.
  104.  
  105. For sending this content, I will follow this rule:
  106.  
  107. [START PART 1/${splitParts.length}]
  108. I will divide the text into parts, each with a strict format.
  109. Do not process the content yet. Simply acknowledge each part as "Part X/Y received" and wait for the next.
  110. [END PART 1/${splitParts.length}]
  111.  
  112. Once all parts are sent, I will write "ALL PARTS SENT" to signal you to process them.
  113. `.trim();
  114.  
  115. editableDiv.innerText = instructionText;
  116. editableDiv.focus();
  117. showNotification("Press Enter to send instructions. Then use the Paste button for parts.");
  118. });
  119.  
  120. // Event listener for the paper button (Step 2)
  121. paperButton.addEventListener('click', () => {
  122. if (splitParts.length === 0) {
  123. showNotification("Click the Split button first to prepare the content.");
  124. return;
  125. }
  126.  
  127. const editableDiv = document.querySelector('#prompt-textarea');
  128. if (!editableDiv) return;
  129.  
  130. // If all parts are sent, send "ALL PARTS SENT" and reset
  131. if (currentPartIndex >= splitParts.length) {
  132. editableDiv.innerText = "ALL PARTS SENT";
  133. showNotification("All parts sent! ChatGPT can now process the data.");
  134. currentPartIndex = 0;
  135. return;
  136. }
  137.  
  138. let partText = splitParts[currentPartIndex];
  139. let totalParts = splitParts.length;
  140. let partNumber = currentPartIndex + 1;
  141.  
  142. let message = `
  143. Do not answer yet. This is just another part of the text I want to send you.
  144. Just receive and acknowledge as "Part ${partNumber}/${totalParts} received" and wait for the next part.
  145.  
  146. [START PART ${partNumber}/${totalParts}]
  147. ${partText}
  148. [END PART ${partNumber}/${totalParts}]
  149. `.trim();
  150.  
  151. if (partNumber < totalParts) {
  152. message += `\nRemember not answering yet. Just acknowledge you received this part with the message "Part ${partNumber}/${totalParts} received" and wait for the next part."`;
  153. }
  154.  
  155. editableDiv.innerText = message;
  156. editableDiv.focus();
  157.  
  158. showNotification(`Sent Part ${partNumber}/${totalParts}. Press Enter.`);
  159.  
  160. currentPartIndex++;
  161. });
  162. })();