Lolz Offtopic Renamer

Меняет название оффтопика на lolz.live

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Lolz Offtopic Renamer
// @namespace    http://tampermonkey.net/
// @version      3.5
// @description  Меняет название оффтопика на lolz.live
// @author       eretly (optimized version)
// @match        *://lolz.live/*
// @grant        none
// @license      MIT
// @run-at       document-end
// ==/UserScript==

(function() {
    'use strict';

    // Конфиг
    const NEW_OFFTOPIC_NAME = "Анимешный Оффтопик"; // Вписываем название оффтопика

    let originalOfftopicName = "";
    const processedElements = new WeakSet();

    const OFFTOPIC_LINK_SELECTORS = [
        'a[href="https://lolz.live/forums/8/"]',
        'a[href="/forums/8/"]',
        'a[href="forums/8/"]',
        '.p-nav-list a[href="/forums/8/"]',
        'a.u-concealed[href="/forums/8/"]',
        '.p-breadcrumbs a[href="/forums/8/"]'
    ];

    const TEXT_ELEMENT_SELECTORS = [
        'span[itemprop="name"]',
        'span.muted',
        'span.innerText',
        '.search-choice span',
        '.p-title-value',
        '.p-title h1',
        '.p-title span',
        '.p-description .u-muted',
        '.p-navgroup-linkText',
        '.node-title'
    ];

    function escapeRegExp(string) {
        return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    }

    function replaceOfftopicName(text) {
        if (!originalOfftopicName || typeof text !== 'string' || !text.includes(originalOfftopicName)) {
            return text;
        }
        return text.replace(new RegExp(escapeRegExp(originalOfftopicName), 'g'), NEW_OFFTOPIC_NAME);
    }

    async function fetchOfftopicName() {
        try {
            const response = await fetch("https://lolz.live/forums/8/");
            const html = await response.text();
            const parser = new DOMParser();
            const doc = parser.parseFromString(html, 'text/html');

            const h1Element = doc.querySelector('h1[title]');
            if (h1Element && h1Element.textContent.trim()) {
                return h1Element.textContent.trim();
            }

            const titleElement = doc.querySelector('title');
            if (titleElement) {
                const match = titleElement.textContent.match(/(.*?)\s*\|\s*lolz\.live/i);
                if (match && match[1]) {
                    return match[1].trim();
                }
            }

            const breadcrumb = doc.querySelector('.p-breadcrumbs-list li:last-child span');
            if (breadcrumb) {
                return breadcrumb.textContent.trim();
            }

            return "";
        } catch (error) {
            console.log("[Lolz Offtopic Renamer] Ошибка при запросе страницы оффтопика:", error);
            return "";
        }
    }

    function getOfftopicNameFromPage() {
        if (window.location.pathname === "/forums/8/" || window.location.pathname === "/forums/8") {
            const h1Element = document.querySelector('h1[title]');
            if (h1Element && h1Element.textContent.trim()) {
                return h1Element.textContent.trim();
            }
        }

        for (const selector of OFFTOPIC_LINK_SELECTORS) {
            const element = document.querySelector(selector);
            if (element && element.textContent.trim()) {
                return element.textContent.trim();
            }
        }

        return "";
    }

    function processTextNodes(node) {
        if (node.nodeName === 'SCRIPT' || node.nodeName === 'STYLE' || processedElements.has(node)) {
            return;
        }

        if (node.nodeType === Node.TEXT_NODE) {
            if (node.nodeValue.includes(originalOfftopicName)) {
                node.nodeValue = replaceOfftopicName(node.nodeValue);
                processedElements.add(node);
            }
        } else {
            for (let i = 0; i < node.childNodes.length; i++) {
                processTextNodes(node.childNodes[i]);
            }
        }
    }

    function updateDOMElements() {
        if (!originalOfftopicName || originalOfftopicName === NEW_OFFTOPIC_NAME) {
            return;
        }

        processTextNodes(document.body);

        OFFTOPIC_LINK_SELECTORS.forEach(selector => {
            document.querySelectorAll(selector).forEach(link => {
                if (!processedElements.has(link) && link.textContent.trim() === originalOfftopicName) {
                    link.textContent = NEW_OFFTOPIC_NAME;
                    processedElements.add(link);
                }
            });
        });

        TEXT_ELEMENT_SELECTORS.forEach(selector => {
            document.querySelectorAll(selector).forEach(element => {
                if (!processedElements.has(element) && element.textContent.trim() === originalOfftopicName) {
                    element.textContent = NEW_OFFTOPIC_NAME;
                    processedElements.add(element);
                }
            });
        });

        if (window.location.pathname === "/forums/8/" || window.location.pathname === "/forums/8") {
            document.querySelectorAll('h1').forEach(h1 => {
                if (!processedElements.has(h1) && h1.textContent.trim() === originalOfftopicName) {
                    h1.textContent = NEW_OFFTOPIC_NAME;
                    h1.setAttribute("title", NEW_OFFTOPIC_NAME);
                    processedElements.add(h1);
                }
            });

            if (document.title.includes(originalOfftopicName)) {
                document.title = replaceOfftopicName(document.title);
            }
        }

        document.querySelectorAll(`[data-cachedtitle*="${originalOfftopicName}"], [title*="${originalOfftopicName}"]`).forEach(el => {
            if (!processedElements.has(el)) {
                if (el.dataset.cachedtitle && el.dataset.cachedtitle.includes(originalOfftopicName)) {
                    el.dataset.cachedtitle = replaceOfftopicName(el.dataset.cachedtitle);
                }
                if (el.title && el.title.includes(originalOfftopicName)) {
                    el.title = replaceOfftopicName(el.title);
                }
                processedElements.add(el);
            }
        });
    }

    function patchDOMMethods() {
        const originalSetAttr = Element.prototype.setAttribute;
        Element.prototype.setAttribute = function(name, value) {
            if ((name === 'data-cachedtitle' || name === 'title') &&
                typeof value === 'string' &&
                originalOfftopicName) {
                value = replaceOfftopicName(value);
            }
            return originalSetAttr.call(this, name, value);
        };

        const originalGetAttr = Element.prototype.getAttribute;
        Element.prototype.getAttribute = function(name) {
            let value = originalGetAttr.call(this, name);
            if ((name === 'data-cachedtitle' || name === 'title') &&
                typeof value === 'string' &&
                originalOfftopicName) {
                value = replaceOfftopicName(value);
            }
            return value;
        };

        const originalTextContent = Object.getOwnPropertyDescriptor(Node.prototype, 'textContent');
        if (originalTextContent && originalTextContent.set) {
            Object.defineProperty(Node.prototype, 'textContent', {
                set(value) {
                    if (typeof value === 'string' && originalOfftopicName) {
                        value = replaceOfftopicName(value);
                    }
                    return originalTextContent.set.call(this, value);
                },
                get: originalTextContent.get
            });
        }
    }

    function observeDOMChanges() {
        const observer = new MutationObserver(() => {
            updateDOMElements();
        });

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

    async function initialize() {
        originalOfftopicName = getOfftopicNameFromPage();

        if (!originalOfftopicName) {
            originalOfftopicName = await fetchOfftopicName();
        }

        if (originalOfftopicName && originalOfftopicName !== NEW_OFFTOPIC_NAME) {
            patchDOMMethods();
            updateDOMElements();
            observeDOMChanges();
        }
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initialize);
    } else {
        initialize();
    }
})();