LZT Article Summarizer

Утилита, которая сокращает текст темы, экономя ваше время на прочтение.

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         LZT Article Summarizer
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  Утилита, которая сокращает текст темы, экономя ваше время на прочтение.
// @author       @planetus (lolz)
// @match        https://lolz.live/threads/*
// @match        https://zelenka.guru/threads/*
// @match        https://lolz.guru/threads/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=zelenka.guru
// @license      MIT
// @grant        GM_addStyle
// @grant        GM_registerMenuCommand
// @grant        GM_setValue
// @grant        GM_getValue
// ==/UserScript==

(function() {
    'use strict';

    const defaultSettings = {
        minTextLength: 200,
        maxSummaryLength: 500,
        maxKeyPoints: 5,
        buttonColor: '#228e5d',
        summaryBgColor: '#091e15',
        summaryTextColor: '#ecf0f1',
        animationSpeed: 300,
        wordsPerMinute: 200
    };

    let settings = Object.assign({}, defaultSettings, GM_getValue('lztSummarizerSettings', {}));

    function saveSettings() {
        GM_setValue('lztSummarizerSettings', settings);
        updateStyles();
    }

    function clearSettings() {
        GM_setValue('lztSummarizerSettings', {});
        settings = Object.assign({}, defaultSettings);
        updateStyles();
    }

    function createSettingsMenu() {
        const settingsHTML = `
            <div id="lzt-settings-overlay" class="lzt-settings-overlay">
                <div id="lzt-settings" class="lzt-settings">
                    <div class="lzt-flex">
                    <h2 class="lzt-settings-title">Настройки LZT Summarizer</h2>
                    <button id="closeSettings" class="lzt-settings-button lzt-settings-close"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-dasharray="12" stroke-dashoffset="12" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.1" d="M12 12l7 7M12 12l-7 -7M12 12l-7 7M12 12l7 -7"><animate fill="freeze" attributeName="stroke-dashoffset" dur="0.6s" values="12;0"/></path></svg></button>
                    </div>
                    <div class="lzt-settings-group">
                        <label for="minTextLength">Минимальная длина текста для резюме:</label>
                        <input type="number" id="minTextLength" value="${settings.minTextLength}">
                    </div>
                    <div class="lzt-settings-group">
                        <label for="maxSummaryLength">Максимальная длина резюме:</label>
                        <input type="number" id="maxSummaryLength" value="${settings.maxSummaryLength}">
                    </div>
                    <div class="lzt-settings-group">
                        <label for="maxKeyPoints">Максимальное количество ключевых моментов:</label>
                        <input type="number" id="maxKeyPoints" value="${settings.maxKeyPoints}">
                    </div>
                    <div class="lzt-settings-group">
                        <label for="buttonColor">Цвет кнопки:</label>
                        <input type="color" id="buttonColor" value="${settings.buttonColor}">
                    </div>
                    <div class="lzt-settings-group">
                        <label for="summaryBgColor">Цвет фона резюме:</label>
                        <input type="color" id="summaryBgColor" value="${settings.summaryBgColor}">
                    </div>
                    <div class="lzt-settings-group">
                        <label for="summaryTextColor">Цвет текста резюме:</label>
                        <input type="color" id="summaryTextColor" value="${settings.summaryTextColor}">
                    </div>
                    <div class="lzt-settings-group">
                        <label for="animationSpeed">Скорость анимации (мс):</label>
                        <input type="number" id="animationSpeed" value="${settings.animationSpeed}">
                    </div>
                    <div class="lzt-settings-buttons">
                        <button id="saveSettings" class="lzt-settings-button lzt-settings-save">Сохранить</button>
                        <button id="clearSettings" class="lzt-settings-button lzt-settings-clear">Очистить всё</button>
                    </div>
                </div>
            </div>
        `;

        const settingsDiv = document.createElement('div');
        settingsDiv.innerHTML = settingsHTML;
        document.body.appendChild(settingsDiv);

        const overlay = document.getElementById('lzt-settings-overlay');
        const settingsPanel = document.getElementById('lzt-settings');

        setTimeout(() => {
            overlay.style.opacity = '1';
            settingsPanel.style.transform = 'translate(-50%, -50%) scale(1)';
        }, 50);

        document.getElementById('saveSettings').addEventListener('click', function() {
            settings.minTextLength = parseInt(document.getElementById('minTextLength').value);
            settings.maxSummaryLength = parseInt(document.getElementById('maxSummaryLength').value);
            settings.maxKeyPoints = parseInt(document.getElementById('maxKeyPoints').value);
            settings.buttonColor = document.getElementById('buttonColor').value;
            settings.summaryBgColor = document.getElementById('summaryBgColor').value;
            settings.summaryTextColor = document.getElementById('summaryTextColor').value;
            settings.animationSpeed = parseInt(document.getElementById('animationSpeed').value);
            saveSettings();
            closeSettingsMenu();
        });

        document.getElementById('clearSettings').addEventListener('click', function() {
            if (confirm('Вы уверены, что хотите сбросить все настройки?')) {
                clearSettings();
                closeSettingsMenu();
                alert('Настройки сброшены до значений по умолчанию.');
            }
        });

        document.getElementById('closeSettings').addEventListener('click', closeSettingsMenu);

        function closeSettingsMenu() {
            overlay.style.opacity = '0';
            settingsPanel.style.transform = 'translate(-50%, -50%) scale(0.9)';
            setTimeout(() => {
                settingsDiv.remove();
            }, 300);
        }
    }

    function updateStyles() {
        GM_addStyle(`
            .lzt-summary-button {
                background: linear-gradient(45deg, ${settings.buttonColor}, ${lightenDarkenColor(settings.buttonColor, -20)});
                border: none;
                color: white;
                padding: 10px 15px;
                text-align: center;
                text-decoration: none;
                display: inline-block;
                font-size: 14px;
                user-select: none;
                margin: 10px 0;
                cursor: pointer;
                border-radius: 4px;
                transition: all ${settings.animationSpeed}ms ease;
                box-shadow: 0 2px 4px rgba(0,0,0,0.1);
                animation: fadeInButton ${settings.animationSpeed}ms ease-out;
            }
            .lzt-summary-button:hover {
                background: linear-gradient(45deg, ${lightenDarkenColor(settings.buttonColor, -20)}, ${lightenDarkenColor(settings.buttonColor, -40)});
                transform: translateY(-2px);
                box-shadow: 0 4px 8px rgba(0,0,0,0.2);
            }
            .lzt-summary-button:active {
                transform: translateY(0);
            }
            .lzt-summary {
                position: relative;
                z-index: 99;
                background-color: ${settings.summaryBgColor};
                border-left: 4px solid ${settings.buttonColor};
                color: ${settings.summaryTextColor};
                padding: 20px;
                margin: 15px 0;
                border-radius: 8px;
                font-size: 14px;
                line-height: 1.6;
                animation: fadeIn ${settings.animationSpeed}ms ease-out;
                box-shadow: 0 4px 6px rgba(0,0,0,0.1);
            }
            @keyframes fadeIn {
                from { opacity: 0; transform: translateY(-10px); }
                to { opacity: 1; transform: translateY(0); }
            }
            @keyframes fadeInButton {
                from {
                    opacity: 0;
                    transform: translateY(10px);
                }
                to {
                    opacity: 1;
                    transform: translateY(0);
                }
            }
             .lzt-flex {
               display: flex;
               align-items: center;
               gap: 30px;
               flex-wrap: nowrap;
               margin-bottom: 15px;
               justify-content: space-between;
            }
            .lzt-summary-title {
                color: ${settings.buttonColor};
                font-weight: bold;
                margin-bottom: 15px;
                font-size: 18px;
                font-weight: bold;
                display: flex;
                align-items: center;
                gap: 5px;
            }
            .lzt-summary-content {
                margin-top: 10px;
                white-space: pre-line;
            }
            .lzt-key-points {
                margin-top: 20px;
                padding-top: 15px;
                border-top: 1px solid rgba(255,255,255,0.2);
            }
            .lzt-key-points-title {
                color: ${settings.buttonColor};
                font-weight: bold;
                margin-bottom: 10px;
                display: flex;
                align-items: center;
                gap: 5px;
            }
            .lzt-key-point {
                margin: 8px 0;
                padding-left: 20px;
                position: relative;
            }
            .lzt-key-point:before {
                content: "•";
                color: ${settings.buttonColor};
                position: absolute;
                left: 0;
                font-size: 18px;
            }
            .lzt-popup {
                position: fixed;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%) scale(0.9);
                background-color: ${settings.summaryBgColor};
                padding: 30px;
                border-radius: 12px;
                box-shadow: 0 10px 30px rgba(0,0,0,0.3);
                z-index: 999999;
                width: 90%;
                max-width: 800px;
                max-height: 90vh;
                overflow-y: auto;
                opacity: 0;
                transition: all ${settings.animationSpeed}ms ease;
            }
            .lzt-popup.show {
                opacity: 1;
                transform: translate(-50%, -50%) scale(1);
            }
            .lzt-popup-close {
                position: absolute;
                top: 15px;
                right: 20px;
                font-size: 28px;
                color: ${settings.summaryTextColor};
                cursor: pointer;
                transition: color ${settings.animationSpeed}ms ease;
            }
            .lzt-popup-close:hover {
                color: ${settings.buttonColor};
            }
            .lzt-original-content {
                transition: opacity ${settings.animationSpeed}ms ease, height ${settings.animationSpeed}ms ease;
                overflow: hidden;
            }
            .lzt-overlay {
                position: fixed;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background-color: rgba(0, 0, 0, 0.7);
                backdrop-filter: blur(8px);
                z-index: 99998;
                opacity: 0;
                transition: opacity ${settings.animationSpeed}ms ease;
            }
            .lzt-overlay.show {
                opacity: 1;
            }
            .lzt-settings-overlay {
                position: fixed;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background-color: rgba(0, 0, 0, 0.8);
                z-index: 10000;
                display: flex;
                justify-content: center;
                align-items: center;
                opacity: 0;
                backdrop-filter: blur(8px);
                transition: opacity ${settings.animationSpeed}ms ease;
            }
            .lzt-settings {
                background-color: #303030b0;
                padding: 30px;
                border-radius: 12px;
                box-shadow: 0 10px 30px rgba(0,0,0,0.3);
                width: 90%;
                max-width: 500px;
                transform: translate(-50%, -50%) scale(0.9);
                transition: transform ${settings.animationSpeed}ms ease;
                position: fixed;
                top: 50%;
                left: 50%;
            }
            .lzt-settings-title {
                display: flex;
                align-items: center;
                gap: 5px;
                color: #228e5d;
                font-weight: bold;
                margin-bottom: 0;
                font-size: 18px;
                white-space: nowrap;
                text-overflow: ellipsis;
            }
            .lzt-settings-group {
                margin-bottom: 15px;
            }
            .lzt-settings-group label {
                display: block;
                color: #bdc3c7;
                margin-bottom: 5px;
            }
            .lzt-settings-group input {
                width: 100%;
                padding: 8px;
                border: none;
                border-radius: 4px;
                background-color: #303030;
                color: #ecf0f1;
                font-size: 14px;
            }
            .lzt-settings-group input[type="color"] {
                height: 40px;
                cursor: pointer;
            }
            .lzt-settings-buttons {
               display: flex;
               gap: 5px;
               justify-content: space-between;
               margin-top: 20px;
            }
            .lzt-settings-button {
                padding: 10px 20px;
                border: none;
                border-radius: 4px;
                font-size: 15px;
                cursor: pointer;
                transition: background-color ${settings.animationSpeed}ms ease;
            }
           .lzt-settings-save {
               display: block;
               width: -webkit-fill-available;
               background-color: #2ecc7161;
               color: white;
            }
            .lzt-settings-save:hover {
               background-color: #27ae60;
            }
            .lzt-settings-clear {
              display: block;
              width: -webkit-fill-available;
              background-color: #f39c1291;
              color: white;
             }
            .lzt-settings-clear:hover {
              background-color: #d35400;
            }
            .lzt-settings-close {
              display: flex;
              border-radius: 12px;
              padding: 8px 18px;
              width: max-content;
              background-color: #313131;
              color: white;
            }
            .lzt-settings-close:hover {
              background-color: #c0392b;
            }
            .lzt-reading-time {
            display: flex;
            align-items: center;
            gap: 5px;
            font-size: 12px;
            opacity: .8;
            color: ${settings.summaryTextColor};
            margin-top: 10px;
            }
        `);
    }

    function lightenDarkenColor(col, amt) {
        let usePound = false;
        if (col[0] == "#") {
            col = col.slice(1);
            usePound = true;
        }
        let num = parseInt(col,16);
        let r = (num >> 16) + amt;
        if (r > 255) r = 255;
        else if (r < 0) r = 0;
        let b = ((num >> 8) & 0x00FF) + amt;
        if (b > 255) b = 255;
        else if (b < 0) b = 0;
        let g = (num & 0x0000FF) + amt;
        if (g > 255) g = 255;
        else if (g < 0) g = 0;
        return (usePound?"#":"") + (g | (b << 8) | (r << 16)).toString(16).padStart(6, '0');
    }

    function extractKeyPoints(text) {
        const sentences = text.match(/[^\.!\?]+[\.!\?]+/g) || [];
        const keyPoints = [];

        const indicators = [
            'важно', 'главное', 'необходимо', 'следует', 'нужно',
            'основной', 'ключевой', 'рекомендуется', 'обратите внимание',
            'в первую очередь', 'самое важное', 'ключевая идея', 'существенно',
            'критически', 'принципиально', 'фундаментально', 'приоритетно'
        ];

        sentences.forEach(sentence => {
            const lowercaseSentence = sentence.toLowerCase();
            if (indicators.some(indicator => lowercaseSentence.includes(indicator)) ||
                (sentence.length > 30 && sentence.length < 200 && /[0-9]/.test(sentence)) ||
                /^[•\-]/.test(sentence.trim())) {
                keyPoints.push(sentence.trim());
            }
        });

        const startIndicators = ['ключевые моменты', 'основные пункты', 'главные идеи'];
        let foundKeyPointSection = false;

        sentences.forEach(sentence => {
            const lowercaseSentence = sentence.toLowerCase().trim();
            if (startIndicators.some(indicator => lowercaseSentence.startsWith(indicator))) {
                foundKeyPointSection = true;
            }
            if (foundKeyPointSection && /^[•\-]/.test(sentence.trim())) {
                keyPoints.push(sentence.trim());
            }
        });

        return [...new Set(keyPoints)].slice(0, settings.maxKeyPoints);
    }

    function summarizeText(text) {
        text = text.replace(/\s+/g, ' ').trim();

        const sentences = text.split(/(?<=[.!?])\s+(?=[A-ZА-Я])/);

        if (sentences.length === 0) {
            return '';
        }

        const sentenceScores = sentences.map((sentence, index) => {
            const words = sentence.toLowerCase().split(' ');
            let score = 0;

            const importantWords = [
                'важно', 'главное', 'необходимо', 'ключевой', 'существенно',
                'критически', 'спонсор', 'проект', 'результат', 'итог',
                'вывод', 'следовательно', 'таким образом', 'поэтому',
                'значит', 'суть', 'основа', 'цель', 'задача'
            ];

            const importantWordsCount = words.filter(word =>
                importantWords.some(important => word.includes(important))
            ).length;
            score += importantWordsCount * 3;

            if (sentence.length > 50 && sentence.length < 200) {
                score += 2;
            }

            if (/[0-9]/.test(sentence)) score += 2;
            if (/[%$€₽]/.test(sentence)) score += 2;

            if (index < 3) score += 3;
            if (index > sentences.length - 4) score += 2;

            if (index > 0) {
                const prevSentence = sentences[index - 1].toLowerCase();
                const commonWords = words.filter(word =>
                    word.length > 3 && prevSentence.includes(word)
                );
                score += commonWords.length * 0.5;
            }

            return { sentence, score, index };
        });

        sentenceScores.sort((a, b) => b.score - a.score);

        const selectedSentences = sentenceScores
            .slice(0, Math.ceil(sentences.length * 0.3))
            .sort((a, b) => a.index - b.index);

        let summary = selectedSentences
            .map(item => item.sentence.trim())
            .join('\n\n');

        if (summary.length > settings.maxSummaryLength) {
            summary = summary.substring(0, settings.maxSummaryLength).trim();
            const lastDot = summary.lastIndexOf('.');
            if (lastDot > 0) {
                summary = summary.substring(0, lastDot + 1);
            }
        }

        return summary;
    }

    function createPopup(content) {
        const overlay = document.createElement('div');
        overlay.className = 'lzt-overlay';
        document.body.appendChild(overlay);

        const popup = document.createElement('div');
        popup.className = 'lzt-popup';
        popup.innerHTML = `
            <div class="lzt-popup-close">&times;</div>
            ${content}
        `;

        document.body.appendChild(popup);

        setTimeout(() => {
            overlay.classList.add('show');
            popup.classList.add('show');
        }, 50);

        const closePopup = () => {
            overlay.classList.remove('show');
            popup.classList.remove('show');
            setTimeout(() => {
                overlay.remove();
                popup.remove();
            }, settings.animationSpeed);
        };

        popup.querySelector('.lzt-popup-close').addEventListener('click', closePopup);
        overlay.addEventListener('click', closePopup);
    }

    function getTextContent(element) {
        let text = '';
        function extractText(node) {
            if (node.nodeType === Node.TEXT_NODE) {
                text += node.textContent.trim() + ' ';
            } else if (node.nodeType === Node.ELEMENT_NODE) {
                if (node.classList.contains('bbCodeBlock') ||
                    node.tagName === 'IMG' ||
                    node.tagName === 'SCRIPT' ||
                    node.tagName === 'STYLE' ||
                    node.classList.contains('messageTextEndMarker') ||
                    node.classList.contains('lzt-summary-button')) {
                    return;
                }
                node.childNodes.forEach(extractText);
            }
        }
        extractText(element);
        return text.replace(/\s+/g, ' ').trim();
    }

    function formatReadingTime(text) {
        const words = text.split(/\s+/).length;
        const minutes = words / settings.wordsPerMinute;

        if (minutes < 1) {
            const seconds = Math.ceil(minutes * 60);
            return `${seconds} сек.`;
        }

        return `${Math.ceil(minutes)} мин.`;
    }

    function addSummaryButton(postElement) {
        if (!postElement.classList.contains('firstPost')) return;

        if (postElement.querySelector('.lzt-summary-button')) return;

        const contentElement = postElement.querySelector('.messageContent');
        if (!contentElement) return;

        const fullText = getTextContent(contentElement);

        if (fullText.length < settings.minTextLength) {
            return;
        }

        const summaryButton = document.createElement('button');
        summaryButton.textContent = '📝 Показать резюме';
        summaryButton.className = 'lzt-summary-button';
        summaryButton.style.opacity = '0';

        let summaryElement = null;
        let isProcessing = false;

        summaryButton.addEventListener('click', function(e) {
            e.preventDefault();
            if (isProcessing) return;
            isProcessing = true;

            if (summaryElement) {
                summaryElement.style.display = summaryElement.style.display === 'none' ? 'block' : 'none';
                summaryButton.textContent = summaryElement.style.display === 'none' ? '📝 Показать резюме' : '❌ Скрыть резюме';

                contentElement.style.height = summaryElement.style.display === 'none' ? 'auto' : '0';
                contentElement.style.opacity = summaryElement.style.display === 'none' ? '1' : '0';
                isProcessing = false;
            } else {
                const summary = summarizeText(fullText);
                const keyPoints = extractKeyPoints(fullText);
                const readingTime = formatReadingTime(fullText);
                const summaryReadingTime = formatReadingTime(summary);

                summaryElement = document.createElement('div');
                summaryElement.className = 'lzt-summary';

                let summaryHTML = `
                    <div class="lzt-summary-title"><svg xmlns="http://www.w3.org/2000/svg" width="23" height="23" viewBox="0 0 24 24"><g fill="none"><path fill="url(#fluentColorPin240)" fill-rule="evenodd" d="m9.53 15.53l-5.25 5.25a.75.75 0 1 1-1.06-1.06l5.25-5.25z" clip-rule="evenodd"/><path fill="url(#fluentColorPin241)" d="m21.068 7.758l-4.826-4.826a2.75 2.75 0 0 0-4.404.715l-2.435 4.87a.75.75 0 0 1-.426.374l-4.166 1.44a1.25 1.25 0 0 0-.476 2.065l7.27 7.27a1.25 1.25 0 0 0 2.065-.477l1.44-4.166a.75.75 0 0 1 .373-.426l4.87-2.435a2.75 2.75 0 0 0 .715-4.404"/><path fill="url(#fluentColorPin242)" fill-opacity="1" d="m21.068 7.758l-4.826-4.826a2.75 2.75 0 0 0-4.404.715l-2.435 4.87a.75.75 0 0 1-.426.374l-4.166 1.44a1.25 1.25 0 0 0-.476 2.065l7.27 7.27a1.25 1.25 0 0 0 2.065-.477l1.44-4.166a.75.75 0 0 1 .373-.426l4.87-2.435a2.75 2.75 0 0 0 .715-4.404"/><defs><linearGradient id="fluentColorPin240" x1="4.633" x2="9.496" y1="19.367" y2="15.648" gradientUnits="userSpaceOnUse"><stop offset=".449" stop-color="#a1a1a1"/><stop offset="1" stop-color="#841010"/></linearGradient><linearGradient id="fluentColorPin241" x1="4.608" x2="16.965" y1="5.483" y2="18.322" gradientUnits="userSpaceOnUse"><stop stop-color="#e54343"/><stop offset="1" stop-color="#af1212"/></linearGradient><radialGradient id="fluentColorPin242" cx="0" cy="0" r="1" gradientTransform="rotate(47.579 -9.812 28.432)scale(7.95948 19.9685)" gradientUnits="userSpaceOnUse"><stop stop-color="#ce6969"/><stop offset="1" stop-color="#772828" stop-opacity="0"/></radialGradient></defs></g></svg> Краткое содержание</div>
                    <div class="lzt-summary-content">${summary || 'Не удалось создать краткое содержание.'}</div>
                    <div class="lzt-reading-time"><svg xmlns="http://www.w3.org/2000/svg" width="21" height="21" viewBox="0 0 32 32"><g fill="none"><path fill="#7d4533" d="M16.81 30.04V23.4L14.5 22l-2.67 1.4v6.64z"/><path fill="#5092ff" d="M21.65 7H7.84L11 23.61h14.99a1.5 1.5 0 0 0 1.5-1.5v-9.27C27.48 9.61 24.87 7 21.65 7"/><path fill="#3f5fff" d="M7.84 7C4.61 7 2 9.61 2 12.84v9.27a1.5 1.5 0 0 0 1.5 1.5h8.67a1.5 1.5 0 0 0 1.5-1.5v-9.27C13.67 9.61 11.06 7 7.84 7"/><path fill="#1345b7" d="M9.27 20H4.98c-.54 0-.98.44-.98.98s.44.98.98.98h4.29c.54 0 .98-.44.98-.98a.97.97 0 0 0-.98-.98"/><path fill="#f92f60" d="M30 19.132v-5.264c0-.475-.369-.868-.816-.868h-2.369c-.446 0-.815.393-.815.868v5.263c0 .476.369.869.816.869h2.369c.446 0 .815-.393.815-.869"/><path fill="#d3d3d3" d="M20.516 14.63A2.42 2.42 0 0 1 16 13.42a2.42 2.42 0 0 1 4.516-1.21h8.904c.67 0 1.21.54 1.21 1.21s-.54 1.21-1.21 1.21z"/></g></svg> Примерное время чтения: ${readingTime} (оригинал) / ${summaryReadingTime} (резюме)</div>
                `;

                if (keyPoints.length > 0) {
                    summaryHTML += `
                        <div class="lzt-key-points">
                            <div class="lzt-key-points-title"><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 32 32"><g fill="none"><g filter="url(#f1543id9)"><path fill="url(#f1543id0)" d="m6.118 26.455l5.047-5.047l3.21 3.211a1.286 1.286 0 0 1-1.039 2.19l-1.08-.11a.87.87 0 0 0-.954.931l.084 1.072a1.214 1.214 0 0 1-2.069.952z"/></g><g filter="url(#f1543ida)"><path fill="url(#f1543id1)" d="m16.397 12.172l3.407 3.406L6.865 28.516a2.409 2.409 0 0 1-3.406-3.407z"/></g><g filter="url(#f1543idb)"><path fill="url(#f1543id2)" fill-rule="evenodd" d="M21.882 18a7.969 7.969 0 1 0 0-15.937a7.969 7.969 0 0 0 0 15.937m0-4a3.969 3.969 0 1 0 0-7.937a3.969 3.969 0 0 0 0 7.937" clip-rule="evenodd"/></g><rect width="6.165" height="1.528" x="13.28" y="14.242" fill="url(#f1543id3)" rx=".764" transform="rotate(45 13.28 14.242)"/><rect width="6.165" height="1.528" x="13.28" y="14.242" fill="url(#f1543idd)" rx=".764" transform="rotate(45 13.28 14.242)"/><rect width="6.165" height="1.528" x="13.28" y="14.242" fill="url(#f1543id4)" rx=".764" transform="rotate(45 13.28 14.242)"/><rect width="6.165" height="1.528" x="14.361" y="13.162" fill="url(#f1543id5)" rx=".764" transform="rotate(45 14.36 13.162)"/><rect width="6.165" height="1.528" x="14.361" y="13.162" fill="url(#f1543ide)" rx=".764" transform="rotate(45 14.36 13.162)"/><rect width="6.165" height="1.528" x="14.361" y="13.162" fill="url(#f1543id6)" rx=".764" transform="rotate(45 14.36 13.162)"/><g filter="url(#f1543idc)"><circle cx="22.309" cy="9.604" r="6.309" stroke="url(#f1543id7)" stroke-width="1.25"/><circle cx="22.309" cy="9.604" r="6.309" stroke="url(#f1543id8)" stroke-width="1.25"/></g><defs><linearGradient id="f1543id0" x1="11.632" x2="9.632" y1="27.875" y2="25.709" gradientUnits="userSpaceOnUse"><stop stop-color="#f4b954"/><stop offset=".908" stop-color="#eca84f"/></linearGradient><linearGradient id="f1543id1" x1="8.038" x2="11.279" y1="21.031" y2="24.188" gradientUnits="userSpaceOnUse"><stop stop-color="#f7c250"/><stop offset="1" stop-color="#f8ab54"/></linearGradient><linearGradient id="f1543id2" x1="21.882" x2="21.882" y1="2.813" y2="18" gradientUnits="userSpaceOnUse"><stop stop-color="#f8cf4d"/><stop offset="1" stop-color="#ed9953"/></linearGradient><linearGradient id="f1543id3" x1="14.087" x2="18.329" y1="15.107" y2="15.152" gradientUnits="userSpaceOnUse"><stop stop-color="#f6bf4e"/><stop offset="1" stop-color="#ea994d"/></linearGradient><linearGradient id="f1543id4" x1="16.683" x2="16.678" y1="15.98" y2="15.322" gradientUnits="userSpaceOnUse"><stop offset=".186" stop-color="#e29226"/><stop offset="1" stop-color="#ec9b4f" stop-opacity="0"/></linearGradient><linearGradient id="f1543id5" x1="15.167" x2="19.41" y1="14.027" y2="14.071" gradientUnits="userSpaceOnUse"><stop stop-color="#f6bf4e"/><stop offset="1" stop-color="#ea994d"/></linearGradient><linearGradient id="f1543id6" x1="17.764" x2="17.759" y1="14.9" y2="14.241" gradientUnits="userSpaceOnUse"><stop offset=".186" stop-color="#e29226"/><stop offset="1" stop-color="#e29226" stop-opacity="0"/></linearGradient><linearGradient id="f1543id7" x1="27.32" x2="21.468" y1="4.298" y2="9.259" gradientUnits="userSpaceOnUse"><stop stop-color="#ffdd67"/><stop offset="1" stop-color="#ffdd67" stop-opacity="0"/></linearGradient><linearGradient id="f1543id8" x1="17.632" x2="19.007" y1="14" y2="11.813" gradientUnits="userSpaceOnUse"><stop stop-color="#feb765"/><stop offset="1" stop-color="#feb765" stop-opacity="0"/></linearGradient><filter id="f1543id9" width="8.635" height="8.752" x="6.118" y="21.258" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="-.15"/><feGaussianBlur stdDeviation=".25"/><feComposite in2="hardAlpha" k2="-1" k3="1" operator="arithmetic"/><feColorMatrix values="0 0 0 0 0.839216 0 0 0 0 0.592157 0 0 0 0 0.34902 0 0 0 1 0"/><feBlend in2="shape" result="effect1_innerShadow_18_23735"/></filter><filter id="f1543ida" width="17.049" height="17.549" x="2.754" y="11.672" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="-.5"/><feGaussianBlur stdDeviation=".75"/><feComposite in2="hardAlpha" k2="-1" k3="1" operator="arithmetic"/><feColorMatrix values="0 0 0 0 0.85098 0 0 0 0 0.541176 0 0 0 0 0.34902 0 0 0 1 0"/><feBlend in2="shape" result="effect1_innerShadow_18_23735"/></filter><filter id="f1543idb" width="15.938" height="16.337" x="13.913" y="1.663" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="-.4"/><feGaussianBlur stdDeviation=".5"/><feComposite in2="hardAlpha" k2="-1" k3="1" operator="arithmetic"/><feColorMatrix values="0 0 0 0 0.815686 0 0 0 0 0.505882 0 0 0 0 0.337255 0 0 0 1 0"/><feBlend in2="shape" result="effect1_innerShadow_18_23735"/></filter><filter id="f1543idc" width="16.368" height="16.368" x="14.125" y="1.42" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_18_23735" stdDeviation=".625"/></filter><radialGradient id="f1543idd" cx="0" cy="0" r="1" gradientTransform="matrix(-.01573 .32677 -1.89283 -.09112 16.743 14.626)" gradientUnits="userSpaceOnUse"><stop stop-color="#fcbc66"/><stop offset="1" stop-color="#fcbc66" stop-opacity="0"/></radialGradient><radialGradient id="f1543ide" cx="0" cy="0" r="1" gradientTransform="matrix(-.01573 .32677 -1.89283 -.09112 17.823 13.545)" gradientUnits="userSpaceOnUse"><stop stop-color="#fbb865"/><stop offset="1" stop-color="#fbb865" stop-opacity="0"/></radialGradient></defs></g></svg> Ключевые моменты:</div>
                            ${keyPoints.map(point => `<div class="lzt-key-point">${point}</div>`).join('')}
                        </div>
                    `;
                } else {
                    summaryHTML += `
                        <div class="lzt-key-points">
                            <div class="lzt-key-points-title"><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 32 32"><g fill="none"><g filter="url(#f1543id9)"><path fill="url(#f1543id0)" d="m6.118 26.455l5.047-5.047l3.21 3.211a1.286 1.286 0 0 1-1.039 2.19l-1.08-.11a.87.87 0 0 0-.954.931l.084 1.072a1.214 1.214 0 0 1-2.069.952z"/></g><g filter="url(#f1543ida)"><path fill="url(#f1543id1)" d="m16.397 12.172l3.407 3.406L6.865 28.516a2.409 2.409 0 0 1-3.406-3.407z"/></g><g filter="url(#f1543idb)"><path fill="url(#f1543id2)" fill-rule="evenodd" d="M21.882 18a7.969 7.969 0 1 0 0-15.937a7.969 7.969 0 0 0 0 15.937m0-4a3.969 3.969 0 1 0 0-7.937a3.969 3.969 0 0 0 0 7.937" clip-rule="evenodd"/></g><rect width="6.165" height="1.528" x="13.28" y="14.242" fill="url(#f1543id3)" rx=".764" transform="rotate(45 13.28 14.242)"/><rect width="6.165" height="1.528" x="13.28" y="14.242" fill="url(#f1543idd)" rx=".764" transform="rotate(45 13.28 14.242)"/><rect width="6.165" height="1.528" x="13.28" y="14.242" fill="url(#f1543id4)" rx=".764" transform="rotate(45 13.28 14.242)"/><rect width="6.165" height="1.528" x="14.361" y="13.162" fill="url(#f1543id5)" rx=".764" transform="rotate(45 14.36 13.162)"/><rect width="6.165" height="1.528" x="14.361" y="13.162" fill="url(#f1543ide)" rx=".764" transform="rotate(45 14.36 13.162)"/><rect width="6.165" height="1.528" x="14.361" y="13.162" fill="url(#f1543id6)" rx=".764" transform="rotate(45 14.36 13.162)"/><g filter="url(#f1543idc)"><circle cx="22.309" cy="9.604" r="6.309" stroke="url(#f1543id7)" stroke-width="1.25"/><circle cx="22.309" cy="9.604" r="6.309" stroke="url(#f1543id8)" stroke-width="1.25"/></g><defs><linearGradient id="f1543id0" x1="11.632" x2="9.632" y1="27.875" y2="25.709" gradientUnits="userSpaceOnUse"><stop stop-color="#f4b954"/><stop offset=".908" stop-color="#eca84f"/></linearGradient><linearGradient id="f1543id1" x1="8.038" x2="11.279" y1="21.031" y2="24.188" gradientUnits="userSpaceOnUse"><stop stop-color="#f7c250"/><stop offset="1" stop-color="#f8ab54"/></linearGradient><linearGradient id="f1543id2" x1="21.882" x2="21.882" y1="2.813" y2="18" gradientUnits="userSpaceOnUse"><stop stop-color="#f8cf4d"/><stop offset="1" stop-color="#ed9953"/></linearGradient><linearGradient id="f1543id3" x1="14.087" x2="18.329" y1="15.107" y2="15.152" gradientUnits="userSpaceOnUse"><stop stop-color="#f6bf4e"/><stop offset="1" stop-color="#ea994d"/></linearGradient><linearGradient id="f1543id4" x1="16.683" x2="16.678" y1="15.98" y2="15.322" gradientUnits="userSpaceOnUse"><stop offset=".186" stop-color="#e29226"/><stop offset="1" stop-color="#ec9b4f" stop-opacity="0"/></linearGradient><linearGradient id="f1543id5" x1="15.167" x2="19.41" y1="14.027" y2="14.071" gradientUnits="userSpaceOnUse"><stop stop-color="#f6bf4e"/><stop offset="1" stop-color="#ea994d"/></linearGradient><linearGradient id="f1543id6" x1="17.764" x2="17.759" y1="14.9" y2="14.241" gradientUnits="userSpaceOnUse"><stop offset=".186" stop-color="#e29226"/><stop offset="1" stop-color="#e29226" stop-opacity="0"/></linearGradient><linearGradient id="f1543id7" x1="27.32" x2="21.468" y1="4.298" y2="9.259" gradientUnits="userSpaceOnUse"><stop stop-color="#ffdd67"/><stop offset="1" stop-color="#ffdd67" stop-opacity="0"/></linearGradient><linearGradient id="f1543id8" x1="17.632" x2="19.007" y1="14" y2="11.813" gradientUnits="userSpaceOnUse"><stop stop-color="#feb765"/><stop offset="1" stop-color="#feb765" stop-opacity="0"/></linearGradient><filter id="f1543id9" width="8.635" height="8.752" x="6.118" y="21.258" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="-.15"/><feGaussianBlur stdDeviation=".25"/><feComposite in2="hardAlpha" k2="-1" k3="1" operator="arithmetic"/><feColorMatrix values="0 0 0 0 0.839216 0 0 0 0 0.592157 0 0 0 0 0.34902 0 0 0 1 0"/><feBlend in2="shape" result="effect1_innerShadow_18_23735"/></filter><filter id="f1543ida" width="17.049" height="17.549" x="2.754" y="11.672" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="-.5"/><feGaussianBlur stdDeviation=".75"/><feComposite in2="hardAlpha" k2="-1" k3="1" operator="arithmetic"/><feColorMatrix values="0 0 0 0 0.85098 0 0 0 0 0.541176 0 0 0 0 0.34902 0 0 0 1 0"/><feBlend in2="shape" result="effect1_innerShadow_18_23735"/></filter><filter id="f1543idb" width="15.938" height="16.337" x="13.913" y="1.663" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="-.4"/><feGaussianBlur stdDeviation=".5"/><feComposite in2="hardAlpha" k2="-1" k3="1" operator="arithmetic"/><feColorMatrix values="0 0 0 0 0.815686 0 0 0 0 0.505882 0 0 0 0 0.337255 0 0 0 1 0"/><feBlend in2="shape" result="effect1_innerShadow_18_23735"/></filter><filter id="f1543idc" width="16.368" height="16.368" x="14.125" y="1.42" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_18_23735" stdDeviation=".625"/></filter><radialGradient id="f1543idd" cx="0" cy="0" r="1" gradientTransform="matrix(-.01573 .32677 -1.89283 -.09112 16.743 14.626)" gradientUnits="userSpaceOnUse"><stop stop-color="#fcbc66"/><stop offset="1" stop-color="#fcbc66" stop-opacity="0"/></radialGradient><radialGradient id="f1543ide" cx="0" cy="0" r="1" gradientTransform="matrix(-.01573 .32677 -1.89283 -.09112 17.823 13.545)" gradientUnits="userSpaceOnUse"><stop stop-color="#fbb865"/><stop offset="1" stop-color="#fbb865" stop-opacity="0"/></radialGradient></defs></g></svg> Ключевые моменты:</div>
                            <div class="lzt-key-point">Не удалось выделить ключевые моменты.</div>
                        </div>
                    `;
                }

                summaryElement.innerHTML = summaryHTML;
                contentElement.parentNode.insertBefore(summaryElement, contentElement.nextSibling);
                summaryButton.textContent = '❌ Скрыть резюме';

                contentElement.style.height = '0';
                contentElement.style.opacity = '0';

                setTimeout(() => {
                    isProcessing = false;
                }, settings.animationSpeed);
            }
        });

        contentElement.parentNode.insertBefore(summaryButton, contentElement);

        setTimeout(() => {
            summaryButton.style.opacity = '1';
        }, 100);
    }

    function summarizeMainArticle() {
        const firstPost = document.querySelector('li.message.firstPost');
        if (!firstPost) {
            alert('Не удалось найти основную статью на странице.');
            return;
        }

        const contentElement = firstPost.querySelector('.messageContent');
        if (!contentElement) {
            alert('Не удалось найти содержимое статьи.');
            return;
        }

        const fullText = getTextContent(contentElement);
        const summary = summarizeText(fullText);
        const keyPoints = extractKeyPoints(fullText);
        const readingTime = formatReadingTime(fullText);
        const summaryReadingTime = formatReadingTime(summary);

        let popupContent = `
            <div class="lzt-summary-title">📝 Краткое содержание статьи</div>
            <div class="lzt-summary-content">${summary || 'Не удалось создать краткое содержание.'}</div>
            <div class="lzt-reading-time"><svg xmlns="http://www.w3.org/2000/svg" width="21" height="21" viewBox="0 0 32 32"><g fill="none"><path fill="#7d4533" d="M16.81 30.04V23.4L14.5 22l-2.67 1.4v6.64z"/><path fill="#5092ff" d="M21.65 7H7.84L11 23.61h14.99a1.5 1.5 0 0 0 1.5-1.5v-9.27C27.48 9.61 24.87 7 21.65 7"/><path fill="#3f5fff" d="M7.84 7C4.61 7 2 9.61 2 12.84v9.27a1.5 1.5 0 0 0 1.5 1.5h8.67a1.5 1.5 0 0 0 1.5-1.5v-9.27C13.67 9.61 11.06 7 7.84 7"/><path fill="#1345b7" d="M9.27 20H4.98c-.54 0-.98.44-.98.98s.44.98.98.98h4.29c.54 0 .98-.44.98-.98a.97.97 0 0 0-.98-.98"/><path fill="#f92f60" d="M30 19.132v-5.264c0-.475-.369-.868-.816-.868h-2.369c-.446 0-.815.393-.815.868v5.263c0 .476.369.869.816.869h2.369c.446 0 .815-.393.815-.869"/><path fill="#d3d3d3" d="M20.516 14.63A2.42 2.42 0 0 1 16 13.42a2.42 2.42 0 0 1 4.516-1.21h8.904c.67 0 1.21.54 1.21 1.21s-.54 1.21-1.21 1.21z"/></g></svg> Примерное время чтения: ${readingTime} (оригинал) / ${summaryReadingTime} (резюме)</div>
        `;

        if (keyPoints.length > 0) {
            popupContent += `
                <div class="lzt-key-points">
                    <div class="lzt-key-points-title">🔑 Ключевые моменты:</div>
                    ${keyPoints.map(point => `<div class="lzt-key-point">${point}</div>`).join('')}
                </div>
            `;
        } else {
            popupContent += `
                <div class="lzt-key-points">
                    <div class="lzt-key-points-title">🔑 Ключевые моменты:</div>
                    <div class="lzt-key-point">Не удалось выделить ключевые моменты.</div>
                </div>
            `;
        }

        createPopup(popupContent);
    }

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

    GM_registerMenuCommand("LZT Резюме статьи", debounce(summarizeMainArticle, 300));
    GM_registerMenuCommand("Настройки LZT Summarizer", debounce(createSettingsMenu, 300));

    updateStyles();

    window.addEventListener('load', function() {
        const firstPost = document.querySelector('li.message.firstPost');
        if (firstPost) {
            addSummaryButton(firstPost);
        }
    });

    const observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            if (mutation.type === 'childList') {
                mutation.addedNodes.forEach(function(node) {
                    if (node.nodeType === 1 && node.matches('li.message.firstPost')) {
                        addSummaryButton(node);
                    }
                });
            }
        });
    });

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