您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a save and download button with a format dropdown to Character.AI, hides edited tags, auto-clicks "Try Again," and enables widescreen mode.
当前为
// ==UserScript== // @name Chat Enhancements // @namespace http://tampermonkey.net/ // @version 0.4 // @description Adds a save and download button with a format dropdown to Character.AI, hides edited tags, auto-clicks "Try Again," and enables widescreen mode. // @author InariOkami // @match https://character.ai/* // @grant none // @icon https://www.google.com/s2/favicons?sz=64&domain=character.ai // ==/UserScript== (async function() { 'use strict'; (function() { function loop() { let elements = document.querySelectorAll("div, p"); elements.forEach(function(val) { if (val.innerText === "(edited)" || val.innerText === "Edited") { val.style.display = 'none'; } }); requestAnimationFrame(loop); } loop(); })(); (function() { let counter = 0; var interval = setInterval(function() { var toastify = document.querySelectorAll('[role="alert"]'); if (toastify.length > 0) { for (var i = 0; i < toastify.length; i++) { if (toastify[i].innerHTML.indexOf("Try Again") !== -1) { toastify[i].querySelector(".btn-primary").click(); counter++; console.log('Auto-clicked %s times', counter); break; } } } }, 50); })(); (function() { function WideScreen() { if (document.URL.startsWith("https://old.character.ai/chat")) { if (document.URL.includes("/chat2") || document.URL.includes("/chat")) { document.body.getElementsByClassName("apppage").item(0).firstElementChild.attributes.style.value = "height: 100%; display: flex; flex-direction: column; overflow-y: hidden; min-width: 300px; max-width: 7680; margin: 0px auto;"; document.getElementsByClassName("container-fluid chatbottom").item(0).attributes.item(1).value = "max-width: 7680;"; } if (document.URL.includes("/chat")) { document.getElementsByClassName("container-fluid chattop").item(0).attributes.item(1).value = "max-width: 7680;"; } } if (document.URL.startsWith("https://character.ai/chat")) { var Chat = document.getElementsByClassName("overflow-x-hidden overflow-y-scroll px-1 flex flex-col-reverse min-w-full hide-scrollbar").item(0).children; for (var i = 0; i < Chat.length; i++) { Chat.item(i).style = "min-width:100%"; document.getElementsByClassName("flex w-full flex-col max-w-2xl").item(0).style = "min-width:100%"; } } } setTimeout(() => { setInterval(WideScreen, 100); }, 1000); })(); function createSaveButton() { const saveChatButton = document.createElement('button'); saveChatButton.innerHTML = 'Chat Options ▼'; saveChatButton.style.position = 'fixed'; saveChatButton.style.top = localStorage.getItem('buttonTop') || '10px'; saveChatButton.style.left = localStorage.getItem('buttonLeft') || '10px'; saveChatButton.style.backgroundColor = '#ff0000'; saveChatButton.style.color = '#ffffff'; saveChatButton.style.padding = '10px'; saveChatButton.style.borderRadius = '5px'; saveChatButton.style.cursor = 'pointer'; saveChatButton.style.zIndex = '1000'; saveChatButton.style.border = 'none'; saveChatButton.style.boxShadow = '0px 2px 5px rgba(0,0,0,0.2)'; document.body.appendChild(saveChatButton); const dropdown = document.createElement('div'); dropdown.style.display = 'none'; dropdown.style.position = 'absolute'; dropdown.style.top = '100%'; dropdown.style.left = '0'; dropdown.style.backgroundColor = '#333'; dropdown.style.border = '1px solid #ccc'; dropdown.style.boxShadow = '0px 2px 5px rgba(0,0,0,0.2)'; dropdown.style.zIndex = '1001'; dropdown.style.color = '#ffffff'; dropdown.style.fontFamily = 'sans-serif'; dropdown.style.fontSize = '14px'; dropdown.style.padding = '5px'; saveChatButton.appendChild(dropdown); const saveButton = document.createElement('button'); saveButton.innerHTML = 'Save Chat'; saveButton.style.display = 'block'; saveButton.style.width = '100%'; saveButton.style.border = 'none'; saveButton.style.padding = '10px'; saveButton.style.cursor = 'pointer'; saveButton.style.backgroundColor = '#444'; saveButton.style.color = '#ffffff'; // White text saveButton.onclick = saveChat; dropdown.appendChild(saveButton); const downloadButton = document.createElement('button'); downloadButton.innerHTML = 'Download Chat'; downloadButton.style.display = 'block'; downloadButton.style.width = '100%'; downloadButton.style.border = 'none'; downloadButton.style.padding = '10px'; downloadButton.style.cursor = 'pointer'; downloadButton.style.backgroundColor = '#444'; downloadButton.style.color = '#ffffff'; // White text downloadButton.onclick = async function() { let format = prompt('Enter format (definition/names):', 'definition'); if (format === 'definition' || format === 'names') { await saveAndDownloadChat(format); } else { alert('Invalid format. Please enter "definition" or "names".'); } }; dropdown.appendChild(downloadButton); return { saveChatButton, dropdown }; } function toggleDropdown(dropdown) { dropdown.style.display = dropdown.style.display === 'none' ? 'block' : 'none'; } function makeDraggable(saveChatButton) { saveChatButton.onmousedown = function(event) { event.preventDefault(); let shiftX = event.clientX - saveChatButton.getBoundingClientRect().left; let shiftY = event.clientY - saveChatButton.getBoundingClientRect().top; document.onmousemove = function(e) { saveChatButton.style.left = (e.clientX - shiftX) + 'px'; saveChatButton.style.top = (e.clientY - shiftY) + 'px'; }; document.onmouseup = function() { localStorage.setItem('buttonTop', saveChatButton.style.top); localStorage.setItem('buttonLeft', saveChatButton.style.left); document.onmousemove = null; document.onmouseup = null; }; }; } function updateStyles(saveChatButton) { const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches; saveChatButton.style.backgroundColor = isDarkMode ? '#333' : '#ff0000'; saveChatButton.style.color = isDarkMode ? '#fff' : '#ffffff'; } var cai_version = -1; if (location.hostname === "old.character.ai") cai_version = 1; else if (location.pathname.startsWith("/chat/")) cai_version = 2; else return alert("Unsupported character.ai version"); var token; if (cai_version === 1) token = JSON.parse(localStorage['char_token']).value; else if (cai_version === 2) token = JSON.parse(document.getElementById("__NEXT_DATA__").innerHTML).props.pageProps.token; async function _fetchchats(charid) { let url = 'https://neo.character.ai/chats/recent/' + charid; let response = await fetch(url, { headers: { "Authorization": `Token ${token}` } }); let json = await response.json(); return json['chats']; } async function getChats(charid) { let json = await _fetchchats(charid); return json.map(chat => chat.chat_id); } async function getMessages(chat, format) { let url = 'https://neo.character.ai/turns/' + chat + '/'; let next_token = null; let turns = []; do { let url2 = url; if (next_token) url2 += "?next_token=" + encodeURIComponent(next_token); let response = await fetch(url2, { headers: { "Authorization": `Token ${token}` } }); let json = await response.json(); turns = turns.concat(json['turns']); next_token = json['next_token']; } while (next_token); return turns.map(turn => format === 'names' ? `User: ${turn['text']}\nBot: ${turn['response']}` : `${JSON.stringify(turn, null, 4)}`); } async function saveChat() { let charid = prompt('Enter character ID:'); let chats = await getChats(charid); let messages = await getMessages(chats[0], 'definition'); alert(messages.join("\n\n")); } async function saveAndDownloadChat(format) { let charid = prompt('Enter character ID:'); let chats = await getChats(charid); let messages = await getMessages(chats[0], format); let filename = `chatlog_${charid}.txt`; let blob = new Blob([messages.join("\n\n")], { type: 'text/plain' }); let link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = filename; document.body.appendChild(link); link.click(); document.body.removeChild(link); } let { saveChatButton, dropdown } = createSaveButton(); saveChatButton.onclick = function() { toggleDropdown(dropdown); }; makeDraggable(saveChatButton); updateStyles(saveChatButton); })();