// ==UserScript==
// @name ChatGPT Text File Scaler
// @version 1.4
// @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);
} catch(e) {
} finally {
isUIProcessing = false;
}
}
}, 100);
})();