c.ai X Panel

Adds a Description and an Autoscroll Button

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(Tôi đã có Trình quản lý tập lệnh người dùng, hãy cài đặt nó!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         c.ai X Panel
// @namespace    c.ai X Panel
// @version      0.4
// @description  Adds a Description and an Autoscroll Button
// @author       Vishanka
// @license     MIT
// @match        https://character.ai/*
// @grant        none
// @icon        https://i.imgur.com/ynjBqKW.png
// ==/UserScript==


(function() {
    'use strict';

    var Description_ToggleButton;
    var DescriptionTextContainer;

    function addDescriptionButton() {
        var parentElement = document.querySelector('div.flex:nth-child(5)');
        if (!parentElement) {
            parentElement = document.querySelector('div.flex:nth-child(4)');
        }

if (parentElement) {
    Description_ToggleButton = document.createElement('button');
    Description_ToggleButton.id = 'Description_ToggleButton';
    Description_ToggleButton.style.display = 'flex';
    Description_ToggleButton.style.alignItems = 'center';
    Description_ToggleButton.style.textAlign = 'left';
    Description_ToggleButton.style.paddingLeft = '17px';
    Description_ToggleButton.style.fontSize = '14px';
    Description_ToggleButton.style.width = '287px';
    Description_ToggleButton.style.height = '40px';
    Description_ToggleButton.style.borderRadius = '8px';

// Mouseover event with softer animation
    Description_ToggleButton.addEventListener('mouseover', function() {
      Description_ToggleButton.style.transition = 'background-color 0.3s ease';
      Description_ToggleButton.style.backgroundColor = '#1F1F23';
    });
    Description_ToggleButton.addEventListener('mouseout', function() {
      Description_ToggleButton.style.transition = 'background-color 0.3s ease';
      Description_ToggleButton.style.backgroundColor = '';
    });

// Create a divider
var DescriptionDivider = document.createElement('div');
DescriptionDivider.style.height = '1px'; // Thin line
DescriptionDivider.style.width = '100%'; // Full width
DescriptionDivider.style.backgroundColor = '#3A3A3D';
DescriptionDivider.style.margin = '0px 0'; // Margin above and below for spacing

// Add the divider to the parent element before the button
parentElement.appendChild(DescriptionDivider);

    var DescriptionImage = document.createElement('img');
    DescriptionImage.src = 'https://i.imgur.com/1DnLhLG.png';
    DescriptionImage.style.marginRight = '12px';
    DescriptionImage.style.width = '18px';
    DescriptionImage.style.height = '18px';
    DescriptionImage.style.display = 'block';
    DescriptionImage.style.flexShrink = 0;

    // Wrap both button text and image in a div
    var DescriptionAndImagecontentWrapper = document.createElement('div');
    DescriptionAndImagecontentWrapper.style.display = 'flex';
    DescriptionAndImagecontentWrapper.style.alignItems = 'center';
    DescriptionAndImagecontentWrapper.appendChild(DescriptionImage);
    DescriptionAndImagecontentWrapper.appendChild(document.createTextNode('Description'));

    Description_ToggleButton.appendChild(DescriptionAndImagecontentWrapper);

    parentElement.appendChild(Description_ToggleButton);
    console.log("Button added successfully.");



            DescriptionTextContainer = document.createElement('div');
            DescriptionTextContainer.style.wordWrap = 'break-word';
            DescriptionTextContainer.style.overflowWrap = 'break-word';
            DescriptionTextContainer.style.maxWidth = '100%';
            DescriptionTextContainer.style.display = 'none';
            DescriptionTextContainer.style.fontSize = '15px';
            DescriptionTextContainer.style.hyphens = 'auto';
            DescriptionTextContainer.style.color = '#a2a2ac';
            parentElement.appendChild(DescriptionTextContainer);

            // Add event listener for button click
            Description_ToggleButton.addEventListener('click', function() {
                var currentURL = document.location.href;
                var afterChat = currentURL.substring(currentURL.indexOf('https://character.ai/chat/') + 'https://character.ai/chat/'.length);
                var currentURL1 = afterChat.split('?hist')[0];
                var description = sessionStorage.getItem(currentURL1 + '_description');
                console.log("currentURL1:", currentURL1);

                if (DescriptionTextContainer.style.display === 'none') {
                    DescriptionTextContainer.innerHTML = description;
                    DescriptionTextContainer.style.display = 'block';
                } else {
                    DescriptionTextContainer.innerHTML = '';
                    DescriptionTextContainer.style.display = 'none';
                }
            });


    let intervalId;
    let autoPressEnabled = false;

    function ArrowRightKeyDown() {
        document.body.dispatchEvent(
            new KeyboardEvent('keydown', {
                bubbles: true,
                key: 'ArrowRight',
            })
        );
        console.log("Arrow right pressed");
    }

function toggleAutoPress() {
    autoPressEnabled = !autoPressEnabled;
    if (autoPressEnabled) {
        // Trigger 30 key presses to the right at once
        for (let i = 0; i < 30; i++) {
            ArrowRightKeyDown();
        }
        intervalId = setInterval(ArrowRightKeyDown, 1000); // Repeat every 1 second
autoscrollButton.innerHTML = '<span style="color: #A2A2AC; margin-left: 5px; margin-right: 13px;">■</span> Stop Autoscroll';


    } else {
        clearInterval(intervalId);
autoscrollButton.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="28" viewBox="0 0 16 32" fill="none" class="h-full" style="margin-right: 10px;"><path d="M9.59998 19.1998L12.8 15.9998L9.59998 12.7998" stroke="#A2A2AC" stroke-width="1.28" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3.59998 19.1998L6.79998 15.9998L3.59998 12.7998" stroke="#A2A2AC" stroke-width="1.28" stroke-linecap="round" stroke-linejoin="round"></path></svg> Start Autoscroll';
    }
}


var autoscrollButton = document.createElement('button');
autoscrollButton.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="28" viewBox="0 0 16 32" fill="none" class="h-full" style="margin-right: 10px;"><path d="M9.59998 19.1998L12.8 15.9998L9.59998 12.7998" stroke="#A2A2AC" stroke-width="1.28" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3.59998 19.1998L6.79998 15.9998L3.59998 12.7998" stroke="#A2A2AC" stroke-width="1.28" stroke-linecap="round" stroke-linejoin="round"></path></svg> Start Autoscroll';
autoscrollButton.style.display = 'flex';
autoscrollButton.style.alignItems = 'center';
autoscrollButton.style.textAlign = 'left';
autoscrollButton.style.paddingLeft = '17px';
autoscrollButton.style.fontSize = '14px';
autoscrollButton.style.width = '287px'; //
autoscrollButton.style.height = '40px'; //
autoscrollButton.style.borderRadius = '8px';
autoscrollButton.addEventListener('click', toggleAutoPress);

// Mouseover event with softer animation
autoscrollButton.addEventListener('mouseover', function() {
    autoscrollButton.style.transition = 'background-color 0.3s ease';
    autoscrollButton.style.backgroundColor = '#1F1F23';
});
autoscrollButton.addEventListener('mouseout', function() {
    autoscrollButton.style.transition = 'background-color 0.3s ease';
    autoscrollButton.style.backgroundColor = '';
});


parentElement.appendChild(autoscrollButton);


        } else {
            console.log("Parent element not found.");
        }
    }


function fetchDescription() {
    const originalOpen = XMLHttpRequest.prototype.open; // Use const for unchanged values
    const interceptedData = {}; // Single object for all intercepted data

    XMLHttpRequest.prototype.open = function(method, url, async) {
        if (url.startsWith('https://plus.character.ai/chat/character/info') ||
            url.startsWith('https://beta.character.ai/chat/character/info')) {
            this.addEventListener('load', () => {
                if (this.status >= 200 && this.status < 300) {
                    try {
                        const response = JSON.parse(this.responseText);
                        if (response && response.character) {
                            const { description, external_id } = response.character;
                            if (description !== undefined) {
                                interceptedData[external_id] = { description };
                                console.log(`NextDescription: ${description}`);
                                console.log(`ExternalID: ${external_id}`);

                                sessionStorage.setItem(`${external_id}_description`, description);
                            } else {
                                console.error("Invalid or empty description field in response");
                            }
                        }
                    } catch (error) {
                        console.error(`Error parsing JSON response: ${error}`);
                    }
                } else {
                    console.error(`Request failed with status: ${this.status}`);
                }
            });
        }
        originalOpen.apply(this, arguments); // Preserve the context of `this`
    };
}

fetchDescription();




// HERE ARE THE FUNCTIONS THAT MAKE SURE THAT THE BUTTON IS ADDED
function addButtonsWithRetry() {
    // Only run on specific pages
    if (!/https:\/\/character\.ai\/chat\//.test(window.location.href)) {
        return;
    }

    var attempts = 0;
    var maxAttempts = 10;
    var interval = setInterval(function() {
        if (!document.getElementById('Description_ToggleButton')) {
            addDescriptionButton(); // Ensure this function is defined elsewhere in your code
            attempts++;
        }
        if (document.getElementById('Description_ToggleButton') || attempts >= maxAttempts) {
            clearInterval(interval); // Stop retrying if button is added or max attempts reached
        }
    }, 1000); // Retry every second
}

addButtonsWithRetry();

// Check for URL changes
var currentUrl = window.location.href;
setInterval(function() {
    if (window.location.href !== currentUrl) {
        console.log("URL changed, checking for button...");
        currentUrl = window.location.href;
        addButtonsWithRetry(); // Reapply the button if URL changes
    }
}, 1000);


})();