Geoguessr Google Maps Auto Opener with Country Info

Automatically opens Google Maps with the current GeoGuessr location, fetches country name, flag, TLD, driving side, language, currency, and phone prefix, and displays this info in a new window.

  1. // ==UserScript==
  2. // @name Geoguessr Google Maps Auto Opener with Country Info
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.5
  5. // @description Automatically opens Google Maps with the current GeoGuessr location, fetches country name, flag, TLD, driving side, language, currency, and phone prefix, and displays this info in a new window.
  6. // @author 0x978 (modified)
  7. // @match https://www.geoguessr.com/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=geoguessr.com
  9. // @grant GM_webRequest
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. let globalCoordinates = {
  14. lat: 0,
  15. lng: 0
  16. };
  17.  
  18. let googleMapsTab = null; // Store the reference to the Google Maps tab
  19. let countryWindow = null; // Store the reference to the country info window
  20.  
  21. // Open or refresh Google Maps with the latest coordinates
  22. function mapsFromCoords() {
  23. const { lat, lng } = globalCoordinates;
  24. if (!lat || !lng) {
  25. return;
  26. }
  27.  
  28. const mapUrl = `https://maps.google.com/?output=embed&q=${lat},${lng}&ll=${lat},${lng}&z=5`;
  29.  
  30. // If no Google Maps tab is open, open a new one
  31. if (!googleMapsTab || googleMapsTab.closed) {
  32. googleMapsTab = window.open(mapUrl, '_blank', 'width=800,height=600,left=1920,top=0');
  33. if (googleMapsTab) {
  34. googleMapsTab.focus();
  35. } else {
  36. console.error('Unable to open the new tab. Your browser may block popups.');
  37. }
  38. } else {
  39. // If the tab is open, update its location with the new coordinates
  40. googleMapsTab.location.href = mapUrl;
  41. }
  42. }
  43.  
  44. // Fetch the country info (name, flag, TLD, driving side, language, currency, phone prefix) using Nominatim and REST Countries APIs
  45. async function getCountryInfo(lat, lng) {
  46. const url = `https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lng}&format=json&addressdetails=1`;
  47.  
  48. try {
  49. const response = await fetch(url);
  50. const data = await response.json();
  51.  
  52. if (data && data.address && data.address.country) {
  53. const country = data.address.country;
  54. const countryCode = data.address.country_code.toUpperCase(); // ISO 3166-1 alpha-2 country code
  55. console.log(`Location: ${lat}, ${lng} - Country: ${country}`);
  56.  
  57. // Fetch country information from REST Countries API
  58. const countryInfo = await getCountryInfoFromREST(countryCode);
  59. console.log(countryInfo);
  60.  
  61. // Open a new window and display the country info
  62. if (!countryWindow || countryWindow.closed) {
  63. countryWindow = window.open('', '_blank', 'width=600,height=400,left=1920,top=0');
  64. }
  65. countryWindow.document.open();
  66. countryWindow.document.write(`
  67. <html>
  68. <head>
  69. <title>Country Information</title>
  70. <style>
  71. body {
  72. font-family: Arial, sans-serif;
  73. text-align: center;
  74. padding: 20px;
  75. }
  76. .country-info {
  77. margin-top: 20px;
  78. }
  79. .flag {
  80. width: 100px;
  81. height: auto;
  82. }
  83. .info {
  84. margin-top: 10px;
  85. font-size: 16px;
  86. }
  87. </style>
  88. </head>
  89. <body>
  90. <h1>Country: ${country}</h1>
  91. <p><strong>TLD:</strong> ${countryInfo.tld}</p>
  92. <p><strong>Driving Side:</strong> ${countryInfo.drivesOn}</p>
  93. <p><strong>Languages:</strong> ${countryInfo.languages.join(', ')}</p>
  94. <p><strong>Currency:</strong> ${countryInfo.currency}</p>
  95. <p><strong>Phone Prefix:</strong> ${countryInfo.phonePrefix}</p>
  96. <div class="country-info">
  97. <img src="https://flagcdn.com/w320/${countryCode.toLowerCase()}.png" class="flag" alt="Flag of ${country}" />
  98. </div>
  99. </body>
  100. </html>
  101. `);
  102. countryWindow.document.close();
  103. } else {
  104. console.error('Country not found in Nominatim response.');
  105. }
  106. } catch (error) {
  107. console.error('Error fetching country info:', error);
  108. }
  109. }
  110.  
  111. // Fetch detailed country info (TLD, driving side, language, currency, phone prefix) using REST Countries API
  112. async function getCountryInfoFromREST(countryCode) {
  113. const url = `https://restcountries.com/v3.1/alpha/${countryCode}`;
  114. try {
  115. const response = await fetch(url);
  116. const data = await response.json();
  117.  
  118. const countryData = data[0];
  119. const tld = countryData.tld ? countryData.tld[0] : 'Unknown TLD';
  120. const drivesOn = countryData.car && countryData.car.side ? (countryData.car.side === 'left' ? 'Left' : 'Right') : 'Unknown';
  121. const languages = Object.values(countryData.languages || {});
  122. const currency = countryData.currencies ? Object.values(countryData.currencies)[0].name : 'Unknown';
  123. const phonePrefix = countryData.idd && countryData.idd.root && countryData.idd.suffixes
  124. ? countryData.idd.root + countryData.idd.suffixes[0]
  125. : 'Unknown';
  126.  
  127. // Debug logs to check the fetched data
  128. console.log({
  129. countryCode,
  130. tld,
  131. drivesOn,
  132. languages,
  133. currency,
  134. phonePrefix
  135. });
  136.  
  137. return {
  138. tld,
  139. drivesOn,
  140. languages,
  141. currency,
  142. phonePrefix
  143. };
  144. } catch (error) {
  145. console.error('Error fetching country info from REST Countries API:', error);
  146. return {
  147. tld: 'Unknown TLD',
  148. drivesOn: 'Unknown',
  149. languages: ['Unknown'],
  150. currency: 'Unknown',
  151. phonePrefix: 'Unknown'
  152. };
  153. }
  154. }
  155.  
  156. // Intercept API call to get coordinates
  157. var originalOpen = XMLHttpRequest.prototype.open;
  158. XMLHttpRequest.prototype.open = function(method, url) {
  159. if (method.toUpperCase() === 'POST' &&
  160. (url.startsWith('https://maps.googleapis.com/$rpc/google.internal.maps.mapsjs.v1.MapsJsInternalService/GetMetadata') ||
  161. url.startsWith('https://maps.googleapis.com/$rpc/google.internal.maps.mapsjs.v1.MapsJsInternalService/SingleImageSearch'))) {
  162.  
  163. this.addEventListener('load', function () {
  164. let interceptedResult = this.responseText;
  165. const pattern = /-?\d+\.\d+,-?\d+\.\d+/g;
  166. let match = interceptedResult.match(pattern)[0];
  167. let split = match.split(",");
  168.  
  169. globalCoordinates.lat = Number.parseFloat(split[0]);
  170. globalCoordinates.lng = Number.parseFloat(split[1]);
  171.  
  172. // Automatically update Google Maps when new coordinates are received
  173. mapsFromCoords();
  174.  
  175. // Get the country info based on the coordinates
  176. getCountryInfo(globalCoordinates.lat, globalCoordinates.lng);
  177. });
  178. }
  179. return originalOpen.apply(this, arguments);
  180. };