GeoGuessr Random Map

Adds a menu command and a button on the Community Maps page that redirect to a Random Map.

目前為 2025-10-21 提交的版本,檢視 最新版本

// ==UserScript==
// @name         GeoGuessr Random Map
// @namespace    https://github.com/asmodeo
// @icon         https://parmageo.vercel.app/gg.ico
// @version      1.0
// @description  Adds a menu command and a button on the Community Maps page that redirect to a Random Map.
// @author       Parma
// @match        https://www.geoguessr.com/*
// @grant        GM_registerMenuCommand
// @connect      www.geoguessr.com
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    let currentPath = window.location.pathname;

    // Redirect to map URL
    function redirectToMap(mapUrl) {
        if (mapUrl && typeof mapUrl === 'string') {
            window.location.href = 'https://www.geoguessr.com' + mapUrl.trim();
        } else {
            alert('Invalid map URL received.');
        }
    }

    // Fetch random map and redirect
    async function getRandomMapAndRedirect() {
        try {
            const response = await fetch('https://www.geoguessr.com/api/v3/social/maps/browse/random');
            if (!response.ok) throw new Error(`HTTP ${response.status}`);
            const map = await response.json();
            redirectToMap(map.url);
        } catch (error) {
            console.error('Random Map error:', error);
            alert('Failed to load a random map.');
        }
    }

    // Menu command
    GM_registerMenuCommand('Random Map', getRandomMapAndRedirect);

    // Button creation (styled like Liked Maps Widget) ---
    function createStyledButton() {
        const btn = document.createElement('button');
        btn.id = 'geoguessr-random-map-btn';
        btn.className = 'button_button__aR6_e button_link__LWagc button_variantPurple__qyK6c';
        btn.title = 'Load a random community map';
        btn.style.minWidth = '140px';
        btn.innerHTML = '<span class="button_label__2JvUx">Random Map</span>';
        btn.addEventListener('click', getRandomMapAndRedirect);
        return btn;
    }

    // Mounting logic
    function isCommunityMapsPage() {
        return window.location.pathname === '/maps/community';
    }

    function mountButton() {
        if (!isCommunityMapsPage()) return;

        const header = document.querySelector('.page-title_header__AHcKq.page-title_collapseOnMobile__n_EP_');
        if (!header) return;

        // Avoid duplicates
        if (header.querySelector(`#geoguessr-random-map-btn`)) return;

        const categoryMenu = header.querySelector('.tag-nav_categoryMenu__AUXWy');
        if (!categoryMenu) return;

        const button = createStyledButton();
        categoryMenu.parentNode.insertBefore(button, categoryMenu.nextSibling);
    }

    function unmountButton() {
        const btn = document.getElementById('geoguessr-random-map-btn');
        if (btn) btn.remove();
    }

    // Navigation handling
    function handleNavigation() {
        const newPath = window.location.pathname;
        if (newPath !== currentPath) {
            currentPath = newPath;
            if (!isCommunityMapsPage()) {
                unmountButton();
            }
        }
        if (isCommunityMapsPage()) {
            mountButton();
        }
    }

    const observer = new MutationObserver(handleNavigation);
    observer.observe(document, { subtree: true, childList: true });
    handleNavigation();
    setInterval(handleNavigation, 800);
})();