SaveAI LMSYS & Arena to HTML

Zapisuje rozmowę w porządku chronologicznym (od najstarszej do najnowszej).

// ==UserScript==
// @name         SaveAI LMSYS & Arena to HTML
// @namespace    http://tampermonkey.net/
// @version      5.0 (Porządek Chronologiczny)
// @description  Zapisuje rozmowę w porządku chronologicznym (od najstarszej do najnowszej).
// @author       AI gemini-2.5-pro
// @match        https://chat.lmsys.org/
// @match        https://lmarena.ai/*
// @grant        none
// @license      MIT
// ==/UserScript==


(function() {
    'use strict';

    const BUTTON_ID = 'save-chat-button-lmsys-50'; // Unikalne ID dla nowej wersji

    function addButton() {
        if (document.getElementById(BUTTON_ID)) return;
        const saveButton = document.createElement('button');
        saveButton.id = BUTTON_ID;
        saveButton.textContent = 'Zapisz Czat';
        Object.assign(saveButton.style, {
            position: 'fixed', bottom: '80px', right: '15px', zIndex: '9999', padding: '10px 15px',
            backgroundColor: '#19c37d', color: 'white', border: 'none', borderRadius: '5px',
            cursor: 'pointer', boxShadow: '0 2px 5px rgba(0,0,0,0.2)', fontSize: '14px', fontFamily: 'sans-serif'
        });
        saveButton.addEventListener('click', saveChatToFile);
        document.body.appendChild(saveButton);
    }

    function saveChatToFile() {
        let conversationHtml = '';

        // Zbieramy WSZYSTKIE kontenery z wiadomościami
        const allMessageContainers = document.querySelectorAll('.prose');

        if (allMessageContainers.length === 0) {
            alert('Nie znaleziono żadnych wiadomości do zapisania.');
            return;
        }

        // ---  KLUCZOWA ZMIANA TUTAJ  ---
        // Konwertujemy NodeList na prawdziwą tablicę (Array) i odwracamy jej kolejność.
        const reversedMessageContainers = Array.from(allMessageContainers).reverse();

        // Teraz iterujemy po ODWRÓCONEJ tablicy.
        reversedMessageContainers.forEach(proseBlock => {

            // Logika rozpoznawania mówcy pozostaje bez zmian
            const parentContainer = proseBlock.closest('.relative.flex-1.min-w-0, .flex.flex-col.gap-4');
            const modelNameElement = parentContainer ? parentContainer.querySelector('p.text-xs.font-mono') : null;

            if (modelNameElement) {
                conversationHtml += `<h3 class="model-header">Model: ${modelNameElement.textContent.trim()}</h3>\n`;
            }

            const contentClone = proseBlock.cloneNode(true);
            const styledElements = contentClone.querySelectorAll('[style]');
            styledElements.forEach(el => el.removeAttribute('style'));

            conversationHtml += contentClone.innerHTML + '<hr>\n';
        });

        const fullHtml = `
            <!DOCTYPE html><html lang="pl"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Zapisana konwersacja</title><style>
            body { font-family: sans-serif; line-height: 1.6; max-width: 900px; margin: 40px auto; padding: 20px; color: #333; }
            hr { border: 0; border-top: 1px solid #eee; margin: 2em 0; }
            pre { background-color: #f4f4f4; padding: 15px; border-radius: 5px; border: 1px solid #ddd; white-space: pre-wrap; word-wrap: break-word; }
            code { font-family: "Consolas", "Courier New", monospace; font-style: normal; }
            .model-header {
                font-size: 1em; color: #2c5282; font-weight: bold; margin-top: 2em; margin-bottom: 0.5em;
            }
            </style></head><body><h1>Konwersacja z LMSYS Arena</h1><p><i>Zapisano: ${new Date().toLocaleString('pl-PL')}</i></p><hr>${conversationHtml}</body></html>`;

        const blob = new Blob([fullHtml], { type: 'text/html' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.download = `lmsys_chat_${new Date().toISOString().slice(0, 10)}.html`;
        a.href = url;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
    }

    setInterval(() => {
        if (!document.getElementById(BUTTON_ID)) {
            // Użyjmy bardziej uniwersalnego selektora, który działa na obu stronach
            if (document.querySelector('textarea')) {
                 addButton();
            }
        }
    }, 1000);

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址