// ==UserScript==
// @name         OverlayConsole
// @version      1.0
// @description  Toggle a console overlay on any webpage
// @match        *://yuntian-deng-chatgpt4.hf.space/*
// @grant        GM_addStyle
// ==/UserScript==

(function () {
    'use strict';

    let consoleOpen = false;
    const consoleDiv = document.createElement('div');

    // Set up the console overlay style
    consoleDiv.id = 'consoleOverlay';
    consoleDiv.style.cssText = `
        position: fixed; bottom: 0; left: 0;
        width: 100%; height: 200px; color: white; background: rgba(0, 0, 0, 0.9);
        overflow-y: auto; z-index: 9999; display: none; font-family: monospace; padding: 10px;
    `;

    const inputBox = document.createElement('input');
    inputBox.style.cssText = `
        width: calc(100% - 20px); padding: 8px; margin-top: 10px; color: white;
        background: #333; border: 1px solid #555; box-sizing: border-box;
    `;
    consoleDiv.appendChild(inputBox);

    // Append consoleDiv to body
    document.body.appendChild(consoleDiv);

    function logMessage(message) {
        const log = document.createElement('div');
        log.textContent = message;
        log.style.cssText = 'padding: 3px 0;'
        consoleDiv.insertBefore(log, inputBox);
    }

    inputBox.addEventListener('keydown', function (e) {
        if (e.key === 'Enter') {
            handleCommand(inputBox.value);
            inputBox.value = '';
        }
    });

    function handleCommand(command) {
        command = command.trim().toLowerCase();
        if (command === 'sve') {
            logMessage('Save chat history.');
        } else if (command === 'svr') {
            logMessage('Copy all chat history to clipboard.');
        } else if (command === 'svu') {
            logMessage('Copy user messages to clipboard.');
        } else if (command === 'svb') {
            logMessage('Copy bot messages to clipboard.');
        } else {
            logMessage("Unknown command: " + command);
        }
    }

    window.addEventListener('keydown', function (e) {
        if (e.key === '`' && !e.ctrlKey && !e.altKey && !e.metaKey) {
            consoleOpen = !consoleOpen;
            consoleDiv.style.display = consoleOpen ? 'block' : 'none';
            if (consoleOpen) inputBox.focus();
        }
    });

    logMessage("Console ready. Press ` to toggle.");
})();








// ==UserScript==
// @name         EnhancedChatment
// @version      9000.15
// @description  Handles Unhandlablaments
// @match        *://yuntian-deng-chatgpt4.hf.space/*
// @grant        none
// @require      https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js
// ==/UserScript==

/* global JSZip */
(function () {
    'use strict';

    const SESSION_OBSERVER_KEY = 'enhancedChat_observerArray';

    let observerArray = JSON.parse(sessionStorage.getItem(SESSION_OBSERVER_KEY)) || [];
    const DEBOUNCE_WAIT = 300;

    initializeObservers();

    function captureMessages() {
        const messageWrap = document.querySelector('.bubble-wrap.svelte-1e1jlin');

        if (!messageWrap) {
            console.error("Message wrap not found.");
            return;
        }

        const messages = Array.from(messageWrap.querySelectorAll('.message-row')).map(div => ({
            htmlContent: div.outerHTML,
            type: div.classList.contains('user-row') ? 'user' : 'bot'
        }));

        mergeNewMessagesIntoObserverArray(messages);
        storeChatHistory();
    }

    function mergeNewMessagesIntoObserverArray(newMessages) {
        newMessages.forEach(msg => {
            if (!observerArray.some(existingMsg => existingMsg.htmlContent === msg.htmlContent)) {
                observerArray.push(msg);
            }
        });
        console.log('Observer array updated:', observerArray);
    }

    function storeChatHistory() {
        sessionStorage.setItem(SESSION_OBSERVER_KEY, JSON.stringify(observerArray));
        console.clear();
        console.log('Stored Observer State:', observerArray);
    }

    function saveChatHistoryToFile() {
        if (typeof JSZip === 'undefined' || observerArray.length === 0) {
            console.error('JSZip is not loaded or chat history is empty.');
            return;
        }

        const zip = new JSZip();
        zip.file('chat_history.txt', observerArray.map(msg => extractTextFromHTML(msg.htmlContent)).join('\n'));
        zip.generateAsync({ type: 'blob' }).then(content => {
            const blobURL = URL.createObjectURL(content);
            const timestamp = new Date().toISOString().replace(/[:.]/g, '-');

            const a = document.createElement('a');
            a.href = blobURL;
            a.download = `chat_history_${timestamp}.zip`;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            console.log('ZIP file created and downloaded successfully!');
        });
    }

    function copyChatHistoryToClipboard() {
        const chatContent = observerArray.map(msg => extractTextFromHTML(msg.htmlContent)).join('\n');
        navigator.clipboard.writeText(chatContent).then(() => {
            console.log('Observer chat copied to clipboard.');
        }).catch(err => {
            console.error('Failed to copy chat history:', err);
        });
    }

    function extractTextFromHTML(htmlContent) {
        const tempDiv = document.createElement('div');
        tempDiv.innerHTML = htmlContent;
        return tempDiv.textContent;
    }

    function copySpecificMessagesToClipboard(type) {
        const filteredMessages = observerArray
            .filter(msg => msg.type === type)
            .map(msg => extractTextFromHTML(msg.htmlContent));
        const messageString = filteredMessages.join('\n');
        navigator.clipboard.writeText(messageString).then(() => {
            console.log(`Copied ${type} messages to clipboard.`);
        }).catch(err => {
            console.error(`Failed to copy ${type} messages to clipboard:`, err);
        });
    }

    function handleCommand() {
        const inputBox = document.querySelector('textarea[data-testid="textbox"]');
        if (inputBox) {
            const command = inputBox.value.trim().toLowerCase();
            switch (command) {
                case 'sve':
                    saveChatHistoryToFile();
                    break;
                case 'svr':
                    copyChatHistoryToClipboard();
                    break;
                case 'svu':
                    copySpecificMessagesToClipboard('user');
                    break;
                case 'svb':
                    copySpecificMessagesToClipboard('bot');
                    break;
                default:
                    console.log("Unknown command.");
                    break;
            }
            inputBox.value = ''; // Clear input box after handling command
        }
    }

    function initializeObservers() {
        const messageWrap = document.querySelector('.bubble-wrap.svelte-1e1jlin');

        if (messageWrap) {
            const observer = new MutationObserver(mutations => {
                mutations.forEach(mutation => {
                    if (mutation.type === "childList") {
                        captureMessagesDebounced();
                    }
                });
            });

            observer.observe(messageWrap, { childList: true, subtree: true });

            const inputBox = document.querySelector('textarea[data-testid="textbox"]');
            if (inputBox) {
                inputBox.addEventListener('input', handleCommand);
            }
        } else {
            console.error("Message wrap not found, retrying...");
            setTimeout(initializeObservers, 1000);
        }
    }

    const captureMessagesDebounced = debounce(captureMessages, DEBOUNCE_WAIT);

    function debounce(func, wait) {
        let timeout;
        return function (...args) {
            const context = this;
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(context, args), wait);
        };
    }

})();







need to enwire console into handlablaments and remove from handlablaments these manual commands through original chat input.

need independent console to not activate if focused inside original input, only outside with "`" key.