ChatGPT Text Splitter

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

当前为 2025-02-19 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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++;
    });
})();