// ==UserScript== // @name ChatGPT Text File Scaler // @version 1.3 // @author refracta // @description ChatGPT utility to cut and transfer text files // @match https://chat.openai.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=openai.com // @license MIT // @namespace https://greasyfork.org/users/467840 // @downloadURL none // ==/UserScript== (async function () { 'use strict'; function createElement(html) { var div = document.createElement('div'); div.innerHTML = html.trim(); return div.firstChild; } function insertAfter(referenceNode, newNode) { if (!!referenceNode.nextSibling) { referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling); } else { referenceNode.parentNode.appendChild(newNode); } } function waitFor(valueFunction, inspectPeriod = 100) { return new Promise(resolve => { let interval = setInterval(async _ => { try { let value = valueFunction(); value = value instanceof Promise ? await value : value; if (value) { clearInterval(interval); resolve(value); } } catch (e) {} }, inspectPeriod); }); } function writeMessage(text) { document.querySelector('textarea').value = text; } function clickSendButton() { document.querySelector('button.absolute').click(); } async function waitResponse() { await waitFor(_ => document.querySelector('button.absolute.p-1 > svg')); } async function sendMessage(text) { writeMessage(text); clickSendButton(); await waitResponse(); } function clearMessages(messageLimit) { let messages = Array.from(document.querySelectorAll('.flex-1.overflow-hidden > div > div > div > div:nth-child(1) > div')); while (messages.length > messageLimit) { messages.shift().remove(); } } function updateLoadTextFileSpan() { let loadTextFileSpan = document.querySelector('#load-text-file'); if (loadTextFileSpan) { loadTextFileSpan.textContent = `Load text file (${localStorage.buffer.length})`; } } async function sendTextFile() { const firstMessage = 'I am going to provide you a book in multiple messages.'; const insertMessage = 'Here is the next page, please do not respond aside from confirmation:\n\n'; const splitLength = 2000; const messageLimit = 30; await sendMessage(firstMessage); while (localStorage.buffer.length > 0) { let length = splitLength - insertMessage.length; let text = localStorage.buffer.slice(0, length); await sendMessage(insertMessage + text); localStorage.buffer = localStorage.buffer.slice(length); updateLoadTextFileSpan(); clearMessages(messageLimit); } } function getText() { return new Promise(resolve => { let input = document.createElement("input"); input.type = "file"; input.accept = "text/plain"; input.onchange = (event) => { let file = event.target.files[0]; let reader = new FileReader(); reader.onload = () => { resolve(reader.result); }; reader.readAsText(file); }; input.click(); }); } localStorage.buffer = localStorage.buffer ? localStorage.buffer : ''; let isUIProcessing = false; setInterval(async _ => { if (!document.querySelector('#load-text-file') && !isUIProcessing) { try { isUIProcessing = true; let historyDiv = document.querySelector('.scrollbar-trigger > nav > div'); let sendTextFileButton = createElement(`Send text file`); sendTextFileButton.addEventListener('click', sendTextFile); insertAfter(historyDiv, sendTextFileButton); let loadTextFileButton = createElement(`Load text file (${localStorage.buffer.length})`); loadTextFileButton.addEventListener('click', async() => { localStorage.buffer = await getText(); updateLoadTextFileSpan(); }); insertAfter(historyDiv, loadTextFileButton); } finally { isUIProcessing = false; } } }, 100); })();