🎉 欢迎访问GreasyFork.Org 镜像站!本镜像站由公众号【爱吃馍】搭建,用于分享脚本。联系邮箱📮

Greasy fork 爱吃馍镜像

Greasy Fork is available in English.

📂 缓存分发状态(共享加速已生效)
🕒 页面同步时间:2026/01/09 15:40:15
🔄 下次更新时间:2026/01/09 16:40:15
手动刷新缓存

Bypass Google Search Region

Add button to bypass Google Search region

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

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

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

🚀 安装遇到问题?关注公众号获取帮助

公众号二维码

扫码关注【爱吃馍】

回复【脚本】获取最新教程和防失联地址

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

🚀 安装遇到问题?关注公众号获取帮助

公众号二维码

扫码关注【爱吃馍】

回复【脚本】获取最新教程和防失联地址

// ==UserScript==
// @name         Bypass Google Search Region
// @namespace    http://tampermonkey.net/
// @version      2.9
// @description  Add button to bypass Google Search region
// @license      MIT
// @match        *://*.google.com/search*
// @match        *://*.google.co.kr/search*
// @match        *://*.google.*/search*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    const DESKTOP_ID = 'bypass-desktop-button';
    const MOBILE_ID = 'bypass-mobile-button';
    const ACTIVE_SAFE = 'off';
    const DEFAULT_GL = 'GH';  // 기본값: Ghana

    // 지역 코드와 이름을 매핑한 객체 (알파벳 순으로 정렬)
    const REGION_OPTIONS = {
        'CN': 'China',
        'GH': 'Ghana',
        'JP': 'Japan',
        'KR': 'Korea',
        'US': 'USA'
    };

    // 페이지 언어를 확인 (ko, en만 체크)
    function getPageLanguage() {
        const lang = navigator.language || navigator.userLanguage;
        if (lang.startsWith('ko')) return 'ko';
        if (lang.startsWith('en')) return 'en';
        return null;
    }

    // 쿠키 설정을 안정적으로 수행
    function ensureBypassCookie(gl) {
        const expectedValue = `gl=${gl}:safe=${ACTIVE_SAFE}`;
        const maxAge = 60 * 60 * 24 * 365 * 5; // 5년

        const hasPrefCookie = document.cookie.includes(`PREF=${expectedValue}`);
        if (!hasPrefCookie) {
            const cookieValue = `PREF=${expectedValue}; max-age=${maxAge}; path=/`;
            document.cookie = `${cookieValue}; domain=.google.com`;
            document.cookie = `${cookieValue}; domain=${window.location.hostname}`;
        }
    }

    // 우회 검색을 적용하는 함수
    function applyBypass(gl) {
        if (!gl) return;

        const url = new URL(window.location.href);
        url.searchParams.set('gl', gl);  // 선택한 국가 코드로 gl 파라미터 설정
        url.searchParams.set('safe', ACTIVE_SAFE);
        url.searchParams.set('pws', '0'); // 개인화된 검색 결과 비활성화

        ensureBypassCookie(gl);

        try {
            sessionStorage.setItem('selected_gl', gl); // 현재 선택한 국가
            sessionStorage.setItem('last_used_gl', gl); // 마지막 우회에 사용한 국가
            sessionStorage.setItem('google_settings_safe', ACTIVE_SAFE);
        } catch (e) {}

        // 페이지 리디렉션
        window.location.href = url.toString();
    }

    // 우회 검색을 해제하는 함수
    function clearBypass() {
        const url = new URL(window.location.href);
        url.searchParams.delete('gl');
        url.searchParams.delete('safe');
        url.searchParams.delete('pws');

        // 쿠키와 로컬 스토리지에서 설정 삭제
        document.cookie = `PREF=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=.google.com`;
        document.cookie = `PREF=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=${window.location.hostname}`;

        try {
            sessionStorage.removeItem('selected_gl'); // 선택한 국가 초기화
            sessionStorage.removeItem('google_settings_safe');
            // last_used_gl은 유지 (sessionStorage)
        } catch (e) {}

        // 페이지 리디렉션
        window.location.href = url.toString();
    }

    // 현재 우회 상태를 확인하는 함수
    function isBypassActive() {
        const url = new URL(window.location.href);
        return url.searchParams.has('gl') && url.searchParams.get('safe') === ACTIVE_SAFE;
    }

    // 우회 상태를 토글하는 함수
    function toggleBypass() {
        if (isBypassActive()) {
            clearBypass();
        } else {
            // 마지막 사용 gl을 가져오되, 없으면 기본값(GH) 사용
            let gl = sessionStorage.getItem('last_used_gl');
            if (!gl) {
                gl = DEFAULT_GL;
            }
            applyBypass(gl);
        }
    }

    // 버튼 텍스트를 현재 언어 및 상태에 따라 업데이트
    function updateText(btn) {
        if (btn) {
            const lang = getPageLanguage();
            const bypassText = lang === 'ko' ? '우회 검색' : 'Bypass Search';
            const clearText = lang === 'ko' ? '우회 해제' : 'Remove Bypass';
            btn.textContent = isBypassActive() ? clearText : bypassText;
        }
    }

    // 팝업 닫기 핸들러 (중복 등록 방지용으로 외부에 정의)
    function onClickOutside(e) {
        const popup = document.getElementById('gl-popup');
        if (popup && !popup.contains(e.target)) {
            popup.remove();
            document.removeEventListener('click', onClickOutside);
        }
    }

    // 지역 선택 팝업 생성
    function createRegionPopup(triggerEl) {
        const existing = document.getElementById('gl-popup');
        if (existing) existing.remove();

        const popup = document.createElement('div');
        popup.id = 'gl-popup';
        popup.style.position = 'absolute';
        popup.style.background = '#fff';
        popup.style.border = '1px solid #ccc';
        popup.style.zIndex = '9999';
        popup.style.fontSize = '14px';
        popup.style.boxShadow = '0 2px 6px rgba(0,0,0,0.2)';
        popup.style.boxSizing = 'border-box';

        const currentGl = sessionStorage.getItem('selected_gl');

        Object.entries(REGION_OPTIONS).forEach(([code, name]) => {
            const item = document.createElement('div');
            item.textContent = name;
            item.style.padding = '6px 12px';
            item.style.cursor = 'pointer';
            item.style.fontWeight = (code === currentGl) ? 'bold' : 'normal'; // 현재 선택 강조
            item.onclick = () => {
                sessionStorage.setItem('selected_gl', code); // 선택된 지역 기억
                applyBypass(code); // 선택된 지역으로 우회 적용
            };
            popup.appendChild(item);
        });

        document.body.appendChild(popup);

        const popupRect = popup.getBoundingClientRect();
        const popupWidth = popupRect.width;
        const popupHeight = popupRect.height;
        const triggerRect = triggerEl.getBoundingClientRect();

        let popupTop = triggerRect.bottom + window.scrollY;
        const popupLeftInit = triggerRect.left + window.scrollX;
        const windowHeight = window.innerHeight;

        // 화면 아래로 넘는 경우, 팝업을 위쪽에 띄움
        if (popupTop + popupHeight > window.scrollY + windowHeight) {
            popupTop = triggerRect.top + window.scrollY - popupHeight;
        }

        // 좌우 위치 조정 (스크롤 생기지 않도록)
        const maxLeft = window.innerWidth - popupWidth - 10;
        let popupLeft = popupLeftInit;
        if (popupLeft > maxLeft) {
            popupLeft = Math.max(maxLeft, 0);
        }

        popup.style.top = `${popupTop}px`;
        popup.style.left = `${popupLeft}px`;

        // 클릭 외부시 팝업 닫기 이벤트 등록 (중복 등록 방지)
        document.removeEventListener('click', onClickOutside);
        document.addEventListener('click', onClickOutside);
    }

    // 데스크톱 버튼 추가
    function addDesktopButton() {
        const interval = setInterval(() => {
            const tool = document.querySelector('#hdtb-tls');
            if (tool && tool.parentElement && !document.getElementById(DESKTOP_ID)) {
                clearInterval(interval);
                const btn = document.createElement('div');
                btn.id = DESKTOP_ID;
                btn.className = 'hdtb-mitem';
                btn.style.cursor = 'pointer';
                btn.style.userSelect = 'none';
                updateText(btn);  // 버튼 텍스트를 현재 언어에 맞게 업데이트
                btn.onclick = toggleBypass;

                const arrow = document.createElement('div');
                arrow.className = 'hdtb-mitem';
                arrow.style.cursor = 'pointer';
                arrow.style.marginLeft = '6px';
                arrow.style.marginRight = '12px';  // 화살표와 버튼 사이에 여유 공간 추가
                arrow.textContent = '▼';
                arrow.onclick = (e) => {
                    e.stopPropagation();
                    createRegionPopup(arrow);
                };

                tool.parentElement.insertBefore(arrow, tool.nextSibling);
                tool.parentElement.insertBefore(btn, arrow);
            }
        }, 500);
    }

    // 모바일 버튼 추가 (개선, 캡처 단계 + stopPropagation)
    function addMobileButton() {
        if (document.getElementById(MOBILE_ID)) return;

        const lang = getPageLanguage();
        const label = lang === 'ko' ? '고급검색' : (lang === 'en' ? 'Advanced Search' : null);
        if (!label) return;

        const advancedSearch = Array.from(document.querySelectorAll('a')).find(a => a.textContent.trim() === label);
        if (!advancedSearch || !advancedSearch.parentElement) return;

        const clone = advancedSearch.parentElement.cloneNode(true);
        const link = clone.querySelector('a');
        if (!link) return;

        clone.id = MOBILE_ID;
        updateText(link);  // 버튼 텍스트를 현재 언어에 맞게 업데이트
        link.style.cursor = 'pointer';
        link.removeAttribute('href');

        // 캡처단계에서 클릭 차단
        link.addEventListener(
          'click',
          (e) => {
            e.preventDefault();
            e.stopPropagation();
            if (typeof e.stopImmediatePropagation === 'function') e.stopImmediatePropagation();
            toggleBypass();
          },
          true
        );

        const arrow = document.createElement('a');
        arrow.textContent = '▼';
        arrow.style.marginLeft = '6px';
        arrow.style.marginRight = '12px';  // 화살표와 버튼 사이에 여유 공간 추가
        arrow.style.cursor = 'pointer';
        arrow.onclick = (e) => {
            e.stopPropagation();
            createRegionPopup(arrow);
        };
        advancedSearch.parentElement.insertAdjacentElement('afterend', clone);
        clone.insertAdjacentElement('afterend', arrow);
    }

    // 쿠키 주기적 유지
    function keepBypassCookieAlive() {
        const gl = sessionStorage.getItem('last_used_gl');
        if (gl) ensureBypassCookie(gl);
    }

    window.addEventListener('load', keepBypassCookieAlive);
    setInterval(keepBypassCookieAlive, 60 * 60 * 1000); // 1시간마다

    // DOM 변화 감지하여 모바일 버튼 계속 감시
    const observer = new MutationObserver(() => {
        addMobileButton();
    });
    observer.observe(document.body, { childList: true, subtree: true });

    // 초기 실행
    addDesktopButton();
    addMobileButton();
})();