Search Engine Switcher

Adds quick links to other search engines (Google, Yandex, Bing, DuckDuckGo) on search result pages

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name         Search Engine Switcher
// @name:ru      Переключатель поисковых систем
// @namespace    https://github.com/abyss-soft/Search-Engine-Switcher
// @version      1.2.0
// @description  Adds quick links to other search engines (Google, Yandex, Bing, DuckDuckGo) on search result pages
// @description:ru Добавляет быстрые ссылки на другие поисковые системы (Яндекс, Google, Bing, DuckDuckGo) на страницах результатов поиска
// @author       abyss-soft
// @license      MIT
// @icon         https://www.google.com/favicon.ico
// @homepageURL  https://github.com/abyss-soft/Search-Engine-Switcher
// @supportURL   https://github.com/abyss-soft/Search-Engine-Switcher/issues
// @match        https://www.google.ru/*
// @match        https://www.google.com/*
// @match        https://yandex.ru/*
// @match        https://yandex.com/*
// @match        http://yandex.com/*
// @match        http://yandex.ru/*
// @match        https://ya.ru/*
// @match        https://duckduckgo.com/*
// @grant        none
// @run-at       document-end
// @noframes
// ==/UserScript==

(function () {
    'use strict';

    let lastSearchTerm = '';
    let yandexLinksAdded = false;
    let googleLinksAdded = false;
    let duckduckgoLinksAdded = false;

    // Получаем текст поиска
    function getSearchTerm() {
        if (location.hostname.includes('google')) {
            const urlParams = new URLSearchParams(window.location.search);
            return urlParams.get('q') || '';
        } else if (location.hostname.includes('yandex') || location.hostname.includes('ya.ru')) {
            const urlParams = new URLSearchParams(window.location.search);
            return urlParams.get('text') || '';
        } else if (location.hostname.includes('duckduckgo')) {
            const urlParams = new URLSearchParams(window.location.search);
            return urlParams.get('q') || '';
        }
        return '';
    }

    // Добавляем ссылки для Яндекса
    function addYandexLinks() {
        const searchEngineBlock = document.querySelector('.SerpFooter-LinksGroup_type_searchengines');
        if (!searchEngineBlock) {
            console.log('❌ Яндекс: не найден блок с ссылками на поисковые системы');
            return false;
        }

        const searchTerm = getSearchTerm();
        if (!searchTerm) {
            console.log('⚠️ Яндекс: не найден поисковый запрос');
            return false;
        }

        // Проверяем, что ссылки еще не добавлены
        if (yandexLinksAdded && lastSearchTerm === searchTerm) {
            console.log('ℹ️ Яндекс: ссылки уже добавлены для этого запроса');
            return false;
        }

        lastSearchTerm = searchTerm;
        yandexLinksAdded = true;

        // Удаляем старые ссылки
        const existingLinks = searchEngineBlock.querySelectorAll('[data-custom-search-link]');
        existingLinks.forEach(link => link.remove());
        const oldBing = document.querySelector('a[href^="//www.bing.com/search?q="]');
        if (oldBing) oldBing.remove();
        const oldGoogle = document.querySelector('a[href^="//www.google.ru/search?"]');
        if (oldGoogle) oldGoogle.remove();

        // Создаем новые ссылки
        const searchEngines = [
            { name: 'Google', url: `https://www.google.com/search?q=${encodeURIComponent(searchTerm)}` },
            { name: 'Bing', url: `https://www.bing.com/search?q=${encodeURIComponent(searchTerm)}` },
            { name: 'DuckDuckGo', url: `https://duckduckgo.com/?q=${encodeURIComponent(searchTerm)}` }
        ];

        searchEngines.forEach((engine, index) => {
            const link = document.createElement('a');
            link.href = engine.url;
            link.textContent = engine.name;
            link.setAttribute('data-custom-search-link', 'true');
            link.style.cssText = `
                color: #5f6368;
                text-decoration: none;
                display: flex;
                align-items: center;
                margin-left: 18px;
                line-height: 1.3;
                text-decoration: none;
                font-family: Arial, sans-serif;
            `;
            link.onmouseover = function () {
                this.style.textDecoration = 'underline';
            };
            link.onmouseout = function () {
                this.style.textDecoration = 'none';
            };
            searchEngineBlock.appendChild(link);
        });

        console.log('✅ Яндекс: добавлены ссылки на поисковые системы');
        return true;
    }

    // Добавляем ссылки для Google
    function addGoogleLinks() {
        const footer = document.querySelector('footer') ||
            document.querySelector('[role="contentinfo"]') ||
            document.querySelector('[jsname="U8b5nd"]');

        if (!footer) {
            console.log('❌ Google: не найден футер');
            return false;
        }

        const helpLink = Array.from(footer.querySelectorAll('a')).find(link => {
            const text = link.textContent.trim();
            const href = link.getAttribute('href') || '';
            return (text === 'Справка' || text === 'Help') && href.includes('support.google.com');
        });

        if (!helpLink) {
            console.log('❌ Google: не найдена ссылка "Справка" или "Help"');
            return false;
        }

        const searchTerm = getSearchTerm();
        if (!searchTerm) {
            console.log('⚠️ Google: не найден поисковый запрос');
            return false;
        }

        // Проверяем, что ссылки еще не добавлены
        if (googleLinksAdded && lastSearchTerm === searchTerm) {
            console.log('ℹ️ Google: ссылки уже добавлены для этого запроса');
            return false;
        }

        lastSearchTerm = searchTerm;
        googleLinksAdded = true;

        // Удаляем старые ссылки
        const existingContainer = document.querySelector('[data-custom-search-links]');
        if (existingContainer) {
            existingContainer.remove();
        }

        // Создаем блок для новых ссылок
        const newLinksContainer = document.createElement('div');
        newLinksContainer.setAttribute('data-custom-search-links', 'true');
        newLinksContainer.style.cssText = `
            display: inline-block;
            margin-right: 10px;
            margin-left: 8px;
        `;
        newLinksContainer.innerHTML = `
            <a href="https://yandex.ru/search/?text=${encodeURIComponent(searchTerm)}" style="color: #5f6368; text-decoration: none; font-size: 14px; line-height: 1.3; font-family: Arial, sans-serif;">Яндекс</a>
            <span style="color: #5f6368; margin: 0 3px; line-height: 1.3; font-family: Arial, sans-serif;">|</span>
            <a href="https://www.bing.com/search?q=${encodeURIComponent(searchTerm)}" style="color: #5f6368; text-decoration: none; font-size: 14px; line-height: 1.3; font-family: Arial, sans-serif;">Bing</a>
            <span style="color: #5f6368; margin: 0 3px; line-height: 1.3; font-family: Arial, sans-serif;">|</span>
            <a href="https://duckduckgo.com/?q=${encodeURIComponent(searchTerm)}" style="color: #5f6368; text-decoration: none; font-size: 14px; line-height: 1.3; font-family: Arial, sans-serif;">DuckDuckGo</a>
        `;

        // Добавляем обработчики наведения
        newLinksContainer.querySelectorAll('a').forEach(link => {
            link.onmouseover = function () {
                this.style.textDecoration = 'underline';
                this.style.color = '#1a0dab';
            };
            link.onmouseout = function () {
                this.style.textDecoration = 'none';
                this.style.color = '#5f6368';
            };
        });

        // Вставляем перед ссылкой "Справка"
        helpLink.parentElement.insertBefore(newLinksContainer, helpLink);

        console.log('✅ Google: добавлены ссылки на поисковые системы');
        return true;
    }

    // Добавляем ссылки для DuckDuckGo
    function addDuckDuckGoLinks() {
        // Ищем футер на DuckDuckGo
        const footer = document.querySelector('.footer') ||
            document.querySelector('footer') ||
            document.querySelector('[role="contentinfo"]');

        if (!footer) {
            console.log('❌ DuckDuckGo: не найден футер');
            return false;
        }

        const searchTerm = getSearchTerm();
        if (!searchTerm) {
            console.log('⚠️ DuckDuckGo: не найден поисковый запрос');
            return false;
        }

        // Проверяем, что ссылки еще не добавлены
        if (duckduckgoLinksAdded && lastSearchTerm === searchTerm) {
            console.log('ℹ️ DuckDuckGo: ссылки уже добавлены для этого запроса');
            return false;
        }

        lastSearchTerm = searchTerm;
        duckduckgoLinksAdded = true;

        // Удаляем старые ссылки
        const existingContainer = document.querySelector('[data-custom-search-links]');
        if (existingContainer) {
            existingContainer.remove();
        }

        // Создаем блок для новых ссылок
        const newLinksContainer = document.createElement('div');
        newLinksContainer.setAttribute('data-custom-search-links', 'true');
        newLinksContainer.style.cssText = `
            display: flex;
            gap: 12px;
            padding: 12px 0;
            border-top: 1px solid #e4e4e4;
            margin-top: 12px;
            font-size: 14px;
            line-height: 1.5;
            margin-left: 10%;
        `;
        newLinksContainer.innerHTML = `
            <span style="color: #717171; font-weight: 500;">Другие поисковики:</span>
            <a href="https://yandex.ru/search/?text=${encodeURIComponent(searchTerm)}" style="color: #717171; text-decoration: none;">Яндекс</a>
            <a href="https://www.google.com/search?q=${encodeURIComponent(searchTerm)}" style="color: #717171; text-decoration: none;">Google</a>
            <a href="https://www.bing.com/search?q=${encodeURIComponent(searchTerm)}" style="color: #717171; text-decoration: none;">Bing</a>
        `;

        // Добавляем обработчики наведения
        newLinksContainer.querySelectorAll('a').forEach(link => {
            link.onmouseover = function () {
                this.style.textDecoration = 'underline';
                this.style.color = '#227eda';
            };
            link.onmouseout = function () {
                this.style.textDecoration = 'none';
                this.style.color = '#717171';
            };
        });

        // Добавляем в футер
        footer.prepend(newLinksContainer);

        console.log('✅ DuckDuckGo: добавлены ссылки на поисковые системы');
        return true;
    }

    // Проверка и добавление ссылок
    function checkAndAddLinks() {
        const isGoogle = location.hostname.includes('google');
        const isYandex = location.hostname.includes('yandex') || location.hostname.includes('ya.ru');
        const isDuckDuckGo = location.hostname.includes('duckduckgo');

        // Проверяем, что это страница поиска
        const isGoogleSearch = isGoogle && location.pathname.includes('/search');
        const isYandexSearch = isYandex && (location.search.includes('text=') || location.pathname === '/search/');
        const isDuckDuckGoSearch = isDuckDuckGo && location.search.includes('q=');

        if (!isGoogleSearch && !isYandexSearch && !isDuckDuckGoSearch) {
            return;
        }

        if (isYandexSearch) {
            addYandexLinks();
        } else if (isGoogleSearch) {
            addGoogleLinks();
        } else if (isDuckDuckGoSearch) {
            addDuckDuckGoLinks();
        }
    }

    // Наблюдатель для Яндекса
    function initYandexObserver() {
        const observer = new MutationObserver(() => {
            const searchEngineBlock = document.querySelector('.SerpFooter-LinksGroup_type_searchengines');
            if (searchEngineBlock) {
                checkAndAddLinks();
                observer.disconnect();
            }
        });

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

    // Наблюдатель для Google
    function initGoogleObserver() {
        const observer = new MutationObserver(() => {
            const footer = document.querySelector('footer');
            if (footer && footer.querySelector('a[href*="support.google.com"]')) {
                checkAndAddLinks();
                observer.disconnect();
            }
        });

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

    // Наблюдатель для DuckDuckGo
    function initDuckDuckGoObserver() {
        const observer = new MutationObserver(() => {
            const footer = document.querySelector('footer');
            if (footer && location.search.includes('q=')) {
                checkAndAddLinks();
                observer.disconnect();
            }
        });

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

    // Инициализация
    function init() {
        // Сначала проверяем, есть ли элементы
        if (document.querySelector('.SerpFooter-LinksGroup_type_searchengines')) {
            checkAndAddLinks();
        } else if (location.hostname.includes('yandex') || location.hostname.includes('ya.ru')) {
            initYandexObserver();
        }

        if (document.querySelector('footer') && document.querySelector('footer a[href*="support.google.com"]')) {
            checkAndAddLinks();
        } else if (location.hostname.includes('google')) {
            initGoogleObserver();
        }

        if (document.querySelector('footer') && location.hostname.includes('duckduckgo')) {
            checkAndAddLinks();
        } else if (location.hostname.includes('duckduckgo')) {
            initDuckDuckGoObserver();
        }

        // Проверка каждые 2 секунды на случай, если элементы появятся позже
        setInterval(() => {
            if (!yandexLinksAdded || !googleLinksAdded || !duckduckgoLinksAdded) {
                checkAndAddLinks();
            }
        }, 2000);
    }

    // Запуск
    setTimeout(init, 1000);
})();