Pikabu Advertising Author Blocker

Блокирует статьи рекламных авторов на Pikabu и опционально блокирует блоки с фандрайзингом/играми

// ==UserScript==
// @name         Pikabu Advertising Author Blocker
// @namespace    http://tampermonkey.net/
// @version      1.3.0
// @description  Блокирует статьи рекламных авторов на Pikabu и опционально блокирует блоки с фандрайзингом/играми
// @match        https://pikabu.ru/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // --- Configuration ---
    const blockedAuthorsList = ["rabota.pikabu", "yandex.travel"]; // Список авторов
    const otherSelectorsToHide = ['.feed-games-carousel', '.story-block_type_fundraising']; // Селекторы других блоков для скрытия
    const blockOtherSelectors = true; // Включить/выключить блокировку других блоков

    // Используем Set для быстрой проверки авторов
    const blockedAuthorsSet = new Set(blockedAuthorsList);

    // CSS класс для скрытия элементов
    const hideClassName = 'paab-hidden-element';

    // --- CSS Injection ---
    // Добавляем стиль для скрытия элементов один раз
    function addHideStyle() {
        const styleId = 'paab-hide-style';
        if (document.getElementById(styleId)) {
            return; // Стиль уже добавлен
        }
        const css = `.${hideClassName} { display: none !important; }`;
        const style = document.createElement('style');
        style.id = styleId;
        style.textContent = css;
        // Добавляем в <head> для надежности
        (document.head || document.documentElement).appendChild(style);
    }

    // --- Core Blocking Logic ---
    function hideElements() {
        // 1. Блокировка статей авторов
        // Выбираем только те статьи, которые еще не скрыты
        const articles = document.querySelectorAll(`article[data-author-name]:not(.${hideClassName})`);
        articles.forEach(article => {
            const authorName = article.getAttribute("data-author-name");
            if (blockedAuthorsSet.has(authorName)) {
                article.classList.add(hideClassName);
                // console.log(`PAAB: Hiding article by ${authorName}`); // Для отладки
            }
        });

        // 2. Блокировка других блоков, если включено
        if (blockOtherSelectors) {
            otherSelectorsToHide.forEach(selector => {
                // Находим элементы по селектору, которые еще не скрыты
                const elements = document.querySelectorAll(`${selector}:not(.${hideClassName})`);
                elements.forEach(element => {
                    element.classList.add(hideClassName);
                    // console.log(`PAAB: Hiding element matching selector ${selector}`); // Для отладки
                });
            });
        }
    }

    // --- Initialization and Observation ---

    // 1. Добавляем CSS стиль
    addHideStyle();

    // 2. Запускаем функцию блокировки сразу и/или по готовности DOM
    // Это обрабатывает как уже существующие элементы, так и те, что появятся до установки MutationObserver
    if (document.readyState === 'loading') {
        // Еще загружается, ждем DOMContentLoaded
        document.addEventListener("DOMContentLoaded", hideElements);
    } else {
        // DOM уже готов или интерактивен
        hideElements();
    }

    // 3. Наблюдаем за изменениями в DOM для динамически добавляемого контента
    // MutationObserver будет вызывать hideElements при добавлении новых узлов
    // Это проще и надежнее, чем пытаться обрабатывать только добавленные узлы вручную
    const observer = new MutationObserver(mutations => {
        // Проверяем, были ли добавлены узлы, чтобы избежать лишних вызовов hideElements
        let nodesAdded = false;
        for (const mutation of mutations) {
            if (mutation.addedNodes.length > 0) {
                nodesAdded = true;
                break;
            }
        }
        // Если узлы были добавлены, запускаем проверку/скрытие
        if (nodesAdded) {
             // Небольшая задержка может помочь, если элементы добавляются пачками
             // setTimeout(hideElements, 50); // Раскомментируйте, если есть проблемы с "морганием"
             hideElements(); // Запускаем без задержки по умолчанию
        }
    });

    // Начинаем наблюдение за всем body (надежно для Pikabu)
    observer.observe(document.body, { childList: true, subtree: true });

    // Примечание: Отключать observer (observer.disconnect()) обычно не требуется в userscript'ах,
    // так как скрипт "умирает" вместе со страницей.

})();