(kiritz🦊 0.25a)

kiritz🦊 tip💡: флаг+город, лиса, автогесс, карты, полная инфа + пинг/лосс до geoguessr

  1. // ==UserScript==
  2. // @name (kiritz🦊 0.25a)
  3. // @namespace http://tampermonkey.net/
  4. // @version 25
  5. // @description kiritz🦊 tip💡: флаг+город, лиса, автогесс, карты, полная инфа + пинг/лосс до geoguessr
  6. // @author kiritz🦊
  7. // @match https://www.geoguessr.com/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=geoguessr.com
  9. // @grant none
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. let globalCoordinates = { lat: 0, lng: 0 };
  14. let autoGuessEnabled = false;
  15. let foxMarker = null;
  16. let fullInfoVisible = false;
  17. let fullInfoInterval = null;
  18. let testBoxVisible = false;
  19. let testBox = null;
  20.  
  21. // Перехват координат
  22. var originalOpen = XMLHttpRequest.prototype.open;
  23. XMLHttpRequest.prototype.open = function (method, url) {
  24. if (method.toUpperCase() === 'POST' &&
  25. (url.startsWith('https://maps.googleapis.com/$rpc/google.internal.maps.mapsjs.v1.MapsJsInternalService/GetMetadata') ||
  26. url.startsWith('https://maps.googleapis.com/$rpc/google.internal.maps.mapsjs.v1.MapsJsInternalService/SingleImageSearch'))) {
  27. this.addEventListener('load', function () {
  28. let interceptedResult = this.responseText;
  29. const pattern = /-?\d+\.\d+,-?\d+\.\d+/g;
  30. let match = interceptedResult.match(pattern)?.[0];
  31. if (!match) return;
  32. let split = match.split(",");
  33. globalCoordinates.lat = parseFloat(split[0]);
  34. globalCoordinates.lng = parseFloat(split[1]);
  35. if (autoGuessEnabled) {
  36. placePinMarker();
  37. }
  38. });
  39. }
  40. return originalOpen.apply(this, arguments);
  41. };
  42.  
  43. // Лиса
  44. function addFoxMarker(lat, lng) {
  45. const element = document.querySelector('[class^="guess-map_canvas__"]');
  46. if (!element || !window.google) return;
  47.  
  48. if (foxMarker) foxMarker.setMap(null);
  49.  
  50. const reactKey = Object.keys(element).find(k => k.startsWith("__reactFiber$"));
  51. const map = element[reactKey]?.return?.return?.memoizedProps?.map;
  52. if (!map) return;
  53.  
  54. const foxIcon = {
  55. url: "data:image/svg+xml;charset=UTF-8," + encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40"><text x="0" y="30" font-size="30">🦊</text></svg>`),
  56. scaledSize: new google.maps.Size(30, 30),
  57. anchor: new google.maps.Point(15, 15)
  58. };
  59.  
  60. foxMarker = new google.maps.Marker({ position: { lat, lng }, map, icon: foxIcon });
  61. setTimeout(() => { if (foxMarker) foxMarker.setMap(null); foxMarker = null; }, 10000);
  62. }
  63.  
  64. // Автогесс
  65. function placePinMarker() {
  66. const { lat, lng } = globalCoordinates;
  67. let element = document.querySelector('[class^="guess-map_canvas__"]');
  68. if (!element) return;
  69.  
  70. const latLngFns = { latLng: { lat: () => lat, lng: () => lng } };
  71. const reactKey = Object.keys(element).find(k => k.startsWith("__reactFiber$"));
  72. const mapElementProps = element[reactKey];
  73. const mapElementClick = mapElementProps.return.return.memoizedProps.map.__e3_.click;
  74. const mapElementPropKey = Object.keys(mapElementClick)[0];
  75. const mapClickProps = mapElementClick[mapElementPropKey];
  76.  
  77. for (let key of Object.keys(mapClickProps)) {
  78. if (typeof mapClickProps[key] === "function") {
  79. mapClickProps[key](latLngFns);
  80. }
  81. }
  82. }
  83.  
  84. // Мини-инфо
  85. function showLocationInfo(countryName, countryCode, cityName) {
  86. let box = document.getElementById("location-info-box");
  87. if (!box) {
  88. box = document.createElement("div");
  89. box.id = "location-info-box";
  90. box.style.cssText = "position:absolute;top:100px;left:20px;z-index:9999;padding:10px 15px;background:rgba(0,0,0,0.85);color:white;font-size:16px;border-radius:8px;font-weight:bold;font-family:Arial,sans-serif;display:flex;align-items:center;gap:10px;";
  91. document.body.appendChild(box);
  92. }
  93.  
  94. const flagUrl = `https://flagcdn.com/w40/${countryCode.toLowerCase()}.png`;
  95. box.innerHTML = `
  96. <span>kiritz🦊 tip💡:</span>
  97. <img src="${flagUrl}" alt="${countryCode}" style="width:30px;height:auto;border-radius:4px;">
  98. <span>страна: ${countryName}</span>
  99. <span>город: ${cityName || "--"}</span>
  100. `;
  101. setTimeout(() => box.remove(), 5000);
  102. }
  103.  
  104. // Google Maps
  105. function openInGoogleMaps(lat, lng) {
  106. const url = `https://maps.google.com/?q=${lat},${lng}&ll=${lat},${lng}&z=5`;
  107. window.open(url, "_blank");
  108. }
  109.  
  110. // Полная инфа
  111. function toggleFullInfoBox() {
  112. if (fullInfoVisible) {
  113. document.getElementById("full-info-box")?.remove();
  114. clearInterval(fullInfoInterval);
  115. fullInfoVisible = false;
  116. return;
  117. }
  118.  
  119. const box = document.createElement("div");
  120. box.id = "full-info-box";
  121. box.style.cssText = "position:absolute;top:240px;left:20px;z-index:9999;padding:12px 15px;background:rgba(0,0,0,0.9);color:white;font-size:15px;border-radius:10px;font-family:Arial,sans-serif;white-space:pre-wrap;line-height:1.5;max-width:320px;cursor:move;";
  122. document.body.appendChild(box);
  123. fullInfoVisible = true;
  124.  
  125. makeDraggable(box);
  126.  
  127. const update = () => {
  128. const { lat, lng } = globalCoordinates;
  129. fetch(`https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lng}&format=json`)
  130. .then(res => res.json())
  131. .then(data => {
  132. const addr = data.address || {};
  133. const country = addr.country || "--";
  134. const code = addr.country_code || "xx";
  135. const state = addr.state || "--";
  136. const city = addr.city || addr.town || addr.village || "--";
  137. const road = addr.road || "--";
  138. const flagUrl = `https://flagcdn.com/w40/${code.toLowerCase()}.png`;
  139. const link = `https://maps.google.com/?q=${lat},${lng}&ll=${lat},${lng}&z=5`;
  140.  
  141. const pingStart = performance.now();
  142. const pingPromise = fetch("https://www.geoguessr.com", { mode: "no-cors" })
  143. .then(() => performance.now() - pingStart)
  144. .catch(() => -1);
  145.  
  146. pingPromise.then(ping => {
  147. const loss = ping < 0 ? 100 : 0;
  148. const pingDisplay = ping < 0 ? "нет ответа" : `${Math.round(ping)}ms`;
  149. box.innerHTML = `
  150. <img src="${flagUrl}" style="width:30px;height:auto;vertical-align:middle;border-radius:4px;">
  151. страна: ${country}
  152. область: ${state}
  153. город: ${city}
  154. улица: ${road}
  155. широта: ${lat.toFixed(5)}
  156. долгота: ${lng.toFixed(5)}
  157. <a href="${link}" target="_blank" style="color:#87cefa;text-decoration:underline;">🗺️ссылка</a>
  158.  
  159. ping: ${pingDisplay}
  160. loss: ${loss}%
  161. ~обновление 5 сек
  162. `;
  163. });
  164. })
  165. .catch(() => {
  166. box.innerText = "Ошибка загрузки данных...";
  167. });
  168. };
  169.  
  170. update();
  171. fullInfoInterval = setInterval(update, 5000);
  172. }
  173.  
  174. // Перетаскивание окна
  175. function makeDraggable(element) {
  176. let isDown = false, offset = [0, 0];
  177. element.addEventListener("mousedown", function (e) {
  178. isDown = true;
  179. offset = [element.offsetLeft - e.clientX, element.offsetTop - e.clientY];
  180. }, true);
  181. document.addEventListener("mouseup", () => isDown = false, true);
  182. document.addEventListener("mousemove", function (e) {
  183. e.preventDefault();
  184. if (isDown) {
  185. element.style.left = (e.clientX + offset[0]) + "px";
  186. element.style.top = (e.clientY + offset[1]) + "px";
  187. }
  188. }, true);
  189. }
  190.  
  191. // Кнопка 0 - Открыть/Закрыть окно с текстом
  192. function toggleTestBox() {
  193. if (testBoxVisible) {
  194. testBox.remove();
  195. testBoxVisible = false;
  196. } else {
  197. testBox = document.createElement("div");
  198. testBox.id = "test-box";
  199. testBox.innerHTML = `
  200. 🦊🦊 ИНФО🦊🦊 <br><br>
  201. 1️⃣ - показывает флаг страны, страна, город <br>
  202. <img src="https://i.imgur.com/KKB0pz7.png" alt="Flag Info" style="width: auto; height: auto;"><br>
  203. 2️⃣ - ставит лису на карте (5000 гесс) <br>
  204. <img src="https://i.imgur.com/qMWst90.png" alt="Fox Marker" style="width: auto; height: auto;"><br>
  205. 3️⃣ - открывает Google Maps с гессом <br>
  206. 4️⃣ - автогесс 5000 <br><br>
  207. 5️⃣ - отладка (полная информация о месте, пинг) <br>
  208. 0️⃣ - ИНФО (открыть/закрыть) <br><br>
  209. версия v0.25a <br>
  210. работают почти все режимы <br>
  211. в батлрофль кантрис работает только 1️⃣,3️⃣ и 5️⃣. <br>
  212. будешь читерить пизды получишь<br>
  213. <img src="https://i.pinimg.com/originals/37/a7/a1/37a7a10382550c1cf67461f0b84aeefb.gif" alt="Info GIF" style="width: auto; height: auto;">
  214. `;
  215. testBox.style.cssText = "position:absolute;top:300px;left:20px;z-index:9999;padding:10px 15px;background:rgba(0,0,0,0.85);color:white;font-size:16px;border-radius:8px;font-weight:bold;font-family:Arial,sans-serif;white-space:pre-wrap;line-height:1.5;";
  216. document.body.appendChild(testBox);
  217. testBoxVisible = true;
  218. makeDraggable(testBox);
  219. }
  220. }
  221.  
  222. // Горячие клавиши
  223. window.addEventListener("keydown", (e) => {
  224. const { lat, lng } = globalCoordinates;
  225. if (!lat || !lng) return;
  226. e.stopImmediatePropagation();
  227. switch (e.keyCode) {
  228. case 49: showLocationInfoFromCoords(lat, lng); break; // 1
  229. case 50: addFoxMarker(lat, lng); break; // 2
  230. case 51: openInGoogleMaps(lat, lng); break; // 3
  231. case 52: placePinMarker(); break; // 4
  232. case 53: toggleFullInfoBox(); break; // 5
  233. case 48: toggleTestBox(); break; // 0
  234. }
  235. }, true);
  236.  
  237. // Для клавиши 1
  238. function showLocationInfoFromCoords(lat, lng) {
  239. fetch(`https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lng}&format=json`)
  240. .then(res => res.json())
  241. .then(data => {
  242. const country = data.address?.country || "--";
  243. const countryCode = data.address?.country_code || "xx";
  244. const city = data.address?.city || data.address?.town || data.address?.village || "--";
  245. showLocationInfo(country, countryCode, city);
  246. })
  247. .catch(() => showLocationInfo("Ошибка", "xx", "--"));
  248. }