ChatGPT Text Splitter

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

目前为 2025-02-19 提交的版本。查看 最新版本

// ==UserScript==
// @name         ChatGPT Text Splitter
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Automatically split long messages into parts for ChatGPT, inspired by jjdiaz.dev, created with ❤️.
// @author       JOHNNYDAN
// @match        https://chatgpt.com/*
// @icon         https://chatgpt-prompt-splitter.jjdiaz.dev/favicon.ico
// @grant        none
// @license      GNU GENERAL PUBLIC LICENSE
// ==/UserScript==

(function() {
    'use strict';

    // Constants
    const MAX_CHUNK_SIZE = 15000;
    const SCISSOR_EMOJI = '✂️';
    const PAPER_EMOJI = '📄';
    let longContent = '';
    let splitParts = [];
    let currentPartIndex = 0;

    // Function to create styled buttons
    function createButton(text, left, top, bgColor) {
        const button = document.createElement('button');
        button.innerHTML = text;
        Object.assign(button.style, {
            position: 'fixed',
            left: `${left}px`,
            top: `${top}px`,
            padding: '8px 12px',
            fontSize: '14px',
            fontWeight: 'bold',
            backgroundColor: bgColor,
            color: 'white',
            border: 'none',
            borderRadius: '8px',
            cursor: 'pointer',
            zIndex: '1000',
            transition: '0.2s ease-in-out',
            boxShadow: '0px 2px 5px rgba(0,0,0,0.2)'
        });

        button.addEventListener('mouseenter', () => button.style.opacity = '0.8');
        button.addEventListener('mouseleave', () => button.style.opacity = '1');

        document.body.appendChild(button);
        return button;
    }

    // Create UI Buttons
    const scissorButton = createButton(SCISSOR_EMOJI + " Split", 1600, 10, '#f39c12'); // Orange
    const paperButton = createButton(PAPER_EMOJI + " Paste", 1600, 50, '#3498db'); // Blue

    // Function to show notifications (extended to 5s)
    function showNotification(message) {
        const notification = document.createElement('div');
        notification.textContent = message;
        Object.assign(notification.style, {
            position: 'fixed',
            top: '50px',
            left: '50%',
            transform: 'translateX(-50%)',
            backgroundColor: '#2f2f2f',
            color: 'white',
            padding: '10px 15px',
            borderRadius: '6px',
            fontSize: '14px',
            fontWeight: 'bold',
            zIndex: '999',
            boxShadow: '0px 2px 5px rgba(0,0,0,0.2)'
        });
        document.body.appendChild(notification);
        setTimeout(() => notification.remove(), 5000); // Extended to 5 seconds
    }

    // Function to split text into chunks
    function splitText(content) {
        let parts = [];
        let numParts = Math.ceil(content.length / MAX_CHUNK_SIZE);
        for (let i = 0; i < numParts; i++) {
            let start = i * MAX_CHUNK_SIZE;
            let end = start + MAX_CHUNK_SIZE;
            parts.push(content.slice(start, end));
        }
        return parts;
    }

    // Event listener for the scissors button (Step 1)
    scissorButton.addEventListener('click', () => {
        const editableDiv = document.querySelector('#prompt-textarea');
        if (!editableDiv) {
            alert('Unable to find the input field!');
            return;
        }

        longContent = editableDiv.innerText.trim();
        splitParts = splitText(longContent);
        currentPartIndex = 0;

        const instructionText = `
The total length of the content I want to send you is too large to send in one piece.

For sending this content, I will follow this rule:

[START PART 1/${splitParts.length}]
I will divide the text into parts, each with a strict format.
Do not process the content yet. Simply acknowledge each part as "Part X/Y received" and wait for the next.
[END PART 1/${splitParts.length}]

Once all parts are sent, I will write "ALL PARTS SENT" to signal you to process them.
        `.trim();

        editableDiv.innerText = instructionText;
        editableDiv.focus();
        showNotification("Press Enter to send instructions. Then use the Paste button for parts.");
    });

    // Event listener for the paper button (Step 2)
    paperButton.addEventListener('click', () => {
        if (splitParts.length === 0) {
            showNotification("Click the Split button first to prepare the content.");
            return;
        }

        const editableDiv = document.querySelector('#prompt-textarea');
        if (!editableDiv) return;

        // If all parts are sent, send "ALL PARTS SENT" and reset
        if (currentPartIndex >= splitParts.length) {
            editableDiv.innerText = "ALL PARTS SENT";
            showNotification("All parts sent! ChatGPT can now process the data.");
            currentPartIndex = 0;
            return;
        }

        let partText = splitParts[currentPartIndex];
        let totalParts = splitParts.length;
        let partNumber = currentPartIndex + 1;

        let message = `
Do not answer yet. This is just another part of the text I want to send you.
Just receive and acknowledge as "Part ${partNumber}/${totalParts} received" and wait for the next part.

[START PART ${partNumber}/${totalParts}]
${partText}
[END PART ${partNumber}/${totalParts}]
        `.trim();

        if (partNumber < totalParts) {
            message += `\nRemember not answering yet. Just acknowledge you received this part with the message "Part ${partNumber}/${totalParts} received" and wait for the next part."`;
        }

        editableDiv.innerText = message;
        editableDiv.focus();

        showNotification(`Sent Part ${partNumber}/${totalParts}. Press Enter.`);

        currentPartIndex++;
    });
})();