您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
A toggleable panel with the swipes of the current turn
- // ==UserScript==
- // @name c.ai X Swipes
- // @namespace c.ai X Swipes
- // @version 2.1
- // @description A toggleable panel with the swipes of the current turn
- // @author Vishanka via chatGPT
- // @license MIT
- // @match https://*.character.ai/chat*
- // @icon https://i.imgur.com/iH2r80g.png
- // @grant none
- // ==/UserScript==
- (function() {
- 'use strict';
- var original_prototype_open = XMLHttpRequest.prototype.open;
- const intercepted_data_object_swipes = {};
- XMLHttpRequest.prototype.open = function(method, url, async) {
- if (
- url.startsWith('https://plus.character.ai/chat/history/continue/') ||
- url.startsWith('https://plus.character.ai/chat/character/info') ||
- url.startsWith('https://beta.character.ai/chat/history/continue/') ||
- url.startsWith('https://beta.character.ai/chat/character/info')
- ) {
- this.addEventListener('load', function() {
- let info1_swipes = JSON.parse(this.responseText);
- intercepted_data_object_swipes.external_id = info1_swipes.character.external_id;
- intercepted_data_object_swipes.name = info1_swipes.character.name;
- console.log("character_id:",intercepted_data_object_swipes.external_id);
- // Only create the toggle button and the panel once
- if (!document.getElementById('NeoPanelSwipes')) {
- createToggleButton_NeoPanelSwipes();
- createNeoPanelSwipes();
- }
- });
- } else if (url.startsWith(`https://neo.character.ai/chats/recent/${intercepted_data_object_swipes.external_id}`)) {
- this.addEventListener('load', function() {
- let info2_swipes = JSON.parse(this.responseText);
- intercepted_data_object_swipes.chat_id = info2_swipes.chats[0].chat_id;
- console.log("chat_id:",intercepted_data_object_swipes.chat_id);
- });
- } else if (url.startsWith(`https://neo.character.ai/turns/${intercepted_data_object_swipes.chat_id}`)) {
- this.addEventListener('load', function() {
- let info3_swipes = JSON.parse(this.responseText);
- intercepted_data_object_swipes.turn_id = info3_swipes.turns[0].turn_key.turn_id;
- intercepted_data_object_swipes.total_turns = info3_swipes.turns.length;
- console.log("turn_id:",intercepted_data_object_swipes.turn_id);
- console.log("total_turns:", intercepted_data_object_swipes.total_turns);
- // Extract data from the last turn_id if there are turns
- if (intercepted_data_object_swipes.total_turns > 0) {
- const lastTurnIndex = intercepted_data_object_swipes.total_turns - 1;
- const lastTurnData = info3_swipes.turns[lastTurnIndex];
- intercepted_data_object_swipes.lastTurnId = lastTurnData.turn_key.turn_id; // Store lastTurnId in intercepted_data_object_swipes
- console.log("Last turn_id:", intercepted_data_object_swipes.lastTurnId);
- }
- // Extract candidates for "turn 0", used for fetching limit
- if (intercepted_data_object_swipes.total_turns > 0) {
- const firstTurnData = info3_swipes.turns[0];
- intercepted_data_object_swipes.candidatesForTurn0 = firstTurnData.candidates;
- intercepted_data_object_swipes.numberOfCandidatesForTurn0 = intercepted_data_object_swipes.candidatesForTurn0.length;
- console.log("Number of candidates for turn 0:", intercepted_data_object_swipes.numberOfCandidatesForTurn0);
- intercepted_data_object_swipes.rawContents = intercepted_data_object_swipes.candidatesForTurn0.map(candidate => candidate.raw_content);
- console.log("Raw contents of candidates for turn 0:", intercepted_data_object_swipes.rawContents);
- // All Styles and Functions of the List Elements
- const swipes = document.createElement('div');
- swipes.style.textAlign = 'left';
- swipes.style.marginTop = '15px';
- swipes.style.overflowWrap = 'break-word';
- swipes.style.whiteSpace = 'pre-wrap';
- swipes.style.maxHeight = 'calc(100% - 12px)'; // Adjust the value as needed
- swipes.style.overflowY = 'auto';
- swipes.style.marginLeft = '-10px';
- swipes.style.scrollbarWidth = '1px';
- //swipes.style.scrollbarColor = 'transparent transparent';
- if (intercepted_data_object_swipes.rawContents) {
- intercepted_data_object_swipes.rawContents.forEach((content, index) => {
- const contentContainer = document.createElement('div'); // Create a container for each content
- contentContainer.style.display = 'flex'; // Use flex layout
- contentContainer.style.alignItems = 'center'; // Center-align vertically
- contentContainer.style.marginBottom = '15px'; // Add some spacing between elements
- contentContainer.style.marginTop = '15px';
- contentContainer.style.direction = 'ltr';
- let isGreen = false; // Flag to track the background color state
- const candidateNumber = index + 1; // Adding 1 to index to make it 1-based
- const numberElement = document.createElement('span'); // Create element for candidate number
- numberElement.textContent = `${candidateNumber}.`;
- numberElement.style.marginRight = '15px'; // Add spacing between number and text
- numberElement.style.direction = 'ltr';
- numberElement.style.marginLeft = '10px';
- // numberElement.style.alignItems = 'center';
- numberElement.style.marginBottom = '15px'
- const contentElement = document.createElement('div'); // Create element for content
- contentElement.innerHTML = content;
- contentElement.style.direction = 'ltr';
- contentElement.style.color = '#878788';
- // Changes the color of the text
- const formattedContent = content.replace(/(["“”«»].*?["“”«»])/g, '<span style="color: #FFFFFF">$1</span>');
- const finalContent1 = formattedContent.replace(/\*\*(.*?)\*\*/g, '<span style="font-weight: bold;">$1</span>');
- const finalContent = finalContent1.replace(/\*(.*?)\*/g, '<span style="font-style: italic; color: #E0DF7F;">$1</span>');
- // Use regular expressions to find text within backticks and apply formatting
- const formattedBackticks_3 = finalContent.replace(/```([^`]*)```/g, '<div style="display: inline-block; margin: 0px 10px; vertical-align: middle;"><div style="color: white; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; text-align: left; white-space: pre; word-spacing: normal; word-break: normal; overflow-wrap: normal; line-height: 1.5; font-size: 13px; tab-size: 4; hyphens: none; padding: 5px; margin: 0px; overflow: auto; background: rgb(1, 22, 39);"><code style="color: rgb(214, 222, 235); font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; text-align: left; white-space: pre-wrap; word-spacing: normal; word-break: normal; overflow-wrap: normal; line-height: 1.5; font-size: 1em; tab-size: 4; hyphens: none;">$1</code></div></div>');
- const formattedBackticks_tilde = formattedBackticks_3.replace(/~~~([^`]*)~~~/g, '<div style="display: inline-block; margin: 0px 10px; vertical-align: middle;"><div style="color: white; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; text-align: left; white-space: pre; word-spacing: normal; word-break: normal; overflow-wrap: normal; line-height: 1.5; font-size: 13px; tab-size: 4; hyphens: none; padding: 5px; margin: 0px; overflow: auto; background: rgb(1, 22, 39);"><code style="color: rgb(214, 222, 235); font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; text-align: left; white-space: pre-wrap; word-spacing: normal; word-break: normal; overflow-wrap: normal; line-height: 1.5; font-size: 1em; tab-size: 4; hyphens: none;">$1</code></div></div>');
- const formattedBackticks_1 = formattedBackticks_tilde.replace(/`(?!`)(.*?)`/g, '<div style="display: inline-block; margin: 0px 10px; vertical-align: middle;"><div style="color: white; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; text-align: left; white-space: pre; word-spacing: normal; word-break: normal; overflow-wrap: normal; line-height: 1.5; font-size: 13px; tab-size: 4; hyphens: none; padding: 5px; margin: 0px; overflow: auto; background: rgb(1, 22, 39);"><code style="color: rgb(214, 222, 235); font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; text-align: left; white-space: pre-wrap; word-spacing: normal; word-break: normal; overflow-wrap: normal; line-height: 1.5; font-size: 1em; tab-size: 4; hyphens: none;">$1</code></div></div>');
- // Set the final formatted content as innerHTML
- contentElement.innerHTML = formattedBackticks_1;
- contentContainer.appendChild(numberElement); // Append number element to container
- contentContainer.appendChild(contentElement); // Append content element to container
- contentContainer.addEventListener('click', (event) => {
- if (event.button === 0) {
- simulateArrowKeyPress(candidateNumber); // Call the function to simulate arrow key press
- }
- });
- contentContainer.addEventListener('dblclick', (event) => {
- if (isGreen) {
- contentContainer.style.backgroundColor = ''; // Reset to default color
- } else {
- contentContainer.style.backgroundColor = 'green';
- }
- isGreen = !isGreen; // Toggle the flag
- });
- swipes.appendChild(contentContainer); // Append the container to the swipes
- // Add a horizontal line after each content (except for the last one)
- if (index < intercepted_data_object_swipes.rawContents.length - 1) {
- const divider = document.createElement('hr');
- swipes.appendChild(divider);
- }
- });
- } else {
- const errorMessage = document.createElement('p');
- errorMessage.textContent = "No raw contents available.";
- swipes.appendChild(errorMessage);
- }
- // Function to simulate ArrowRight key press
- function simulateArrowKeyPress(steps) {
- for (let step = 0; step < 50; step++) {
- ArrowLeftKeyDown();
- }
- for (let step = 0; step < steps - 1; step++) {
- ArrowRightKeyDown();
- }
- }
- // Your existing ArrowRightKeyDown function
- function ArrowRightKeyDown() {
- document.body.dispatchEvent(
- new KeyboardEvent('keydown', {
- bubbles: true,
- key: 'ArrowRight',
- })
- );
- console.log("Arrow right pressed");
- }
- // Your existing ArrowLeftKeyDown function
- function ArrowLeftKeyDown() {
- document.body.dispatchEvent(
- new KeyboardEvent('keydown', {
- bubbles: true,
- key: 'ArrowLeft',
- })
- );
- console.log("Arrow left pressed");
- }
- NeoPanelSwipes.appendChild(swipes);
- }
- XHR_interception_resolve(intercepted_data_object_swipes);
- });
- }
- original_prototype_open.apply(this, [method, url, async]);
- };
- let XHR_interception_resolve;
- const XHR_interception_promise = new Promise(function(resolve, reject) {
- XHR_interception_resolve = resolve;
- });
- XHR_interception_promise.then(function() {
- console.log("Intercepted Data:", intercepted_data_object_swipes);
- });
- function createToggleButton_NeoPanelSwipes() {
- const toggleButton_NeoPanelSwipes = document.createElement('button');
- toggleButton_NeoPanelSwipes.innerHTML = '<svg transform="rotate(90)" stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 16 16" height="22" width="22" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M11.854 3.646a.5.5 0 0 1 0 .708L8.207 8l3.647 3.646a.5.5 0 0 1-.708.708l-4-4a.5.5 0 0 1 0-.708l4-4a.5.5 0 0 1 .708 0zM4.5 1a.5.5 0 0 0-.5.5v13a.5.5 0 0 0 1 0v-13a.5.5 0 0 0-.5-.5z"></path></svg>';
- toggleButton_NeoPanelSwipes.style.position = 'fixed';
- toggleButton_NeoPanelSwipes.style.bottom = '0px';
- toggleButton_NeoPanelSwipes.style.right = '3px';
- toggleButton_NeoPanelSwipes.style.backgroundColor = 'none';
- toggleButton_NeoPanelSwipes.style.color = 'white';
- toggleButton_NeoPanelSwipes.style.fontWeight = 'bold';
- toggleButton_NeoPanelSwipes.style.padding = '0px';
- toggleButton_NeoPanelSwipes.style.margin = '0px';
- // toggleButton_NeoPanelSwipes.style.width = '5%';
- toggleButton_NeoPanelSwipes.style.border = 'none';
- toggleButton_NeoPanelSwipes.style.borderRadius = '0px';
- toggleButton_NeoPanelSwipes.style.cursor = 'pointer';
- toggleButton_NeoPanelSwipes.style.userSelect = 'none';
- toggleButton_NeoPanelSwipes.style.zIndex = '101';
- toggleButton_NeoPanelSwipes.addEventListener('click', toggleNeoPanelSwipes);
- document.body.appendChild(toggleButton_NeoPanelSwipes);
- }
- function createNeoPanelSwipes() {
- const NeoPanelSwipes = document.createElement('div');
- NeoPanelSwipes.id = 'NeoPanelSwipes';
- NeoPanelSwipes.style.position = 'fixed';
- NeoPanelSwipes.style.bottom = '0px';
- NeoPanelSwipes.style.right = '0%';
- NeoPanelSwipes.style.width = '351px';
- NeoPanelSwipes.style.height = '100%';
- NeoPanelSwipes.style.backgroundColor = '#18181B';
- NeoPanelSwipes.style.borderLeft = '0.3px solid #3F3F46';
- NeoPanelSwipes.style.padding = '10px';
- NeoPanelSwipes.style.zIndex = '100';
- NeoPanelSwipes.style.resize = 'horizontal';
- NeoPanelSwipes.style.direction = 'rtl';
- NeoPanelSwipes.style.overflowX = 'auto';
- NeoPanelSwipes.style.overflowY = 'hidden';
- NeoPanelSwipes.style.display = 'none';
- NeoPanelSwipes.style.paddingBottom = '70px';
- const otherElement = document.querySelector('.w-\\[786px\\]');
- if (otherElement) {
- // Get the computed style of the other element
- const otherElementStyle = window.getComputedStyle(otherElement);
- // Extract the width property from the computed style
- const otherElementWidth = parseFloat(otherElementStyle.width);
- // Set the width of NeoPanelSwipes to match the other element
- NeoPanelSwipes.style.width = otherElementWidth/1.734 + 'px';
- }
- // Add Swipes header to the panel
- const swipes_headline = document.createElement('h5');
- swipes_headline.textContent = 'Swipes';
- swipes_headline.style.marginTop = '5px';
- swipes_headline.style.marginBottom = '15px';
- swipes_headline.style.textAlign = 'center';
- NeoPanelSwipes.appendChild(swipes_headline);
- // Add a horizontal line (divider)
- const divider_swipes1 = document.createElement('hr');
- NeoPanelSwipes.appendChild(divider_swipes1);
- document.body.appendChild(NeoPanelSwipes);
- }
- function toggleNeoPanelSwipes() {
- const NeoPanelSwipes = document.getElementById('NeoPanelSwipes');
- if (NeoPanelSwipes.style.display === 'block') {
- NeoPanelSwipes.style.display = 'none';
- } else {
- NeoPanelSwipes.style.display = 'block';
- }
- }
- })();