您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds Apple Look Around to GeoGuessr
- // ==UserScript==
- // @name AppleGuessr
- // @namespace https://gf.qytechs.cn/en/users/946023-mistystar
- // @version 2.1
- // @description Adds Apple Look Around to GeoGuessr
- // @author Mistystar (Mistystar#2205, https://github.com/kittenz) & stocc (stocc#2919, https://github.com/stocc)
- // @match https://www.geoguessr.com/*
- // @icon https://www.google.com/s2/favicons?sz=64&domain=geoguessr.com
- // @grant none
- // @license MIT
- // @run-at document-start
- // @require https://cdn.jsdelivr.net/npm/protobufjs@7.0.0/dist/protobuf.js
- // @require https://cdn.jsdelivr.net/npm/long@5/umd/index.js
- // @require https://cdn.jsdelivr.net/gh/chebum/heic2any@2c517409ac73e86e92560312b58fcfd565ad7393/dist/heic2any.min.js
- // ==/UserScript==
- /******/ (() => { // webpackBootstrap
- /******/ "use strict";
- /******/ var __webpack_modules__ = ({
- /***/ 297:
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
- // Blatantly stolen from https://github.com/sk-zk/lookaround-map/blob/main/static/auth.js
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
- };
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
- };
- var _Authenticator_instances, _Authenticator_generateSessionId, _Authenticator_generateTokenP3;
- Object.defineProperty(exports, "__esModule", ({ value: true }));
- exports.Authenticator = void 0;
- const options_1 = __webpack_require__(944);
- const proto_1 = __webpack_require__(224);
- const TOKEN_P1 = "4cjLaD4jGRwlQ9U";
- const MANIFEST_URL = "https://gspe35-ssl.ls.apple.com/geo_manifest/dynamic/config?application=geod" +
- "&application_version=1&country_code=US&hardware=MacBookPro11,2&os=osx" +
- "&os_build=20B29&os_version=11.0.1";
- var GLOBAL_TOKENP2 = undefined;
- class Authenticator {
- constructor() {
- _Authenticator_instances.add(this);
- this.sessionId = null;
- }
- init() {
- return __awaiter(this, void 0, void 0, function* () {
- yield this.refreshCredentials();
- });
- }
- refreshCredentials() {
- return __awaiter(this, void 0, void 0, function* () {
- this.sessionId = __classPrivateFieldGet(this, _Authenticator_instances, "m", _Authenticator_generateSessionId).call(this);
- });
- }
- hasSession() {
- return this.sessionId != null;
- }
- getTokenP2() {
- return __awaiter(this, void 0, void 0, function* () {
- if (GLOBAL_TOKENP2 == undefined) {
- GLOBAL_TOKENP2 = (yield this.getResourceManifest()).tokenP2;
- }
- return GLOBAL_TOKENP2;
- });
- }
- authenticateUrl(url) {
- return __awaiter(this, void 0, void 0, function* () {
- const urlObj = new URL(url);
- let p2 = yield this.getTokenP2();
- const tokenP3 = __classPrivateFieldGet(this, _Authenticator_instances, "m", _Authenticator_generateTokenP3).call(this);
- const token = TOKEN_P1 + p2 + tokenP3;
- const timestamp = Math.floor(Date.now() / 1000) + 4200;
- const separator = urlObj.search ? "&" : "?";
- let urlPath = urlObj.pathname;
- if (urlObj.search) {
- urlPath += urlObj.search;
- }
- const plaintext = `${urlPath}${separator}sid=${this.sessionId}${timestamp}${tokenP3}`;
- const plaintextBytes = new TextEncoder().encode(plaintext);
- const key = yield sha256(token);
- const ciphertext = yield aes(key, plaintextBytes);
- const ciphertextB64 = btoa(String.fromCharCode(...new Uint8Array(ciphertext)));
- const ciphertextUrl = encodeURIComponent(ciphertextB64);
- const accessKey = `${timestamp}_${tokenP3}_${ciphertextUrl}`;
- const final = `${url}${separator}sid=${this.sessionId}&accessKey=${accessKey}`;
- return final;
- });
- }
- getResourceManifest() {
- return __awaiter(this, void 0, void 0, function* () {
- const response = yield fetch(options_1.CORS_PROXY + MANIFEST_URL);
- let pb = yield response.arrayBuffer();
- return yield proto_1.default.parseResourceManifest(pb);
- });
- }
- }
- exports.Authenticator = Authenticator;
- _Authenticator_instances = new WeakSet(), _Authenticator_generateSessionId = function _Authenticator_generateSessionId() {
- let id = "";
- for (let i = 0; i < 40; i++) {
- const digit = (Math.random() * 10) | 0;
- id += digit.toString();
- }
- return id;
- }, _Authenticator_generateTokenP3 = function _Authenticator_generateTokenP3() {
- const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
- let token = "";
- for (let i = 0; i < 16; i++) {
- const idx = (Math.random() * chars.length) | 0;
- token += chars[idx];
- }
- return token;
- };
- function sha256(message) {
- return __awaiter(this, void 0, void 0, function* () {
- const msgBuffer = new TextEncoder().encode(message);
- const hashBuffer = yield window.crypto.subtle.digest("SHA-256", msgBuffer);
- return hashBuffer;
- });
- }
- function aes(key, encodedMessage) {
- return __awaiter(this, void 0, void 0, function* () {
- const iv = new Uint8Array(16); // 16 zeroes
- const cryptoKey = yield window.crypto.subtle.importKey("raw", key, { name: "AES-CBC" }, true, ["encrypt"]);
- return yield window.crypto.subtle.encrypt({
- name: "AES-CBC",
- iv,
- }, cryptoKey, encodedMessage);
- });
- }
- //# sourceMappingURL=auth.js.map
- /***/ }),
- /***/ 97:
- /***/ ((__unused_webpack_module, exports) => {
- Object.defineProperty(exports, "__esModule", ({ value: true }));
- const TILE_SIZE = 256;
- class GeoUtils {
- static haversineDistance(coords1, coords2) {
- function toRad(x) {
- return x * Math.PI / 180;
- }
- var lon1 = coords1[0];
- var lat1 = coords1[1];
- var lon2 = coords2[0];
- var lat2 = coords2[1];
- var R = 6371; // km
- var x1 = lat2 - lat1;
- var dLat = toRad(x1);
- var x2 = lon2 - lon1;
- var dLon = toRad(x2);
- var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
- Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
- Math.sin(dLon / 2) * Math.sin(dLon / 2);
- var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
- var d = R * c;
- return d;
- }
- static radians_to_degrees(radians) {
- var pi = Math.PI;
- return radians * (180 / pi);
- }
- static headingFromUnknowns(unknown10, unknown11) {
- let westmin = 1;
- let westmax = 2159;
- let eastmin = 16383; // looking (north/south) and very slightly east
- let eastmax = 14318; // looking slightly (north/south) directly east
- let northmin = 8204; // this is likely lower
- let northmax = 6054;
- let southmin = 8204; // this is likely lower
- let southmax = 10173;
- var ew = 0;
- if (unknown10 < westmax) {
- ew = -((unknown10 - westmin) / (westmax - westmin));
- }
- else if (unknown10 > eastmax) {
- ew = ((unknown10 - eastmin) / (eastmax - eastmin));
- }
- var ns = 0;
- if (unknown11 <= northmin) {
- ns = ((unknown11 - northmin) / (northmax - northmin));
- }
- else {
- ns = -((unknown11 - southmin) / (southmax - southmin));
- }
- var r = GeoUtils.radians_to_degrees(Math.atan2(ew, ns));
- if (r < 0) {
- r += 360;
- }
- return r;
- }
- static mercator_to_wgs84(x, y) {
- let lat = (2 * Math.atan(Math.exp((y - 128) / -(256 / (2 * Math.PI)))) - Math.PI / 2) / (Math.PI / 180);
- let lon = (x - 128) / (256 / 360);
- return [lat, lon];
- }
- static tile_coord_to_wgs84(x, y, z) {
- let scale = 1 << z;
- let pixel_coord = [x * TILE_SIZE, y * TILE_SIZE];
- let world_coord = [pixel_coord[0] / scale, pixel_coord[1] / scale];
- let lat_lon = GeoUtils.mercator_to_wgs84(world_coord[0], world_coord[1]);
- return [lat_lon[0], lat_lon[1]];
- }
- static protobuf_tile_offset_to_wsg84(x_offset, y_offset, tile_x, tile_y) {
- let pano_x = tile_x + (x_offset / 64.0) / (TILE_SIZE - 1);
- let pano_y = tile_y + (255 - (y_offset / 64.0)) / (TILE_SIZE - 1);
- let coords = GeoUtils.tile_coord_to_wgs84(pano_x, pano_y, 17);
- return coords;
- }
- static wgs84_to_mercator(lat, lon) {
- var siny = Math.sin(lat * Math.PI / 180);
- siny = Math.min(Math.max(siny, -0.9999), 0.9999);
- return [
- TILE_SIZE * (0.5 + lon / 360),
- TILE_SIZE * (0.5 - Math.log((1 + siny) / (1 - siny)) / (4 * Math.PI))
- ];
- }
- static wgs84_to_tile_coord(lat, lon, zoom) {
- var scale = 1 << zoom;
- var world_coord = this.wgs84_to_mercator(lat, lon);
- var tile_coord = [
- Math.floor((world_coord[0] * scale) / TILE_SIZE),
- Math.floor((world_coord[1] * scale) / TILE_SIZE)
- ];
- return tile_coord;
- }
- static heading(coords1, coords2) {
- try {
- let c1 = new google.maps.LatLng(coords1[0], coords1[1]);
- let c2 = new google.maps.LatLng(coords2[0], coords2[1]);
- let result = google.maps.geometry.spherical.computeHeading(c1, c2);
- if (result < 0) {
- result += 360;
- }
- return result;
- }
- catch (e) {
- console.log(e);
- }
- }
- }
- exports["default"] = GeoUtils;
- //# sourceMappingURL=geoutils.js.map
- /***/ }),
- /***/ 590:
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
- // ==UserScript==
- // @name AppleGuessr
- // @namespace https://gf.qytechs.cn/en/users/946023-mistystar
- // @version 2.1
- // @description Adds Apple Look Around to GeoGuessr
- // @author Mistystar (Mistystar#2205, https://github.com/kittenz) & stocc (stocc#2919, https://github.com/stocc)
- // @match https://www.geoguessr.com/*
- // @icon https://www.google.com/s2/favicons?sz=64&domain=geoguessr.com
- // @grant none
- // @license MIT
- // @run-at document-start
- // @require https://cdn.jsdelivr.net/gh/chebum/heic2any@master/dist/heic2any.min.js
- // @require https://cdn.jsdelivr.net/npm/protobufjs@7.0.0/dist/protobuf.js
- // @require https://cdn.jsdelivr.net/npm/long@5/umd/index.js
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
- };
- Object.defineProperty(exports, "__esModule", ({ value: true }));
- // ==/UserScript==
- /*
- CREDITS
- Massive thank you to the following people:
- - skzk#8049 - Without https://github.com/sk-zk/lookaround-map this script would not have been possible to make
- - Jupaoqq#7742 - I learned a lot from looking at Unity Script's source code
- - mattisinthesky#1294 or kowalski - For hosting the lookaround-map in Heroku and helping with issues
- - efefury#0519 and Apfeloxid#1368 - For making the Take A Look Around Germany map
- */
- // BEGIN CODE SECTION
- const Options = __webpack_require__(944);
- const Lookaround = __webpack_require__(215);
- const lookaround_1 = __webpack_require__(215);
- const geoutils_1 = __webpack_require__(97);
- protobuf.util.Long = Long;
- protobuf.configure();
- const MENU_HTML = (/* unused pure expression or super */ null && (`
- <div class="start-standard-game_settings__x94PU">
- <div class="game-settings_default__DIBgs">
- <div class="game-settings_toggleLabel__nipwm">
- <div class="label_sizeXSmall__mFnrR">Apple Look Around</div>
- <span></span>
- </div>
- <div>
- <input type="checkbox" class="apple-look-around-toggle" checked>
- </div>
- </div>
- </div>
- `));
- const isGamePage = () => location.pathname.startsWith("/challenge/") || location.pathname.startsWith("/results/") ||
- location.pathname.startsWith("/game/") || location.pathname.startsWith("/battle-royale/") ||
- location.pathname.startsWith("/duels/") || location.pathname.startsWith("/team-duels/") ||
- location.pathname.startsWith("/bullseye/") ||
- location.pathname.startsWith("/live-challenge/");
- function overrideOnLoad(googleScript, observer, overrider) {
- const oldOnload = googleScript.onload;
- googleScript.onload = (event) => {
- const google = window.google;
- if (google) {
- observer.disconnect();
- overrider(google);
- }
- if (oldOnload) {
- oldOnload.call(googleScript, event);
- }
- };
- }
- function grabGoogleScript(mutations) {
- for (const mutation of mutations) {
- for (const newNode of mutation.addedNodes /* Please shut up, it works in JS so it must work here as well */) {
- const asScript = newNode;
- if (asScript && asScript.src && asScript.src.startsWith("https://maps.googleapis.com/")) {
- return asScript;
- }
- }
- }
- return null;
- }
- function injecter(overrider) {
- if (document.documentElement) {
- injecterCallback(overrider);
- }
- else {
- alert("Script didn't load, refresh to try loading the script");
- }
- }
- function injecterCallback(overrider) {
- new MutationObserver((mutations, observer) => {
- const googleScript = grabGoogleScript(mutations);
- if (googleScript) {
- overrideOnLoad(googleScript, observer, overrider);
- }
- }).observe(document.documentElement, { childList: true, subtree: true });
- }
- // End Script injection --------------------------------------------------------------s
- function injectMenu() {
- const inject = () => {
- if (document.querySelector(".apple-look-around-toggle") !== null)
- return;
- const settingsSection = document.querySelector('.section_sectionMedium__yXgE6');
- if (settingsSection === null)
- return;
- settingsSection.insertAdjacentHTML("beforeend", MENU_HTML);
- const checkbox = document.querySelector(".apple-look-around-toggle");
- if (checkbox) {
- let isChecked = localStorage.getItem("applelookaroundchecked");
- if (isChecked === null) {
- checkbox.checked = false;
- localStorage.setItem("applelookaroundchecked", "false");
- }
- else if (isChecked === "true") {
- checkbox.checked = true;
- }
- else {
- checkbox.checked = false;
- }
- checkbox.addEventListener("change", (event) => {
- if (event.currentTarget === null)
- return;
- if (event.currentTarget.checked) {
- localStorage.setItem("applelookaroundchecked", "true");
- }
- else {
- localStorage.setItem("applelookaroundchecked", "false");
- }
- });
- }
- };
- // We want the page to be loaded before trying to inject anything
- let documentLoadedInterval = setInterval(function () {
- if (document.readyState === "complete") {
- clearInterval(documentLoadedInterval);
- inject();
- }
- }, 100);
- }
- // ----------------------------------------------------------------------------
- // Sate vars
- // TODO: Is there a better way to do this?
- var loadingInProgress = false;
- var currentPano = new lookaround_1.PanoInfo("", "", "", 0, 0, 0);
- var currentlyLoadedPanoTiles = [];
- var curNeighbors = [];
- // When moving, this is used to keep the current viewport while loading the next pano
- var oldHeading = 0;
- // ----------------------------------------------------------------------------
- // Google Maps API callbacks
- // Return a pano image given the panoID.
- const getCustomPanoramaTileUrl = (pano, zoom, tileX, tileY) => {
- // Currently loading first image in a round, return a blank image
- //if (pano.startsWith("r")){
- if (currentlyLoadedPanoTiles.length === 0) {
- return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==";
- }
- return currentlyLoadedPanoTiles[tileX];
- };
- const getPano = (pano) => {
- let rp = Options.RESOLUTION_PROFILES[Options.RESOLUTION_SETTING];
- let fullWidth = 2 * rp.big.width + 2 * rp.small.width - 4 * rp.overlap;
- return {
- location: {
- pano: pano,
- description: "Apple Look Around",
- latLng: new google.maps.LatLng(currentPano.lat, currentPano.lon),
- },
- links: [],
- // The text for the copyright control.
- copyright: "(C) Apple",
- // The definition of the tiles for this panorama.
- tiles: {
- tileSize: new google.maps.Size(Math.round(fullWidth / 4), Math.round(Options.EXTENSION_FACTOR * rp.big.height)),
- worldSize: new google.maps.Size(fullWidth, Math.round(rp.big.height * Options.EXTENSION_FACTOR)),
- // The heading in degrees at the origin of the panorama
- // tile set.
- centerHeading: function () {
- // While loading: use the old heading so that when moving, you keep the same viewport while loading the next pano
- if (loadingInProgress) {
- return oldHeading;
- }
- else {
- var newHeading = (currentPano.heading + Options.HEADING_CALIBRATION) % 360;
- oldHeading = newHeading;
- return newHeading;
- }
- }(),
- getTileUrl: getCustomPanoramaTileUrl,
- },
- };
- };
- // ----------------------------------------------------------------------------
- // Init
- function initLookAround() {
- google.maps.StreetViewPanorama = class extends google.maps.StreetViewPanorama {
- constructor(...args) {
- super(...args);
- let isChecked = localStorage.getItem("applelookaroundchecked");
- if (isChecked === "true") {
- this.registerPanoProvider(getPano);
- // Position is being changed by GeoGuessr at the beginning of each round. this.getPosition() contains lat/lng of round.
- this.addListener("position_changed", () => {
- console.log("Position changed " + this.getPosition());
- try {
- // Detect if this is a new round. Normally, currentPano is already updated if this is a move in the same round.
- if ((this.getPosition().lat() === currentPano.lat && this.getPosition().lng() === currentPano.lon)) {
- console.log("Position is currentPano => same round");
- return;
- }
- console.warn("Position actually changed => new round; full reload");
- currentlyLoadedPanoTiles = []; // Causes black screen again
- this.getFirstPanoId();
- }
- catch (e) {
- console.error(e);
- }
- });
- // Called after setPano(). If the pano is "r<panoId>/<regioId>", then we load the tiles for that pano.
- // If it doesn't start with "r", then loading is done.
- this.addListener("pano_changed", () => {
- console.log("Pano changed " + this.getPano());
- if (this.getPano() != null && this.getPano() != currentPano.panoFullId() && this.getPano() != "" && this.getPano().startsWith("r")) {
- console.log("New pano requested " + this.getPano());
- try {
- this.beginLoadingPanos(this, this.getPano().replace("r", ""));
- }
- catch (_a) { }
- }
- });
- this.addListener("links_changed", () => {
- console.log("Links changed " + this.getLinks());
- if (!this.getPano().startsWith("r") && curNeighbors != null) {
- //this.getLinks().push(curNeighbors[0])
- let neighborLinks = curNeighbors.map(neighbor => {
- return {
- "descripton": "",
- "pano": "r" + neighbor.panoFullId(),
- "heading": Math.round(geoutils_1.default.heading([neighbor.lat, neighbor.lon], [currentPano.lat, currentPano.lon]) + 180) % 360,
- };
- });
- console.log("Pushing Links " + neighborLinks.length);
- for (const neighbor of neighborLinks) {
- if (neighbor.pano != "") {
- this.getLinks().push(neighbor);
- }
- }
- }
- });
- }
- }
- getFirstPanoId() {
- return __awaiter(this, void 0, void 0, function* () {
- let isChecked = localStorage.getItem("applelookaroundchecked");
- if (isChecked !== "true")
- return;
- try {
- let lat = this.position.lat();
- let lon = this.position.lng();
- let lookAroundPanoId, regionId;
- let closestObject = yield Lookaround.getClosestPanoAtCoords(lat, lon);
- lookAroundPanoId = closestObject.panoId;
- regionId = closestObject.regionId;
- // Request pano to load
- currentPano = closestObject;
- this.setPano("r" + lookAroundPanoId + "/" + regionId);
- }
- catch (_a) { }
- });
- }
- // param panoFullId is "panoId/regionId"
- beginLoadingPanos(_t, panoFullId) {
- return __awaiter(this, void 0, void 0, function* () {
- if (loadingInProgress)
- return;
- //console.warn("http://localhost:5000/#c=17/"+currentPano.lat+"/"+currentPano.lon+"&p="+currentPano.lat+"/"+currentPano.lon);
- // Moved. Find the selected neigbor from ID.
- if (curNeighbors.length > 0) {
- let selectedNeighbor = curNeighbors.filter(n => n.panoFullId() == panoFullId)[0];
- if (selectedNeighbor != null) {
- currentPano = selectedNeighbor;
- }
- }
- console.log("Start loading Panos");
- loadingInProgress = true;
- let pano0 = Lookaround.loadTileForPano(panoFullId, 0);
- let pano1 = Lookaround.loadTileForPano(panoFullId, 1);
- let pano2 = Lookaround.loadTileForPano(panoFullId, 2);
- let pano3 = Lookaround.loadTileForPano(panoFullId, 3);
- curNeighbors = yield (yield Lookaround.getNeighbors(currentPano));
- loadingInProgress = false;
- currentlyLoadedPanoTiles = [yield pano0, yield pano1, yield pano2, yield pano3];
- // Set another panoId to refresh the view
- this.setPano(panoFullId);
- });
- }
- };
- }
- function launchObserver() {
- initLookAround();
- //let observer3 = new MutationObserver((mutations) => {
- // const PATH_NAME = window.location.pathname;
- // if (PATH_NAME.startsWith("/maps/") && PATH_NAME.endsWith("/play")) { // Inject the options menu if the path name is /maps/XXXXXXX/play
- // //injectMenu();
- // }
- //});
- //observer3.observe(document.body, {childList: true, subtree: true, attributes: false, characterData: false});
- }
- function onLoad() {
- let isChecked = localStorage.getItem("applelookaroundchecked");
- if (isChecked === null) {
- localStorage.setItem("applelookaroundchecked", "true");
- }
- //const PATH_NAME = window.location.pathname;
- //if (PATH_NAME.startsWith("/maps/") && PATH_NAME.endsWith("/play")) { // Inject the options menu if the path name is /maps/XXXXXXX/play
- // //injectMenu();
- //}
- injecter(() => {
- launchObserver();
- });
- }
- (function () {
- onLoad();
- })();
- window.onload = onLoad;
- //# sourceMappingURL=index.js.map
- /***/ }),
- /***/ 215:
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
- };
- Object.defineProperty(exports, "__esModule", ({ value: true }));
- exports.getNeighbors = exports.getClosestPanoAtCoords = exports.loadTileForPano = exports.PanoInfo = void 0;
- const Options = __webpack_require__(944);
- const auth_1 = __webpack_require__(297);
- const geoutils_1 = __webpack_require__(97);
- const proto_1 = __webpack_require__(224);
- const auth = new auth_1.Authenticator();
- var tileCache = {};
- class PanoInfo {
- constructor(date, panoId, regionId, heading, lat, lon) {
- this.date = date;
- this.panoId = panoId;
- this.regionId = regionId;
- this.heading = heading;
- this.lat = lat;
- this.lon = lon;
- }
- panoFullId() {
- return this.panoId + "/" + this.regionId;
- }
- }
- exports.PanoInfo = PanoInfo;
- function getCoverageTileRaw(tile_x, tile_y) {
- return __awaiter(this, void 0, void 0, function* () {
- let headers = new Headers({
- "maps-tile-style": "style=57&size=2&scale=0&v=0&preflight=2",
- "maps-tile-x": tile_x.toString(),
- "maps-tile-y": tile_y.toString(),
- "maps-tile-z": "17",
- "maps-auth-token": "w31CPGRO/n7BsFPh8X7kZnFG0LDj9pAuR8nTtH3xhH8=",
- });
- let response = yield (yield fetch(Options.CORS_PROXY + "https://gspe76-ssl.ls.apple.com/api/tile?", { headers: headers })).arrayBuffer();
- let tile = yield proto_1.default.parseMapTile(response);
- return tile;
- });
- }
- function getCoverageInMapTile(x, y) {
- return __awaiter(this, void 0, void 0, function* () {
- try {
- if (tileCache["" + x + "/" + y]) {
- return tileCache[x + "/" + y];
- }
- let response = yield getCoverageTileRaw(x, y);
- var coverage = [];
- for (let pano of response.pano) {
- let coords = geoutils_1.default.protobuf_tile_offset_to_wsg84(pano.unknown4.longitudeOffset, pano.unknown4.latitudeOffset, x, y);
- let p = new PanoInfo(pano.timestamp.toString(), pano.panoid.toString(), response.unknown13[pano.regionIdIdx].regionId.toString(), geoutils_1.default.headingFromUnknowns(pano.unknown4.unknown10, pano.unknown4.unknown11), coords[0], coords[1]);
- coverage.push(p);
- }
- tileCache["" + x + "/" + y] = coverage;
- return coverage;
- }
- catch (error) {
- console.log(error);
- }
- });
- }
- function getClosestPanoAtCoords(lat, lon) {
- return __awaiter(this, void 0, void 0, function* () {
- try {
- let tile = geoutils_1.default.wgs84_to_tile_coord(lat, lon, 17);
- let coverage = yield getCoverageInMapTile(tile[0], tile[1]);
- if (coverage.length == 0) {
- return null;
- }
- let smallestDistance = 9999999;
- let closest = null;
- for (let pano of coverage) {
- let distance = geoutils_1.default.haversineDistance([lat, lon], [pano.lat, pano.lon]);
- if (distance < smallestDistance) {
- smallestDistance = distance;
- closest = pano;
- }
- }
- return closest;
- }
- catch (error) {
- console.log(error);
- return null;
- }
- });
- }
- exports.getClosestPanoAtCoords = getClosestPanoAtCoords;
- function getNeighbors(panoInfo) {
- return __awaiter(this, void 0, void 0, function* () {
- try {
- let tile = geoutils_1.default.wgs84_to_tile_coord(panoInfo.lat, panoInfo.lon, 17);
- var coverage = yield getCoverageInMapTile(tile[0], tile[1]);
- // TODO Only extend when needed (we're close to the edge of the tile)
- coverage = coverage.concat(yield getCoverageInMapTile(tile[0] + 1, tile[1]));
- coverage = coverage.concat(yield getCoverageInMapTile(tile[0] - 1, tile[1]));
- coverage = coverage.concat(yield getCoverageInMapTile(tile[0], tile[1] + 1));
- coverage = coverage.concat(yield getCoverageInMapTile(tile[0], tile[1] - 1));
- coverage = coverage.concat(yield getCoverageInMapTile(tile[0] - 1, tile[1] - 1));
- coverage = coverage.concat(yield getCoverageInMapTile(tile[0] + 1, tile[1] - 1));
- coverage = coverage.concat(yield getCoverageInMapTile(tile[0] - 1, tile[1] + 1));
- coverage = coverage.concat(yield getCoverageInMapTile(tile[0] + 1, tile[1] + 1));
- coverage = coverage.sort((a, b) => Math.abs(geoutils_1.default.haversineDistance([panoInfo.lat, panoInfo.lon], [a.lat, a.lon])) - Math.abs(geoutils_1.default.haversineDistance([panoInfo.lat, panoInfo.lon], [b.lat, b.lon])));
- coverage = coverage.filter(pano => pano.panoFullId() != panoInfo.panoFullId());
- let minDist = 0.030; // 30 meters
- let maxDist = 0.300; // 300 meters
- coverage = coverage.filter(n => (minDist < Math.abs(geoutils_1.default.haversineDistance([panoInfo.lat, panoInfo.lon], [n.lat, n.lon])) &&
- Math.abs(geoutils_1.default.haversineDistance([panoInfo.lat, panoInfo.lon], [n.lat, n.lon])) < maxDist));
- return coverage.slice(0, 8);
- }
- catch (error) {
- console.log(error);
- }
- });
- }
- exports.getNeighbors = getNeighbors;
- function getUrlForTile(panoFullId, x, resolution) {
- return __awaiter(this, void 0, void 0, function* () {
- try {
- //if (!auth.hasSession()) {
- yield auth.init();
- //}
- let segments = panoFullId.split("/");
- let panoId = segments[0];
- let regionId = segments[1];
- let panoid_padded = panoId.padStart(20, "0");
- let region_id_padded = regionId.padStart(10, "0");
- let panoid_split = panoid_padded.slice(0, 4) + "/" + panoid_padded.slice(4, 8) + "/" + panoid_padded.slice(8, 12) + "/" + panoid_padded.slice(12, 16) + "/" + panoid_padded.slice(16, 20);
- return auth.authenticateUrl(Options.APPLE_MAPS_TILE_ENDPOINT + panoid_split + "/" + region_id_padded + "/t/" + x + "/" + resolution);
- }
- catch (error) {
- console.log(error);
- }
- });
- }
- // param panoFullId is "panoId/regionId"
- function loadTileForPano(panoFullId, x) {
- return __awaiter(this, void 0, void 0, function* () {
- try {
- var jpegblob;
- if (Options.CONVERT_LOCALLY) {
- // Step 1: Get the URL of the tile to load
- // New endpoint /panourl in the python server returns just the Apple URL for the pano
- var appleMapsPanoURL = yield getUrlForTile(panoFullId, x, Options.RESOLUTION_SETTING);
- appleMapsPanoURL = Options.CORS_PROXY + appleMapsPanoURL;
- // Step 2: Load the tile
- //console.log("Requesting tile " + [appleMapsPanoURL])
- var blobres = yield fetch(appleMapsPanoURL);
- var blob = yield blobres.blob();
- // Step 3: Convert from HEIC to JPEG with heic2any
- //console.log("Fetched tile, converting and resizing... " + [appleMapsPanoURL])
- //let startTime = Math.floor(Date.now() / 1000);
- jpegblob = heic2any({ "blob": blob, "type": "image/jpeg" });
- }
- else {
- jpegblob = yield (yield fetch(Options.BASE_URL + "pano/" + panoFullId + "/" + Options.RESOLUTION_SETTING + "/" + x + "/")).blob();
- }
- // Step 4: Process image
- // Cut off the overlap from the right of the tile using canvas
- // and add black bars on top and bottom because we don't have sky/ground tiles
- let rp = Options.RESOLUTION_PROFILES[Options.RESOLUTION_SETTING];
- // Putting the jpeg blob into a canvas to remove 256 px from the right (removes overlap)
- var w = rp.big.width;
- if (x == 1 || x == 3) {
- w = rp.small.width;
- }
- w = w - rp.overlap;
- var canvas = document.createElement('canvas');
- canvas.height = Math.round(Options.EXTENSION_FACTOR * rp.big.height);
- canvas.width = w;
- var ctx = canvas.getContext('2d');
- var img = new Image();
- var result = "";
- img.onload = function () {
- ctx.drawImage(img, 0, (canvas.height - rp.big.height) / 2);
- // This is a big data:image/jpeg;base64, URL
- result = canvas.toDataURL("image/jpeg");
- };
- img.src = URL.createObjectURL(yield jpegblob);
- //let endTime = Math.floor(Date.now() / 1000);
- //console.log("Time to convert: " + (endTime - startTime) + " seconds");
- // Wait for context to finish loading
- // TODO: Is there a better way?
- const delay = ms => new Promise(res => setTimeout(res, ms));
- yield delay(100);
- //let endTime2 = Math.floor(Date.now() / 1000);
- //console.log("Full time: " + (endTime - startTime) + " seconds");
- URL.revokeObjectURL(img.src);
- canvas.remove();
- img.remove();
- return result;
- }
- catch (error) {
- console.log(error);
- }
- });
- }
- exports.loadTileForPano = loadTileForPano;
- //# sourceMappingURL=lookaround.js.map
- /***/ }),
- /***/ 944:
- /***/ ((__unused_webpack_module, exports) => {
- Object.defineProperty(exports, "__esModule", ({ value: true }));
- exports.CONVERT_LOCALLY = exports.BASE_URL = exports.RESOLUTION_PROFILES = exports.APPLE_MAPS_TILE_ENDPOINT = exports.CORS_PROXY = exports.EXTENSION_FACTOR = exports.HEADING_CALIBRATION = exports.RESOLUTION_SETTING = void 0;
- // Determines the resolution of images requested from Apple
- // Setting a higher resolution will make rounds load WAY slower, until browsers start to support HEIC
- // 0 = highest resolution available, 4 = lowest resolution available.
- // Default: 2
- const RESOLUTION_SETTING = 2;
- exports.RESOLUTION_SETTING = RESOLUTION_SETTING;
- // Constant value added to calculated heading to calibrate the GeoGuessr compass
- const HEADING_CALIBRATION = 45;
- exports.HEADING_CALIBRATION = HEADING_CALIBRATION;
- const EXTENSION_FACTOR = 2.12; // TODO Play around with this value for best results with image stretching
- exports.EXTENSION_FACTOR = EXTENSION_FACTOR;
- const BASE_URL = "https://lookaround.stocc.dev/";
- exports.BASE_URL = BASE_URL;
- const CONVERT_LOCALLY = true;
- exports.CONVERT_LOCALLY = CONVERT_LOCALLY;
- const CORS_PROXY = "https://nameless-bastion-28139.herokuapp.com/";
- exports.CORS_PROXY = CORS_PROXY;
- const APPLE_MAPS_TILE_ENDPOINT = "https://gspe72-ssl.ls.apple.com/mnn_us/";
- exports.APPLE_MAPS_TILE_ENDPOINT = APPLE_MAPS_TILE_ENDPOINT;
- const RESOLUTION_PROFILES = {
- 0: {
- "overlap": 256,
- "big": {
- "width": 5632,
- "height": 4352,
- },
- "small": {
- "width": 3072,
- "height": 4352,
- }
- },
- 1: {
- "overlap": 188,
- "big": {
- "width": 4128,
- "height": 3088,
- },
- "small": {
- "width": 2256,
- "height": 3088,
- },
- },
- 2: {
- "overlap": 100,
- "big": {
- "width": 2208,
- "height": 1648,
- },
- "small": {
- "width": 1200,
- "height": 1648,
- }
- },
- 3: {
- "overlap": 71,
- "big": {
- "width": 1568,
- "height": 1168,
- },
- "small": {
- "width": 848,
- "height": 1168,
- }
- },
- 4: {
- "overlap": 50,
- "big": {
- "width": 1104,
- "height": 832,
- },
- "small": {
- "width": 608,
- "height": 832,
- }
- }
- };
- exports.RESOLUTION_PROFILES = RESOLUTION_PROFILES;
- //# sourceMappingURL=options.js.map
- /***/ }),
- /***/ 224:
- /***/ (function(__unused_webpack_module, exports) {
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
- };
- Object.defineProperty(exports, "__esModule", ({ value: true }));
- let mapTile = `
- syntax = "proto3";
- message MapTile {
- repeated Pano pano = 1;
- repeated Unknown13 unknown13 = 4;
- repeated Unknown22 unknown22 = 5;
- TileCoordinate tileCoordinate = 6;
- message Pano {
- uint64 panoid = 1;
- int32 unknown1 = 4;
- int64 timestamp = 5; // time the pano was taken
- int32 region_id_idx = 7;
- repeated int32 unknown3 = 9; // goes from 0 to 5. available sizes maybe?
- Unknown4 unknown4 = 10;
- Unknown5 unknown5 = 12;
- message Unknown4 {
- int32 longitude_offset = 1;
- int32 latitude_offset = 2;
- int32 unknown8 = 3;
- int32 unknown9 = 4;
- int32 unknown10 = 5;
- int32 unknown11 = 6;
- }
- message Unknown5 {
- repeated int32 unknown12 = 1;
- }
- }
- message Unknown13 {
- int32 unknown14 = 1;
- // this is the param that appears in pano URLs after the pano ID.
- // no idea what this does exactly.
- int32 region_id = 3;
- int32 unknown15 = 4;
- int32 unknown16 = 5;
- int32 unknown17 = 6;
- int32 unknown18 = 9;
- int32 unknown19 = 10;
- int32 unknown20 = 11;
- int32 unknown21 = 12;
- }
- message Unknown22 {
- int32 unknown23 = 1;
- Unknown24 unknown24 = 4;
- Unknown25 unknown25 = 5;
- int32 unknown26 = 6;
- message Unknown24 {
- int32 unknown27 = 1;
- double unknown28 = 2;
- double unknown29 = 3;
- double unknown30 = 4;
- double unknown31 = 5;
- double unknown32 = 6;
- double unknown33 = 7;
- double unknown34 = 8;
- double unknown35 = 9;
- double unknown36 = 10;
- }
- message Unknown25 {
- double unknown37 = 1;
- double unknown38 = 2;
- double unknown39 = 3;
- double unknown40 = 4;
- double unknown41 = 5;
- double unknown42 = 6;
- }
- }
- message TileCoordinate {
- int32 x = 1;
- int32 y = 2;
- int32 z = 3;
- }
- }`;
- let resourceManifest = `
- syntax = "proto3";
- message ResourceManifest {
- repeated StyleConfig style_config = 2;
- string token_p2 = 30;
- string cache_base_url = 31;
- repeated CacheFile cache_file = 72;
- repeated string cache_file_2 = 9;
- message CacheFile {
- string file_name = 2;
- }
- message StyleConfig {
- string url_prefix_1 = 1;
- string url_prefix_2 = 9;
- StyleID style_id = 3;
- enum StyleID {
- _ = 0;
- C3MM_1 = 14;
- C3M = 15;
- DTM_1 = 16;
- DTM_2 = 17;
- C3MM_2 = 52;
- }
- }
- }
- `;
- class Proto {
- static parseResourceManifest(payload) {
- return __awaiter(this, void 0, void 0, function* () {
- const array = new Uint8Array(payload);
- let manifest = protobuf.parse(resourceManifest).root.lookup("ResourceManifest");
- let message = manifest.decode(array);
- return message;
- });
- }
- static parseMapTile(payload) {
- return __awaiter(this, void 0, void 0, function* () {
- const array = new Uint8Array(payload);
- let manifest = protobuf.parse(mapTile).root.lookup("MapTile");
- let message = manifest.decode(array);
- return message;
- });
- }
- }
- exports["default"] = Proto;
- //# sourceMappingURL=proto.js.map
- /***/ })
- /******/ });
- /************************************************************************/
- /******/ // The module cache
- /******/ var __webpack_module_cache__ = {};
- /******/
- /******/ // The require function
- /******/ function __webpack_require__(moduleId) {
- /******/ // Check if module is in cache
- /******/ var cachedModule = __webpack_module_cache__[moduleId];
- /******/ if (cachedModule !== undefined) {
- /******/ return cachedModule.exports;
- /******/ }
- /******/ // Create a new module (and put it into the cache)
- /******/ var module = __webpack_module_cache__[moduleId] = {
- /******/ // no module.id needed
- /******/ // no module.loaded needed
- /******/ exports: {}
- /******/ };
- /******/
- /******/ // Execute the module function
- /******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
- /******/
- /******/ // Return the exports of the module
- /******/ return module.exports;
- /******/ }
- /******/
- /************************************************************************/
- /******/
- /******/ // startup
- /******/ // Load entry module and return exports
- /******/ // This entry module is referenced by other modules so it can't be inlined
- /******/ var __webpack_exports__ = __webpack_require__(590);
- /******/
- /******/ })()
- ;
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址