Geoguessr Location Resolver (Works in all modes)

Features: Automatically score 5000 Points | Score randomly between 4500 and 5000 points | Open in Google Maps

当前为 2024-04-17 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Geoguessr Location Resolver (Works in all modes)
  3. // @namespace http://tampermonkey.net/
  4. // @version 12.3
  5. // @description Features: Automatically score 5000 Points | Score randomly between 4500 and 5000 points | Open in Google Maps
  6. // @author 0x978
  7. // @match https://www.geoguessr.com/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=geoguessr.com
  9. // @grant GM_webRequest
  10. // ==/UserScript==
  11.  
  12.  
  13. // =================================================================================================================
  14. // 'An idiot admires complexity, a genius admires simplicity'
  15. // Learn how I made this script: https://github.com/0x978/GeoGuessr_Resolver/blob/master/howIMadeTheScript.md
  16. // Contribute things you think will be cool once you learn: https://github.com/0x978/GeoGuessr_Resolver/pulls
  17. // ================================================================================================================
  18.  
  19. let globalCoordinates = { // keep this stored globally, and we'll keep updating it for each API call.
  20. lat: 0,
  21. lng: 0
  22. }
  23.  
  24. let globalPanoID = undefined
  25.  
  26. // Below, I intercept the API call to Google Street view and view the result before it reaches the client.
  27. // Then I simply do some regex over the response string to find the coordinates, which Google gave to us in the response data
  28. // I then update a global variable above, with the correct coordinates, each time we receive a response from Google.
  29.  
  30. var originalOpen = XMLHttpRequest.prototype.open;
  31. XMLHttpRequest.prototype.open = function(method, url) {
  32. // Geoguessr now calls the Google Maps API multiple times each round, with subsequent requests overwriting
  33. // the saved coordinates. Calls to this exact API path seems to be legitimate for now. A better solution than panoID currently?
  34. // Needs testing.
  35. if (url.startsWith('https://maps.googleapis.com/$rpc/google.internal.maps.mapsjs.v1.MapsJsInternalService/GetMetadata')) {
  36.  
  37. this.addEventListener('load', function () {
  38. let interceptedResult = this.responseText
  39. const pattern = /-?\d+\.\d+,-?\d+\.\d+/g;
  40. let match = interceptedResult.match(pattern)[0];
  41. let split = match.split(",")
  42.  
  43. let lat = Number.parseFloat(split[0])
  44. let lng = Number.parseFloat(split[1])
  45.  
  46.  
  47. globalCoordinates.lat = lat
  48. globalCoordinates.lng = lng
  49. });
  50. }
  51. // Call the original open function
  52. return originalOpen.apply(this, arguments);
  53. };
  54.  
  55.  
  56. // ====================================Placing Marker====================================
  57.  
  58. function placeMarker(safeMode){
  59. let {lat,lng} = globalCoordinates
  60.  
  61. if (safeMode) { // applying random values to received coordinates.
  62. const sway = [Math.random() > 0.5,Math.random() > 0.5]
  63. const multiplier = Math.random() * 4
  64. const horizontalAmount = Math.random() * multiplier
  65. const verticalAmount = Math.random() * multiplier
  66. sway[0] ? lat += verticalAmount : lat -= verticalAmount
  67. sway[1] ? lng += horizontalAmount : lat -= horizontalAmount
  68. }
  69.  
  70. // Okay well played Geoguessr u got me there for a minute, but below should work.
  71. // Below is the only intentionally complicated part of the code - it won't be simplified or explained for good reason.
  72. // let element = document.getElementsByClassName("guess-map_canvas__JAHHT")[0]
  73. let element = document.querySelectorAll('[class^="guess-map_canvas__"]')[0]
  74. if(!element){
  75. placeMarkerStreaks()
  76. return
  77. }
  78. const keys = Object.keys(element)
  79. const key = keys.find(key => key.startsWith("__reactFiber$"))
  80. const props = element[key]
  81. const x = props.return.return.memoizedProps.map.__e3_.click
  82. const y = Object.keys(x)[0]
  83.  
  84. const z = {
  85. latLng:{
  86. lat: () => lat,
  87. lng: () => lng,
  88. }
  89. }
  90.  
  91. const xy = x[y]
  92. const a = Object.keys(x[y])
  93.  
  94. for(let i = 0; i < a.length ;i++){
  95. let q = a[i]
  96. if (typeof xy[q] === "function"){
  97. xy[q](z)
  98. }
  99. }
  100. }
  101.  
  102. // similar idea as above, but with special considerations for the streaks modes.
  103. // again - will not be explained.
  104. function placeMarkerStreaks(){
  105. let {lat,lng} = globalCoordinates
  106. let element = document.getElementsByClassName("region-map_mapCanvas__R95Ki")[0]
  107. if(!element){
  108. return
  109. }
  110. const keys = Object.keys(element)
  111. const key = keys.find(key => key.startsWith("__reactFiber$"))
  112. const props = element[key]
  113. const x = props.return.return.memoizedProps.map.__e3_.click
  114. const y = Object.keys(x)
  115. const w = "(e.latLng.lat(),e.latLng.lng())}"
  116. const v = {
  117. latLng:{
  118. lat: () => lat,
  119. lng: () => lng,
  120. }
  121. }
  122. for(let i = 0; i < y.length; i++){
  123. const curr = Object.keys(x[y[i]])
  124. let func = curr.find(l => typeof x[y[i]][l] === "function")
  125. let prop = x[y[i]][func]
  126. if(prop && prop.toString().slice(5) === w){
  127. prop(v)
  128. }
  129. }
  130. }
  131.  
  132. // ====================================Open In Google Maps====================================
  133.  
  134. function mapsFromCoords() { // opens new Google Maps location using coords.
  135.  
  136. const {lat,lng} = globalCoordinates
  137. if (!lat || !lng) {
  138. return;
  139. }
  140.  
  141. // Reject any attempt to call an overridden window.open, or fail .
  142. if(nativeOpen && nativeOpen.toString().indexOf('native code') === 19){
  143. nativeOpen(`https://maps.google.com/?output=embed&q=${lat},${lng}&ll=${lat},${lng}&z=5`);
  144. }
  145. }
  146.  
  147. // ====================================Controls,setup, etc.====================================
  148.  
  149.  
  150. let onKeyDown = (e) => {
  151. if (e.keyCode === 49) {
  152. e.stopImmediatePropagation(); // tries to prevent the key from being hijacked by geoguessr
  153. placeMarker(true)
  154. }
  155. if (e.keyCode === 50) {
  156. e.stopImmediatePropagation();
  157. placeMarker(false)
  158. }
  159. if (e.keyCode === 51) {
  160. e.stopImmediatePropagation();
  161. mapsFromCoords(false)
  162. }
  163. }
  164.  
  165. document.addEventListener("keydown", onKeyDown);