Yandex CleanSearch

Блокировка страниц по домену и заголовкам, рекламы и прочего дерьма в яндекс.

安裝腳本?
作者推薦腳本

您可能也會喜歡 Yandex Wikipedia Info

安裝腳本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Yandex CleanSearch
// @namespace    http://tampermonkey.net/
// @version      3.3.1
// @description  Блокировка страниц по домену и заголовкам, рекламы и прочего дерьма в яндекс.
// @author       Zzakhar
// @match        https://yandex.ru/search/*
// @match        ya.ru/*
// @grant        GM_xmlhttpRequest
// @grant        GM_info
// @license      CC BY-NC-ND
// ==/UserScript==

(function() {
    'use strict';




    // auto redirect ya.ru/search to legit page
    function autoredirecttolegit() {
        if (window.location.hostname === "ya.ru" && window.location.pathname === "/search/") {
            const urlParams = new URLSearchParams(window.location.search);
            const text = urlParams.get('text');
            if (text) {
                window.location.href = `https://yandex.ru/search/?text=${text}`;
            }
        }
    }


    // Дб локал
    let blockedSites = JSON.parse(localStorage.getItem('blockedSites')) || [];
     function saveBlockedSites() {
        localStorage.setItem('blockedSites', JSON.stringify(blockedSites));
    }

    let blockedPropagandaCount = 0;
    let blockedAdsCount = 0;
    let blockedPropaganda = [];
    let isHidden = true;
    const currentVersion = GM_info.script.version;


    // Update notification
    function checkForUpdates() {
        GM_xmlhttpRequest({
            method: 'GET',
            url: versionCheckUrl,
            onload: function(response) {
                if (response.status === 200) {
                    const newVersionMatch = response.responseText.match(/@version\s+([0-9]+\.[0-9]+\.[0-9]+)/);
                    if (newVersionMatch) {
                        const newVersion = newVersionMatch[1];
                        if (newVersion !== currentVersion) {
                            alert(`Доступно обновление: версия ${newVersion}.`);
                        } else {
                            console.log('У вас самая последняя версия скрипта.');
                        }
                    }
                } else {
                    console.error('Ошибка при проверке обновлений:', response.statusText);
                }
            }
        });
    }

    //перенес все в 1 функцию для блока дерьма и рекламы
    function blockContainers() {
        if (window.location.hostname === 'ya.ru') {
            const marketFeed = document.querySelector("body > main > div:nth-child(3) > div > div > noindex > div.market-feed");
            if (marketFeed) {
                marketFeed.style.display = 'none';
            }
        }
        else if (window.location.hostname.includes('yandex.ru') && window.location.pathname.includes('search')) {
            const containerToHide = document.querySelector("body > main > div > div.main__container > div > div > div.content__left > div.VanillaReact.RelatedBottom");
            if (containerToHide) {
                containerToHide.style.display = 'none';
                console.log("Рекомендации скрыты.");
            }

            const searchResultAside = document.querySelector('#search-result-aside');
            const rsyaGuarantee = searchResultAside ? searchResultAside.querySelector('#rsya-guarantee') : null;

            //rsya-guarantee
            if (rsyaGuarantee) {
                const serpList = searchResultAside.querySelector('div.serp-list');
                if (serpList) {
                    serpList.style.display = 'none';
                    console.log("Контейнер serp-list удален.");
                }
            }
        }
    }


    // remove shit from search bar

    //deb for no lags
    function debounce(func, delay) {
        let debounceTimer;
        return function () {
            const context = this;
            const args = arguments;
            clearTimeout(debounceTimer);
            debounceTimer = setTimeout(() => func.apply(context, args), delay);
        };
    }

    // delete shit
    function removeBlockedSuggestions() {
        const suggestionList = document.querySelector('div.Root.Root_inited > div.HeaderDesktop > header > form > div.mini-suggest__popup.mini-suggest__popup_visible > ul.mini-suggest__popup-content');

        if (suggestionList) {
            const suggestionItems = suggestionList.querySelectorAll('li.mini-suggest__item');

            suggestionItems.forEach((item) => {
                const dataText = item.getAttribute('data-text');
                const anchor = item.querySelector('a.mini-suggest__item-link');
                let containsBlockedWord = false;
                let containsBlockedLink = false;
                if (dataText) {
                    containsBlockedWord = blockedSites.some(site => dataText.includes(site));
                }
                if (anchor) {
                    const href = anchor.href;
                    containsBlockedLink = blockedSites.some(site => href.includes(site));
                }
                const subtitleDiv = anchor?.querySelector('div.mini-suggest__item-content > div.mini-suggest__item-subtitle > span.mini-suggest__item-label'); // чтобы удалялась реклама из поиска
                if (subtitleDiv || containsBlockedWord || containsBlockedLink) {
                    //console.log("Удалено из поиска:", item.getAttribute('data-text'));
                    item.remove();
                }
            });
        }
    }


    // счетчик
    function updateBlockCounter() {
        const resultsContainer = document.querySelector('.main__center');
        let counterCard = resultsContainer.querySelector('.blocked-counter-card');

        if (!counterCard) {
            counterCard = document.createElement('div');
            counterCard.className = 'blocked-counter-card';
            counterCard.style.backgroundColor = '#300';
            counterCard.style.color = '#ffffff';
            counterCard.style.padding = '10px';
            counterCard.style.marginBottom = '10px';
            counterCard.style.border = '1px solid #600';
            counterCard.style.borderRadius = '5px';
            counterCard.style.maxWidth = '34%';
            counterCard.style.overflow = 'auto';
            resultsContainer.prepend(counterCard);
        }

        const counterText = `Заблокировано: ${blockedPropagandaCount} ненужного мусора и ${blockedAdsCount} рекламы`;
        let textElement = counterCard.querySelector('.counter-text');
        if (!textElement) {
            textElement = document.createElement('div');
            textElement.className = 'counter-text';
            counterCard.appendChild(textElement);
        }
        textElement.textContent = counterText;

        updateButtons(counterCard);
    }

    // смена кнопок
    function updateButtons(counterCard) {
        let showButton = counterCard.querySelector('.show-button');
        let removeButton = counterCard.querySelector('.remove-button');

        if (blockedPropagandaCount > 0 || blockedAdsCount > 0) {
            counterCard.style.display = 'flex';
            counterCard.style.justifyContent = 'space-between';
            counterCard.style.alignItems = 'center';

            if (isHidden) {
                if (!showButton) {
                    showButton = document.createElement('button');
                    showButton.className = 'show-button';
                    showButton.textContent = 'Показать';
                    showButton.style.backgroundColor = '#007bff';
                    showButton.style.color = '#ffffff';
                    showButton.style.border = 'none';
                    showButton.style.borderRadius = '5px';
                    showButton.style.padding = '5px 10px';
                    showButton.style.cursor = 'pointer';
                    showButton.style.marginLeft = '10px';
                    showButton.onclick = showBlockedPropaganda;

                    counterCard.appendChild(showButton);
                }

                if (removeButton) {
                    removeButton.remove();
                }
            } else {
                if (!removeButton) {
                    removeButton = document.createElement('button');
                    removeButton.className = 'remove-button';
                    removeButton.textContent = 'Убрать';
                    removeButton.style.backgroundColor = '#dc3545';
                    removeButton.style.color = '#ffffff';
                    removeButton.style.border = 'none';
                    removeButton.style.borderRadius = '5px';
                    removeButton.style.padding = '5px 10px';
                    removeButton.style.cursor = 'pointer';
                    removeButton.style.marginLeft = '10px';
                    removeButton.onclick = hideBlockedPropaganda;

                    counterCard.appendChild(removeButton);
                }

                if (showButton) {
                    showButton.remove();
                }
            }
        } else {
            if (showButton) {
                showButton.remove();
            }
            if (removeButton) {
                removeButton.remove();
            }
        }
    }

    // Мейн функция поиска
    function blockLinksAndAds() {
        const results = document.querySelectorAll('.serp-item');

        blockedPropagandaCount = 0;
        blockedAdsCount = 0;
        blockedPropaganda = [];

        results.forEach(result => {
            const isAd = checkIfAd(result);
            const link = result.querySelector('a.Link');
            const title = result.querySelector('.OrganicTitle-LinkText');

            if (link && title) {
                const href = link.href.toLowerCase();
                const titleText = title.textContent.toLowerCase();

                const isBlocked = blockedSites.some(site => href.includes(site) || titleText.includes(site));

                if (isAd) {
                    result.style.display = 'none';
                    blockedAdsCount++;
                } else if (isBlocked) {
                    result.style.display = 'none';
                    blockedPropagandaCount++;
                    blockedPropaganda.push(result);
                    console.log("Заблокирована дичь: ", result);
                }
            }
        });

        updateBlockCounter();
    }

    //проверка на рекламу, пофикшено 3.3
    function checkIfAd(result) {
        const adTextIndicators = ['реклама', 'баннер', 'advertise'];

        // Проверяем первый селектор для текущей версии
        const currentVersionTarget = result.querySelector(':scope > div > span');
        if (currentVersionTarget) {
            if (adTextIndicators.some(text => currentVersionTarget.textContent.toLowerCase().includes(text))) {
                return true; // Реклама найдена в текущей версии
            }
        }

        // Проверяем второй селектор для старой версии
        const oldVersionTarget = result.querySelector('div > div.Organic-ContentWrapper.organiccontent-wrapper > div.TextContainer.OrganicText.organictext.text-container.Typo.Typo_text_m.Typo_line_m > span > span');
        if (oldVersionTarget) {
            if (adTextIndicators.some(text => oldVersionTarget.textContent.toLowerCase().includes(text))) {
                return true; // Реклама найдена в старой версии
            }
        }

        return false; // Реклама не найдена
    }

    // Показать бтн
    function showBlockedPropaganda() {
        console.log("Показать");
        if (isHidden) {
            blockedPropaganda.forEach(prop => {
                prop.style.display = 'block';
            });
            isHidden = false;
            updateButtons(document.querySelector('.blocked-counter-card'));
        }
    }

    // Скрыть бтн
    function hideBlockedPropaganda() {
        console.log("Убрать");
        if (!isHidden) {
            blockedPropaganda.forEach(prop => {
                prop.style.display = 'none';
            });
            isHidden = true;
            updateButtons(document.querySelector('.blocked-counter-card'));
        }
    }





    // настройки


    function updateBlockedSitesList() {
        const list = document.getElementById('blockedSitesList');
        if (list){
            list.innerHTML = '';
            blockedSites.forEach(site => {
                const li = document.createElement('li');
                li.textContent = site;
                list.appendChild(li);
            });
        }
    }

    function resetBlockedSites() {
        blockedSites.length = 0;
        saveBlockedSites();
        updateBlockedSitesList();
        setTimeout(() => {
            location.reload(); // релоад
        }, 2000);
        showNotification('Все заблокированные сайты были очищены.');
    }

    function createPopup() {
        const popup = document.createElement('div');
        popup.className = 'custom-popup';

        // тёмная тема или нет
        const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
        const isDarkMode = darkModeMediaQuery.matches;

        // Применяем стили для темной или светлой темы
        popup.style.cssText = `
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        border-radius: 10px;
        padding: 20px;
        z-index: 9999;
        display: none;
        width: 300px;
        max-width: 90%;
        transition: transform 0.3s ease, opacity 0.3s ease;
        opacity: 0;
        ${isDarkMode ? `
            background-color: #0e1011;
            border: 2px solid #970e05; /* Красная рамка */
            box-shadow: 0 0 15px #4c0803, 0 0 30px #8b0903; /* Красное свечение */
            color: white;
        ` : `
            background-color: #f9f9f9;
            border: 2px solid #007BFF; /* Синяя рамка */
            box-shadow: 0 0 15px #007BFF, 0 0 30px #00A3FF; /* Синее свечение */
            color: black;
        `}
    `;

        // Определяем содержимое попапа в зависимости от текущего URL
        const currentUrl = window.location.href;
        if (currentUrl.includes('yandex.ru/search')) {
            popup.innerHTML = `
            <h3>Yandex CleanSearch</h3>
            <input type="text" id="siteInput" placeholder="Домен или заголовок (Например: rutube.ru)"
                   style="
                       width: 90%;
                       padding: 10px;
                       margin-bottom: 10px;
                       border: 2px solid ${isDarkMode ? '#970e05' : '#007BFF'};
                       background-color: ${isDarkMode ? '#0e1011' : 'white'};
                       color: ${isDarkMode ? 'white' : 'black'};
                       border-radius: 10px;
                       outline: none;
                       transition: border-color 0.3s ease, box-shadow 0.3s ease;
                   ">
            <div style="display: flex; justify-content: center; gap: 10px; margin-bottom: 10px;">
                <button id="blockSiteBtn" style="
                    background-color: red;
                    color: white;
                    border: none;
                    border-radius: 20px;
                    padding: 10px 20px;
                    cursor: pointer;
                    font-size: 14px;
                    transition: background-color 0.3s ease;">Заблокировать</button>
                <button id="unblockSiteBtn" style="
                    background-color: green;
                    color: white;
                    border: none;
                    border-radius: 20px;
                    padding: 10px 20px;
                    cursor: pointer;
                    font-size: 14px;
                    transition: background-color 0.3s ease;">Разблокировать</button>
            </div>
            <div style="display: flex; align-items: center; justify-content: space-between;">
                <h4 style="margin: 0;">Заблокированные сайты:</h4>
                <button id="resetBtn" style="
                    background-color: orange;
                    color: white;
                    border: none;
                    border-radius: 10px;
                    padding: 5px 10px;
                    cursor: pointer;
                    font-size: 12px;
                    transition: background-color 0.3s ease;">Сбросить</button>
            </div>
            <ul id="blockedSitesList" style="max-height: 80px; overflow-y: auto;"></ul>
            <span id="closePopupBtn" style="
                position: absolute;
                top: 10px;
                right: 10px;
                cursor: pointer;
                font-size: 20px;
                font-weight: bold;">&times;</span>
        `;
        } else if (currentUrl.includes('ya.ru')) {
            popup.innerHTML = `
            <div class="popup-container">
    <h3>Yandex CleanSearch</h3>
    <p>
        Скрипт был создан для TamperMonkey и написан для Javascript пользователем zzakhar. <br>
        Для использования скрипта начните поиск и введите запрос.
    </p>
    <p>
        Через несколько мгновений на странице поиска в левом верхнем углу появится иконка расширения. Нажмите на неё
        и начните конфигурацию. Вы можете блокировать как домены, так и ключевые слова.
    </p>
    <p>Спасибо за использование!</p>
    <span id="closePopupBtn" style="
        position: absolute;
        top: 10px;
        right: 10px;
        cursor: pointer;
        font-size: 20px;
        font-weight: bold;">
        &times;
    </span>
</div>
        `;
        }
        document.body.appendChild(popup);
        if (currentUrl.includes('yandex.ru/search')) {
            document.getElementById('blockSiteBtn').addEventListener('click', blockSite);
            document.getElementById('unblockSiteBtn').addEventListener('click', unblockSite);
            document.getElementById('resetBtn').addEventListener('click', resetBlockedSites);
        }
        document.getElementById('closePopupBtn').addEventListener('click', () => {
            popup.style.display = 'none';
        });
    }


    function showPopup() {
        const popup = document.querySelector('.custom-popup');
        popup.style.display = 'block';
        popup.style.opacity = '1';
        popup.style.transform = 'translate(-50%, -50%) scale(1.05)'; // анимация
        updateBlockedSitesList();
    }

   function showNotification(message) {
       const notification = document.createElement('div');
       notification.className = 'notification';
       notification.innerText = message;
       notification.style.cssText = `
        position: fixed;
        top: 20px;
        right: 20px;
        background-color: #4caf50; /* Зеленый цвет для успешного уведомления */
        color: white;
        padding: 15px;
        border-radius: 5px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
        z-index: 10000;
        opacity: 0;
        transform: translateY(-20px);
        transition: opacity 0.5s, transform 0.5s;
    `;

       document.body.appendChild(notification);
       setTimeout(() => {
           notification.style.opacity = '1';
           notification.style.transform = 'translateY(0)';
       }, 100);
       setTimeout(() => {
           notification.style.opacity = '0';
           notification.style.transform = 'translateY(-20px)';
           setTimeout(() => {
               document.body.removeChild(notification);
           }, 500);
       }, 3000);
   }

    function blockSite() {
        const site = document.getElementById('siteInput').value.toLowerCase();
        if (site && !blockedSites.includes(site)) {
            blockedSites.push(site);
            saveBlockedSites();
            updateBlockedSitesList();
            showNotification(`${site} has been blocked.`);
        } else {
            showNotification('Site is already blocked or input is empty.');
        }
    }

    function unblockSite() {
        const site = document.getElementById('siteInput').value.toLowerCase();
        const index = blockedSites.indexOf(site);
        if (index !== -1) {
            blockedSites.splice(index, 1);
            saveBlockedSites();
            showNotification(`${site} has been unblocked.`);
            updateBlockedSitesList()
            setTimeout(() => {
            location.reload();
            }, 2000);
        } else {
            showNotification('Site not found in blocked list.');
        }
    }

    function getHeaderLogo() {
        let headerLogo = document.querySelector('header.HeaderDesktop-Main .HeaderLogo');
        if (!headerLogo) {
            headerLogo = document.querySelector('main.body__wrapper .headline');//for ya.ru
        }
        return headerLogo;
    }

    // иконка для настроек
    function createIcon() {
        const headerLogo = getHeaderLogo();

        if (!headerLogo) {
            console.error('Логотип не найден');
            return;
        }

        headerLogo.removeAttribute('href'); // rem href
        headerLogo.style.cursor = 'default';

        const icon = document.createElement('img');
        icon.className = 'custom-icon';
        icon.src = 'https://avatars.mds.yandex.net/i?id=6a46c4318776cd395ef17ab922147471976ebe7d-3569718-images-thumbs&n=13';
        icon.id = 'YandexCleanSearch'; // ID
        icon.alt = 'FREEINTERNET';

        if (window.location.hostname === 'ya.ru') { // для ya.ru т.к. там надо чуть больше короче и чуть правее
            icon.style.cssText = `
            width: 2.2rem;
            height: 2.2rem;
            border-radius: 50%;
            cursor: pointer;
            position: relative;
            left: 30px; /* Смещение для ya.ru */
            vertical-align: middle;
            opacity: 0;
            transform: scale(0.9);
            transition: opacity 0.5s ease, transform 0.5s ease;
        `;
        } else {
            icon.style.cssText = `
            width: 36px;
            height: 36px;
            border-radius: 50%;
            cursor: pointer;
            position: relative;
            left: 25px;
            vertical-align: middle;
            opacity: 0;
            transform: scale(0.9);
            transition: opacity 0.5s ease, transform 0.5s ease;
        `;
        }
        headerLogo.insertBefore(icon,headerLogo.children[1])
        //headerLogo.appendChild(icon); - prev vers
        setTimeout(() => {
            icon.style.opacity = '1';
            icon.style.transform = 'scale(1)';
        }, 50);

        icon.addEventListener('click', showPopup);
    }
    function removeDuplicateIcon() {
        const elements = document.querySelectorAll('#YandexCleanSearch');
        if (elements.length > 1) {
            for (let i = 1; i < elements.length; i++) {
                elements[i].remove();
            }
            console.log("Лишние элементы #YandexCleanSearch были удалены.");
        }
    }


    window.addEventListener('load', function() {
        createPopup();
        createIcon();
        autoredirecttolegit()
        console.log("Создана иконка и заблокирована реклама(в контейнерах)");
    });


        //основной цикл
    const observer = new MutationObserver(() => {
        if (window.location.hostname !== 'ya.ru') { // NO YA.RU SHIT
            if (isHidden) {
                blockLinksAndAds();
            }
            // icon 2-ule check
            const suggestionPopup = document.querySelector('div.Root.Root_inited > div.HeaderDesktop > header > form > div.mini-suggest__popup');
            if (suggestionPopup && suggestionPopup.classList.contains('mini-suggest__popup_visible')) {
                removeBlockedSuggestions();
            }
            setTimeout(() => {
                const secondCheckIcon = document.querySelector('#YandexCleanSearch');
                if (!secondCheckIcon) {
                    createIcon();
                }
            }, 500);
            removeDuplicateIcon()
        } else {
                const marketFeed = document.querySelector("body > main > div:nth-child(3) > div > div > noindex > div");
                if (marketFeed) {
                    blockContainers()
                    console.log("market-feed удален.");
                }
            }

        });
    observer.observe(document.body, { childList: true, subtree: true });
    console.log('Yandex ClearSearch v',currentVersion,' launched');
})();