Greasy Fork is available in English.

Chat Report Ultimate

Кнопка репорта в чате, размытие меню и кнопки быстрых причин в окне жалобы

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

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

Tendrás que instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Tendrás que instalar una extensión como Tampermonkey antes de poder instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         Chat Report Ultimate
// @namespace    http://tampermonkey.net/
// @version      3.0
// @description  Кнопка репорта в чате, размытие меню и кнопки быстрых причин в окне жалобы
// @author       You
// @match        https://lolz.live/*
// @match        https://zelenka.guru/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=lolz.live
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // === НАСТРОЙКИ ПРИЧИН РЕПОРТА ===
    const REASONS = [
        'Выпрашивание симпатий',
        'Неуважительное поведение к пользователю',
        'Попрошайничество',
        'Запрещенный контент',
        'Неадекватный контент',
    ];

    // SVG иконка флажка (репорт)
    const reportIconSvg = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lztng-yh4ip5"><path d="M4 13.9999L5.57465 20.2985C5.61893 20.4756 5.64107 20.5642 5.66727 20.6415C5.92317 21.397 6.60352 21.9282 7.39852 21.9933C7.4799 21.9999 7.5712 21.9999 7.75379 21.9999C7.98244 21.9999 8.09677 21.9999 8.19308 21.9906C9.145 21.8982 9.89834 21.1449 9.99066 20.193C10 20.0967 10 19.9823 10 19.7537V5.49991M18.5 13.4999C20.433 13.4999 22 11.9329 22 9.99991C22 8.06691 20.433 6.49991 18.5 6.49991M10.25 5.49991H6.5C4.01472 5.49991 2 7.51463 2 9.99991C2 12.4852 4.01472 14.4999 6.5 14.4999H10.25C12.0164 14.4999 14.1772 15.4468 15.8443 16.3556C16.8168 16.8857 17.3031 17.1508 17.6216 17.1118C17.9169 17.0756 18.1402 16.943 18.3133 16.701C18.5 16.4401 18.5 15.9179 18.5 14.8736V5.1262C18.5 4.08191 18.5 3.55976 18.3133 3.2988C18.1402 3.05681 17.9169 2.92421 17.6216 2.88804C17.3031 2.84903 16.8168 3.11411 15.8443 3.64427C14.1772 4.55302 12.0164 5.49991 10.25 5.49991Z"></path></svg>`;

    // === ОБЩАЯ ИНЪЕКЦИЯ СТИЛЕЙ ===
    const addCustomStyles = () => {
        if (document.getElementById('lolz-custom-report-styles')) return;
        const style = document.createElement('style');
        style.id = 'lolz-custom-report-styles';
        style.textContent = `
            /* Стилизуем панель оригинального контекстного меню (размытие) */
            .message-actions {
                background-color: rgba(20, 20, 20, 0.4) !important;
                backdrop-filter: blur(12px) !important;
                -webkit-backdrop-filter: blur(12px) !important;
                border: 1px solid rgba(255, 255, 255, 0.1) !important;
                border-radius: 8px !important;
            }
            .message-actions ul.menu {
                background: transparent !important;
            }
            .message-actions ul.menu li.action:hover {
                background-color: rgba(255, 255, 255, 0.1) !important;
            }

            /* Стили для кнопок причин репорта */
            .injected-reasons {
                display: flex;
                flex-direction: column;
                gap: 6px;
                margin-bottom: 12px;
            }
            .injected-reason-btn {
                display: flex;
                align-items: center;
                gap: 10px;
                padding: 8px 14px;
                font-size: 14px;
                cursor: pointer;
                border: 1px solid #3a3a3a;
                border-radius: 6px;
                background: #2a2a2a;
                color: #e0e0e0;
                text-align: left;
                transition: background 0.15s, border-color 0.15s;
            }
            .injected-reason-btn:hover {
                background: #333;
                border-color: #4caf50;
                color: #fff;
            }
            .injected-reason-btn::before {
                content: '';
                display: inline-block;
                width: 7px;
                height: 7px;
                border-radius: 50%;
                background: #4caf50;
                flex-shrink: 0;
            }
        `;
        document.head.appendChild(style);
    };

    // === ФУНКЦИЯ 1: ИКОНКА РЕПОРТА В ЧАТЕ ===
    function addReportIcon(messageHeader) {
        if (messageHeader.querySelector('.custom-report-btn')) return;

        const usernameEl = messageHeader.querySelector('.chat2-message-username');
        if (!usernameEl) return;

        const reportBtn = document.createElement('span');
        reportBtn.className = 'custom-report-btn';
        reportBtn.innerHTML = reportIconSvg;
        reportBtn.title = 'Пожаловаться';
        
        reportBtn.style.cssText = `
            color: #ff3b30; 
            cursor: pointer; 
            margin-left: 6px; 
            display: inline-flex; 
            align-items: center; 
            opacity: 0.5; 
            transition: opacity 0.2s;
        `;
        
        reportBtn.addEventListener('mouseenter', () => reportBtn.style.opacity = '1');
        reportBtn.addEventListener('mouseleave', () => reportBtn.style.opacity = '0.5');

        // Симуляция правого клика и вызова окна репорта
        reportBtn.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation();

            const messageBlock = e.target.closest('.chat2-message');
            if (!messageBlock) return;

            // Вызываем контекстное меню
            const rightClickEvent = new MouseEvent('contextmenu', {
                bubbles: true,
                cancelable: true,
                view: window,
                button: 2,
                buttons: 2,
                clientX: e.clientX,
                clientY: e.clientY
            });
            messageBlock.dispatchEvent(rightClickEvent);

            // Ищем и жмем "Пожаловаться"
            setTimeout(() => {
                const actionsMenu = document.querySelector('.message-actions');
                if (actionsMenu) {
                    const menuItems = actionsMenu.querySelectorAll('li.action');
                    for (let item of menuItems) {
                        if (item.textContent.includes('Пожаловаться')) {
                            item.click();
                            break;
                        }
                    }
                }
            }, 50);
        });

        usernameEl.appendChild(reportBtn);
    }

    // === ФУНКЦИЯ 2: КНОПКИ ПРИЧИН В ОКНЕ ЖАЛОБЫ ===
    function injectButtons(reportForm) {
        if (reportForm.querySelector('.injected-reasons')) return;

        const textarea = reportForm.querySelector('textarea[name="reason"], #reason');
        if (!textarea) return;

        function submitAndClose() {
            const submitBtn = reportForm.querySelector('button.submit, button.primary, input[type="submit"]');
            if (submitBtn) submitBtn.click();
            
            // На всякий случай пытаемся найти кнопку закрытия модалки
            const closeBtn = document.querySelector('.OverlayCloser, [data-close], .close');
            if (closeBtn) closeBtn.click();
        }

        const container = document.createElement('div');
        container.className = 'injected-reasons';
        
        REASONS.forEach(reason => {
            const btn = document.createElement('button');
            btn.type = 'button';
            btn.className = 'injected-reason-btn';
            btn.textContent = reason;
            
            btn.addEventListener('click', () => {
                textarea.value = reason;
                // Имитируем ввод для фреймворка
                textarea.dispatchEvent(new Event('input', { bubbles: true }));
                textarea.dispatchEvent(new Event('change', { bubbles: true }));
                submitAndClose();
            });
            
            container.appendChild(btn);
        });
        
        textarea.parentElement.insertBefore(container, textarea);

        // Отправка по Enter
        textarea.addEventListener('keydown', (e) => {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                submitAndClose();
            }
        });
    }

    // === ИНИЦИАЛИЗАЦИЯ И НАБЛЮДЕНИЕ ===
    function init() {
        addCustomStyles();
        
        // Проверяем чат
        const headers = document.querySelectorAll('.chat2-message-header');
        headers.forEach(addReportIcon);
        
        // Проверяем форму (если она уже открыта)
        const reportForm = document.querySelector('.report-message');
        if (reportForm) injectButtons(reportForm);
    }

    // Единый наблюдатель за изменениями (новые сообщения + открытие окон)
    const observer = new MutationObserver((mutations) => {
        for (const mutation of mutations) {
            for (const node of mutation.addedNodes) {
                if (node.nodeType === Node.ELEMENT_NODE) {
                    
                    // 1. Ищем новые сообщения в чате
                    if (node.classList.contains('chat2-message-header')) {
                        addReportIcon(node);
                    } else {
                        const headers = node.querySelectorAll('.chat2-message-header');
                        headers.forEach(addReportIcon);
                    }

                    // 2. Ищем модальное окно репорта
                    if (node.classList.contains('report-message')) {
                        injectButtons(node);
                    } else {
                        const forms = node.querySelectorAll('.report-message');
                        forms.forEach(injectButtons);
                    }
                }
            }
        }
    });

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