您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
ChatGPT utility to cut and transfer text files
- // ==UserScript==
- // @name ChatGPT Text File Scaler
- // @version 1.8
- // @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
- // ==/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) {
- let textarea = document.querySelector('textarea');
- textarea.value = text;
- let event = new Event('input', {
- bubbles: true
- });
- textarea.dispatchEvent(event);
- }
- async function clickSendButton() {
- do {
- document.querySelector('button.absolute').disabled = false;
- let clickEvent = document.createEvent('MouseEvents');
- clickEvent.initEvent("click", true, true);
- document.querySelector('button.absolute').dispatchEvent(clickEvent);
- if (document.querySelector('textarea')?.value === '') {
- break;
- }
- await new Promise(resolve => setTimeout(resolve, 100));
- } while (true);
- }
- async function waitResponse() {
- await waitFor(_ => document.querySelector('button.absolute.p-1 > span > 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 bottomMenu = document.querySelector('div > nav > div.border-t.border-white\\/20.pt-2');
- let sendTextFileButton = createElement(`<a href="#" class="flex py-3 px-3 items-center gap-3 rounded-md hover:bg-gray-500/10 transition-colors duration-200 text-white cursor-pointer text-sm"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg>Send text file</a>`);
- sendTextFileButton.addEventListener('click', sendTextFile);
- bottomMenu.prepend(sendTextFileButton);
- let loadTextFileButton = createElement(`<a href="#" class="flex py-3 px-3 items-center gap-3 rounded-md hover:bg-gray-500/10 transition-colors duration-200 text-white cursor-pointer text-sm"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg><span id="load-text-file">Load text file (${localStorage.buffer.length})</span></a>`);
- loadTextFileButton.addEventListener('mousedown', async(event) => {
- localStorage.buffer = event.button === 0 ? await getText() : await navigator.clipboard.readText();
- updateLoadTextFileSpan();
- });
- loadTextFileButton.addEventListener('contextmenu', event => {
- event.preventDefault();
- event.stopPropagation();
- });
- bottomMenu.prepend(loadTextFileButton);
- } catch (e) {}
- finally {
- isUIProcessing = false;
- }
- }
- }, 100);
- })();