Chat History Downloader

Download chat history as txt file

Від 14.04.2024. Дивіться остання версія.

// ==UserScript==
// @name Chat History Downloader
// @namespace http://tampermonkey.net/
// @version 1.6
// @description Download chat history as txt file
// @author akira0245
// @match *://chat.lmsys.org
// @match *://arena.lmsys.org
// @icon https://chat.lmsys.org/favicon.ico
// @grant none
// @license GPLv3
// ==/UserScript==

(function() {
    'use strict';


    // 定义组件ID常量
    const COMPONENT_ID_MODEL_A = 15;
    const COMPONENT_ID_MODEL_B = 17;
    const COMPONENT_ID_MODEL_A_NAME = 20;
    const COMPONENT_ID_MODEL_B_NAME = 22;
    const COMPONENT_ID_ORIGINAL_CHAT = 90;
    const COMPONENT_ID_ORIGINAL_MODEL = 86;

    // 获取模型名称
    function getModelName(componentId) {
        return gradio_config.components.find(component => component.id === componentId).props.value;
    }

    // 获取聊天记录
    function getChatHistory(componentId) {
        const props = gradio_config.components.find(component => component.id === componentId).props;
        let chatHistory = "";

        for (let i = 0; i < props.value.length; i++) {
            const [userMessage, assistantMessage] = props.value[i];
            chatHistory += `User: \n${userMessage}\n\n------\n\nAssistant: \n${assistantMessage}\n\n------\n\n`;
        }

        return chatHistory;
    }

    // 下载聊天记录
    function downloadChatHistory(chatHistory, modelName) {
        if (chatHistory) {
            const blob = new Blob([chatHistory], { type: 'text/plain' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = `chat_history_${modelName}_${new Date().toLocaleString()}.md`;
            a.click();
            URL.revokeObjectURL(url);
        } else {
            alert('No chat history found.');
        }
    }

    // 创建下载按钮
    function createDownloadButton(componentId) {
        const downloadButton = document.createElement('button');
        downloadButton.textContent = `📥 Download Chat${componentId === COMPONENT_ID_MODEL_A ? ' A' : componentId === COMPONENT_ID_MODEL_B ? ' B' : ''}`;
        downloadButton.classList.add('lg', 'secondary', 'svelte-cmf5ev');

        // 点击下载按钮时执行下载操作
        downloadButton.addEventListener('click', function() {
            let modelName, chatHistory;
            if (componentId === COMPONENT_ID_MODEL_A || componentId === COMPONENT_ID_MODEL_B) {
                modelName = getModelName(componentId === COMPONENT_ID_MODEL_A ? COMPONENT_ID_MODEL_A_NAME : COMPONENT_ID_MODEL_B_NAME);
                chatHistory = getChatHistory(componentId);
            } else {
                modelName = getModelName(COMPONENT_ID_ORIGINAL_MODEL);
                chatHistory = getChatHistory(COMPONENT_ID_ORIGINAL_CHAT);
            }
            downloadChatHistory(chatHistory, modelName);
        });

        return downloadButton;
    }

    // 监视指定按钮的出现
    function observeTargetButton(mutationsList, observer) {
        for (let mutation of mutationsList) {
            if (mutation.type === 'childList') {
                const originalTargetButton = document.querySelector('button.lg.secondary.svelte-cmf5ev#component-100');
                const newTargetButton = document.querySelector('button.lg.secondary.svelte-cmf5ev#component-37');

                // 在原有目标按钮旁边插入下载按钮
                if (originalTargetButton) {
                    const originalDownloadButton = createDownloadButton();
                    originalTargetButton.parentNode.insertBefore(originalDownloadButton, originalTargetButton.nextSibling);
                }

                // 在新目标按钮旁边插入下载按钮
                if (newTargetButton) {
                    const downloadButtonA = createDownloadButton(COMPONENT_ID_MODEL_A);
                    const downloadButtonB = createDownloadButton(COMPONENT_ID_MODEL_B);
                    newTargetButton.parentNode.insertBefore(downloadButtonB, newTargetButton.nextSibling);
                    newTargetButton.parentNode.insertBefore(downloadButtonA, newTargetButton.nextSibling);
                }

                // 当原有目标按钮和新目标按钮都出现时,停止观察页面变化
                if (originalTargetButton && newTargetButton) {
                    observer.disconnect();
                    break;
                }
            }
        }
    }

    // 创建 MutationObserver 实例
    const observer = new MutationObserver(observeTargetButton);

    // 配置观察选项
    const config = { childList: true, subtree: true };

    // 开始观察页面变化
    observer.observe(document.body, config);
})();