Greasy Fork is available in English.
See where your guess was after each round!
当前为
// ==UserScript==
// @name Guess Peek (Geoguessr)
// @namespace alienperfect
// @version 1.0.7
// @description See where your guess was after each round!
// @author Alien Perfect
// @match https://www.geoguessr.com/*
// @icon https://www.google.com/s2/favicons?sz=32&domain=geoguessr.com
// @run-at document-start
// @grant GM_addStyle
// @grant GM_info
// @grant unsafeWindow
// ==/UserScript==
"use strict";
const searchRadius = 250000;
const scriptName = GM_info.script.name;
const GAMES_API = "https://www.geoguessr.com/api/v3/games/";
let streetViewService;
function main() {
console.log(`${scriptName} is running!`);
GM_addStyle(`
.peek-tooltip {
display: none;
position: absolute;
width: 120px;
background: #323232;
border-radius: 4px;
text-align: center;
padding: 0.5rem;
font-size: 0.9rem;
right: 50%;
bottom: 220%;
margin-right: -60px;
opacity: 90%;
z-index: 4;
}
.peek-tooltip:after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #323232 transparent transparent transparent;
}
[data-pano]:hover .peek-tooltip,
[data-no-pano]:hover .peek-tooltip {
display: block;
}
[data-pano] > :first-child {
cursor: pointer;
--border-color: #E91E63 !important;
--border-size-factor: 2 !important;
}
[data-no-pano] > :first-child {
cursor: initial;
--border-color: #323232 !important;
--border-size-factor: 1.5 !important;
}
`);
const _fetch = unsafeWindow.fetch;
unsafeWindow.fetch = async (resource, options) => {
const response = await _fetch(resource, options);
if (resource.includes(GAMES_API) && options.method === "POST") {
try {
if (!streetViewService) initStreetViewService();
const resp = await response.clone().json();
const guess = resp.player.guesses.pop();
const guessCoords = { lat: guess.lat, lng: guess.lng };
let pano;
let oldRadius;
let radius = searchRadius;
let proceed = true;
while (proceed) {
try {
pano = await streetViewService.getPanorama({
location: guessCoords,
radius: radius,
source: "outdoor",
preference: "nearest",
});
radius =
unsafeWindow.google.maps.geometry.spherical.computeDistanceBetween(
guessCoords,
pano.data.location.latLng,
);
// Avoid infinite loop!
if (oldRadius && radius >= oldRadius) break;
oldRadius = radius;
} catch (e) {
proceed = false;
}
}
if (pano) {
const url = getPanoUrl(pano.data.location.pano);
updateGuessMarker(url, radius);
} else {
updateGuessMarker();
}
} catch (e) {
console.error(`${scriptName} error: ${e}`);
}
}
return response;
};
}
function updateGuessMarker(url, radius) {
new MutationObserver(function () {
const flag = document.querySelector("[data-qa='correct-location-marker']");
const marker = document.querySelector("[data-qa='guess-marker']");
if (flag && marker) {
this.disconnect();
const [distance, units] = humanizeDistance(searchRadius);
const tooltip = document.createElement("div");
tooltip.className = "peek-tooltip";
tooltip.textContent = `No location was found within ${distance} ${units}!`;
if (url) {
const [distance, units] = humanizeDistance(radius);
tooltip.textContent = `Click to see the nearest location! [${distance} ${units}]`;
marker.setAttribute("data-pano", "true");
marker.addEventListener("click", () => {
window.open(url, "_blank");
});
} else {
marker.setAttribute("data-no-pano", "true");
}
marker.append(tooltip);
}
}).observe(document.body, {
childList: true,
subtree: true,
});
}
function initStreetViewService() {
streetViewService = new unsafeWindow.google.maps.StreetViewService();
}
function getPanoUrl(pano) {
return `https://www.google.com/maps/@?api=1&map_action=pano&pano=${pano}`;
}
function humanizeDistance(distance) {
if (distance >= 1000) return [(distance / 1000).toFixed(1), "km"];
return [distance.toFixed(1), "m"];
}
main();