Geoguessr Location Retriever

Get the actual location Geoguessr gave you from the result screens. Works for games and streaks, solo and challenge.

От 03.11.2022. Виж последната версия.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @name         Geoguessr Location Retriever
// @match        https://www.geoguessr.com/*
// @description  Get the actual location Geoguessr gave you from the result screens. Works for games and streaks, solo and challenge.
// @version      1.1.3
// @author       victheturtle#5159
// @grant        none
// @license      MIT
// @icon         https://www.svgrepo.com/show/12218/find.svg
// @namespace    https://greatest.deepsurf.us/users/967692-victheturtle
// ==/UserScript==

let lastChecked = 0;
let checkedResults = false;

function getPins() {
    return document.querySelectorAll("[class*='map-pin_clickable']");
};

function panoIdDecoder(geoguessrPanoId) {
    let gsvPanoId = "";
    for (let i = 0; i < geoguessrPanoId.length; i+=2) {
        let seq = geoguessrPanoId.substring(i, i+2);
        gsvPanoId += String.fromCharCode(parseInt(seq, 16));
    }
    return gsvPanoId;
}

function linkOfLocation(round, copyToClipboard) {
    if (round.panoId == null) return null;
    let lat = round.lat;
    let lng = round.lng;
    let pid = panoIdDecoder(round.panoId);
    let rh = round.heading;
    let rp = round.pitch;
    let rz = round.zoom;
    let h = Math.round(round.heading * 100) / 100;
    let p = Math.round((90 + round.pitch) * 100) / 100;
    let z = Math.round((90 - round.zoom/2.75*90) * 10) / 10;
    const extra = `"countryCode":null,"stateCode":null,"extra":{"tags":[]}`;
    let link = `https://www.google.com/maps/@${lat},${lng},3a,${z}y,${h}h${(p==90)?"":","+p+"t"}/data=!3m6!1e1!3m4!1s${pid}!2e0!7i13312!8i6656`;
    let loc_json = `{"lat":${lat},"lng":${lng},"heading":${rh},"pitch":${rp},"panoId":"${pid}","zoom":${rz},${extra}}`;
    //console.log(link);
    //console.log(loc_json+",");
    if (copyToClipboard) {
        try {
            navigator.clipboard.writeText(loc_json+",");
        } catch (e) {console.log(e)};
    }
    return link;
}

function addFlagOnclicks(rounds) {
    let pin = getPins();
    for (let i = 0; i < pin.length; i++) {
        let link = linkOfLocation(rounds[(pin.length>1) ? pin[i].innerText-1 : rounds.length-1-i], pin.length==1);
        if (link != null) pin[i].onclick = function () {window.open(link, '_blank');};
    }
};

function addStreakChallengeOnclicks(rounds) {
    setTimeout(() => {
        let playersTable = document.querySelectorAll(".results_highscoreHeader__oQH32")[0].parentElement.children[1];
        let roundsTable = document.querySelectorAll(".results_highscoreHeader__oQH32")[1].parentElement;
        for (let i = 0; i < playersTable.children.length; i += 2) {
            playersTable.children[i].onclick = function () {addStreakChallengeOnclicks(rounds);};
        }
        for (let i = 1; i < roundsTable.children.length; i++) {
            let link = linkOfLocation(rounds[i-1], false);
            if (link != null) roundsTable.children[i].onclick = function () {window.open(link, '_blank');};
            roundsTable.children[i].style="cursor: pointer;";
        }
    }, 200);
}

function check() {
    const game_tag = location.pathname.split("/")[2];
    let api_url = "https://www.geoguessr.com/api/v3/games/"+game_tag;
    if (location.pathname.startsWith("/challenge") || !!document.querySelector(".switch_switch__LMkRx")) {
        api_url = "https://www.geoguessr.com/api/v3/challenges/"+game_tag+"/game";
    };
    fetch(api_url)
    .then(res => res.json())
    .then(out => {
        addFlagOnclicks(out.rounds.slice(0, out.player.guesses.length));
        if (out.type == "challenge" && out.mode == "streak") {
            let api_url2 = "https://www.geoguessr.com/api/v3/results/scores/"+game_tag+"/0/1";
            fetch(api_url2)
            .then(res => res.json())
            .then(out => addStreakChallengeOnclicks(out[0].game.rounds))
            .catch(err => { throw err });
        };
    }).catch(err => { throw err });

};

function doCheck() {
    if (!(location.pathname.startsWith("/results") || location.pathname.startsWith("/game") || location.pathname.startsWith("/challenge"))) return;
    let pinCount = getPins().length;
    if (pinCount == 0) {
        lastChecked = 0;
        checkedResults = false;
    } else if (pinCount != lastChecked || location.pathname.startsWith("/results") && !checkedResults && document.readyState == "complete") {
        lastChecked = pinCount;
        checkedResults = location.pathname.startsWith("/results");
        check();
    }
};

function checkSoon() {
    for (let timeout of [250,500,1200,2000,5000]) {
        setTimeout(doCheck, timeout);
    }
};

document.addEventListener('click', checkSoon, false);
document.addEventListener('keypress', (e) => { if (e.key === " ") checkSoon(); });
document.addEventListener('load', checkSoon(), false);