Geoguessr Location Resolver (Works in all modes)

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

当前为 2023-11-01 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Geoguessr Location Resolver (Works in all modes)
  3. // @namespace http://tampermonkey.net/
  4. // @version 11.21
  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. // ==================================== ANTI-ANTI-cheat stuff ====================================
  25. window.open = (...e) =>{ // try to re-write window.open back to its native function.
  26. nativeOpen(...e)
  27. }
  28.  
  29. GM_webRequest([
  30. { selector: 'https://www.geoguessr.com/api/v4/trails', action: 'cancel' },
  31. { selector: 'https://www.geoguessr.com/api/v4/bdd406e4-c426-4d04-85b3-230f6fceef28', action: 'cancel' },
  32. { selector: 'https://www.geoguessr.com/api/v4/b9bc4481-80c9-483a-a945-c24d935174f0', action: 'cancel' },
  33. ]);
  34. // ==================================== Coordinate Interception ====================================
  35.  
  36. // Below, I intercept the API call to Google Street view and view the result before it reaches the client.
  37. // Then I simply do some regex over the response string to find the coordinates, which Google gave to us in the response data
  38. // I then update a global variable above, with the correct coordinates, each time we receive a response from Google.
  39. // This needs further testing - but initial tests look promising
  40.  
  41. var originalOpen = XMLHttpRequest.prototype.open;
  42. XMLHttpRequest.prototype.open = function(method, url) {
  43. if (url.startsWith('https://maps.googleapis.com')) {
  44.  
  45. this.addEventListener('load', function () {
  46. let interceptedResult = this.responseText
  47. const pattern = /-?\d+\.\d+,-?\d+\.\d+/g;
  48. let match = interceptedResult.match(pattern)[0];
  49. let split = match.split(",")
  50.  
  51. let lat = Number.parseFloat(split[0])
  52. let lng = Number.parseFloat(split[1])
  53. globalCoordinates.lat = lat
  54. globalCoordinates.lng = lng
  55. });
  56. }
  57. // Call the original open function
  58. return originalOpen.apply(this, arguments);
  59. };
  60.  
  61.  
  62. // ====================================Placing Marker====================================
  63.  
  64. function placeMarker(safeMode){
  65. let {lat,lng} = globalCoordinates
  66.  
  67. if (safeMode) { // applying random values to received coordinates.
  68. const sway = [Math.random() > 0.5,Math.random() > 0.5]
  69. const multiplier = Math.random() * 4
  70. const horizontalAmount = Math.random() * multiplier
  71. const verticalAmount = Math.random() * multiplier
  72. sway[0] ? lat += verticalAmount : lat -= verticalAmount
  73. sway[1] ? lng += horizontalAmount : lat -= horizontalAmount
  74. }
  75.  
  76. // Okay well played Geoguessr u got me there for a minute, but below should work.
  77. // Below is the only intentionally complicated part of the code - it won't be simplified or explained for good reason.
  78. let element = document.getElementsByClassName("guess-map_canvas__JAHHT")[0]
  79. if(!element){
  80. placeMarkerStreaks()
  81. return
  82. }
  83. const keys = Object.keys(element)
  84. const key = keys.find(key => key.startsWith("__reactFiber$"))
  85. const props = element[key]
  86. const x = props.return.return.memoizedProps.map.__e3_.click
  87. const y = Object.keys(x)[0]
  88.  
  89. const z = {
  90. latLng:{
  91. lat: () => lat,
  92. lng: () => lng,
  93. }
  94. }
  95. x[y].xe(z)
  96. }
  97.  
  98. // similar idea as above, but with special considerations for the streaks modes.
  99. // again - will not be explained.
  100. function placeMarkerStreaks(){
  101. let {lat,lng} = globalCoordinates
  102. let element = document.getElementsByClassName("region-map_mapCanvas__R95Ki")[0]
  103. if(!element){
  104. console.log("unable to find map element")
  105. return
  106. }
  107. const keys = Object.keys(element)
  108. const key = keys.find(key => key.startsWith("__reactFiber$"))
  109. const props = element[key]
  110. const x = props.return.return.memoizedProps.map.__e3_.click
  111. const y = Object.keys(x)
  112. const w = "(e.latLng.lat(),e.latLng.lng())}"
  113. const z = y.find(a => x[a].xe.toString().slice(5) === w)
  114. const v = {
  115. latLng:{
  116. lat: () => lat,
  117. lng: () => lng,
  118. }
  119. }
  120. x[z].xe(v)
  121. }
  122.  
  123. // ====================================Open In Google Maps====================================
  124.  
  125. function mapsFromCoords() { // opens new Google Maps location using coords.
  126.  
  127. const {lat,lng} = globalCoordinates
  128. if (!lat || !lng) {
  129. console.log("Failed to fetch coords for Google Maps")
  130. return;
  131. }
  132.  
  133. // Reject any attempt to call an overridden window.open, or fail .
  134. if(window.open.toString().indexOf('native code') === -1){
  135. console.log("Geoguessr has overridden window.open.")
  136. if(nativeOpen && nativeOpen.toString().indexOf('native code') !== -1){
  137. console.log("fallback enabled.")
  138. nativeOpen(`https://www.google.com/maps/place/${lat},${lng}`);
  139. }
  140. }
  141. else{
  142. window.open(`https://www.google.com/maps/place/${lat},${lng}`)
  143. }
  144. }
  145.  
  146. // ====================================Controls,setup, etc.====================================
  147.  
  148. function setInnerText(){
  149. const text = `
  150. Geoguessr Resolver Loaded Successfully
  151.  
  152. IMPORTANT GEOGUESSR RESOLVER UPDATE INFORMATION:
  153. The script has been rewritten after a big update by the developers.
  154. Reminder that using the script is at your own risk - don't ruin other's fun.
  155. `
  156. if(document.getElementsByClassName("header_logo__vV0HK")[0]){
  157. const logoWrapper = document.getElementsByClassName("header_logo__vV0HK")[0]
  158. logoWrapper.innerText = text
  159. }
  160. }
  161.  
  162. let onKeyDown = (e) => {
  163. if (e.keyCode === 49) {
  164. e.stopImmediatePropagation(); // tries to prevent the key from being hijacked by geoguessr
  165. placeMarker(true)
  166. }
  167. if (e.keyCode === 50) {
  168. e.stopImmediatePropagation();
  169. placeMarker(false)
  170. }
  171. if (e.keyCode === 51) {
  172. e.stopImmediatePropagation();
  173. mapsFromCoords(false)
  174. }
  175. }
  176. setInnerText()
  177. document.addEventListener("keydown", onKeyDown);
  178.