// ==UserScript== // @name Geoguessrtips // @namespace https://www.leonbrandt.com // @version 3.1 // @description A specific map is required to prompt. Press 1 to prompt for knowledge in plonkit, such as: plonkit novice guide, etc., or a question bank with tips keywords can be used. // @author Leon Brandt // @homepage https://www.leonbrandt.com // @match https://www.geoguessr.com/* // @grant GM_xmlhttpRequest // @run-at document-idle // @connect nominatim.openstreetmap.org // @connect knowledgetips.fun // @connect cdn.nlark.com // @downloadURL https://update.greasyfork.icu/scripts/479164/Geoguessrtips.user.js // @updateURL https://update.greasyfork.icu/scripts/479164/Geoguessrtips.meta.js // ==/UserScript== (function() { 'use strict'; let isMatch = true; const modalHTML = `
倒计时: 15秒
地址信息: ${storedAddress}
`; if (countdownInterval) { clearInterval(countdownInterval); } let countdown = 15; countdownInterval = setInterval(function() { countdown--; modalContent.innerHTML = `倒计时: ${countdown}秒
`; if (countdown <= 0) { clearInterval(countdownInterval); modalContent.innerHTML = `省份:${storedAddress}
`; const tags = serverText.split('; '); tags.forEach((tag, index) => { const tagElement = createTagElement(tag, index); modalContent.appendChild(tagElement); }); } }, 1000); modalContent.innerHTML = '倒计时: 15秒'; if (modal.style.display !== 'none') { modal.style.display = 'block'; modal.style.opacity = '1'; modal.style.visibility = 'visible'; } } function closeModal() { const modal = document.getElementById('customModal'); modal.style.opacity = '0'; modal.style.visibility = 'hidden'; setTimeout(() => modal.style.display = 'none', 100); } let isSaveTagActive = false; function saveTag(paragraph, index) { if (!isSaveTagActive) { return; } const editedText = paragraph.textContent.trim(); paragraph.contentEditable = "false"; let tags = []; tags = localStorage.getItem('tagsText') ? localStorage.getItem('tagsText').split('; ') : []; if (index !== undefined) { if (editedText === '') { tags.splice(index, 1); const tagContainer = paragraph.parentElement; if (tagContainer) { tagContainer.remove(); } } else { tags[index] = editedText; } } else { if (editedText !== '') { tags.push(editedText); } } tags = tags.filter(tag => tag && tag.trim()); const updatedTagsText = tags.join('; '); localStorage.setItem('tagsText', updatedTagsText); const storedCoordinates = JSON.parse(localStorage.getItem('coordinates')); const dataToSend = { mapsId: localStorage.getItem('mapsId'), coordinates: storedCoordinates, tagsText: updatedTagsText }; const saveButton = paragraph.parentElement.querySelector('.save-button'); if (saveButton) { saveButton.style.display = 'none'; } GM_xmlhttpRequest({ method: "POST", url: 'http://knowledgetips.fun:3000/save-data', data: JSON.stringify(dataToSend), headers: { "Content-Type": "application/json" }, onload: function(response) { } }); } isSaveTagActive = false; isSaveTagActive = true; //更新标签 function updateTagNumbers() { const tags = document.querySelectorAll('.tag-container'); tags.forEach((tag, index) => { const label = tag.querySelector('.tag-label'); if (label) { label.textContent = `${index + 1}. `; } }); } function addNewTag() { const inputBox = document.getElementById('customInputBox'); const newText = inputBox.value.trim(); if (newText) { const newTagElement = createTagElement(newText); const modalContent = document.getElementById('modalContent'); modalContent.appendChild(newTagElement); saveTag(newTagElement.querySelector('p')); inputBox.value = ''; updateTagNumbers(); } const customInputBox = document.getElementById('customInputBox'); customInputBox.style.height = '30px'; } const addButton = document.getElementById('addButton'); if (addButton) { } else { } addButton.addEventListener('click', addNewTag); let isPinned = false; function loadPinState() { const savedState = localStorage.getItem('isPinned'); if (savedState !== null) { isPinned = savedState === 'true'; } updatePinButton(); } function updatePinButton() { const pinButton = document.getElementById('pinModal'); pinButton.textContent = isPinned ? '📍' : '📌'; } function togglePin() { isPinned = !isPinned; localStorage.setItem('isPinned', isPinned); updatePinButton(); } document.getElementById('pinModal').addEventListener('click', function(event) { togglePin(); event.stopPropagation(); }); window.addEventListener('load', loadPinState); //以上是置顶函数变量 let isDragging = false; let dragStartX, dragStartY; let originalX, originalY; document.getElementById('customModalHeader').addEventListener('mousedown', function(e) { if (e.target !== this && e.target !== document.querySelector('#customModalHeader h2')) { return; } isDragging = true; dragStartX = e.clientX; dragStartY = e.clientY; const modal = document.getElementById('customModal'); originalX = parseInt(window.getComputedStyle(modal).left, 10); originalY = parseInt(window.getComputedStyle(modal).top, 10); e.preventDefault(); }); document.addEventListener('mousemove', function(e) { if (!isDragging) return; let newX = originalX + e.clientX - dragStartX; let newY = originalY + e.clientY - dragStartY; updateModalPosition(newX, newY); }); document.addEventListener('mouseup', function(e) { if (isDragging) { isDragging = false; let newX = originalX + e.clientX - dragStartX; let newY = originalY + e.clientY - dragStartY; updateModalPosition(newX, newY); localStorage.setItem('modalPosition', JSON.stringify({ x: newX, y: newY })); } }); document.addEventListener('click', function(event) { const modal = document.getElementById('customModal'); if (!isPinned && !modal.contains(event.target)) { closeModal(); } }); document.getElementById('modalClose').addEventListener('click', closeModal); function toggleModal() { const modal = document.getElementById('customModal'); if (modal.style.opacity === '1' || modal.style.visibility === 'visible') { modal.style.opacity = '0'; modal.style.visibility = 'hidden'; modal.style.display = 'none'; } else { modal.style.opacity = '1'; modal.style.visibility = 'visible'; modal.style.display = 'block'; } } document.addEventListener("keyup", function(evt) { const targetTagName = (evt.target || evt.srcElement).tagName; if (evt.key === '1' && targetTagName !== 'INPUT' && targetTagName !== 'TEXTAREA') { toggleModal(); } }); const mapsIdMatch = window.location.href.match(/maps-start\?mapsId=(\d+)/); const mapsId = mapsIdMatch ? mapsIdMatch[1] : localStorage.getItem('mapsId') || '未找到ID'; if (mapsIdMatch) { localStorage.setItem('mapsId', mapsId); } const mapsIdPattern = /maps\/([a-zA-Z0-9]+|famous-places)/; const addressPattern = /\[\["(.*?)","zh"\]\]|\[\[.*?,\["(.*?)","zh"\]\]\]/; const coordinatePattern = /\[\[null,null,(-?\d+\.\d+),(-?\d+\.\d+)\],\[\d+\.\d+\],\[\d+\.\d+,\d+\.\d+,\d+\.\d+\]\]|\[\s*null,\s*null,\s*(-?\d+\.\d+),\s*(-?\d+\.\d+)\s*\]/; var realSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function(value) { let currentUrl = this._url; this.addEventListener("loadstart", function() { currentUrl = this._url; }); this.addEventListener("load", function() { let previousMapsId = localStorage.getItem('previousMapsId'); let currentMapsId = localStorage.getItem('mapsId'); const currentUrlMapsIdMatch = mapsIdPattern.exec(window.location.href); if (currentUrlMapsIdMatch) { const newMapsId = currentUrlMapsIdMatch[1]; if (newMapsId !== currentMapsId) { localStorage.setItem('previousMapsId', currentMapsId); localStorage.setItem('mapsId', newMapsId); } } currentMapsId = localStorage.getItem('mapsId'); previousMapsId = localStorage.getItem('previousMapsId'); if (currentMapsId !== previousMapsId) { } else { } if (currentUrl.includes('https://maps.googleapis.com/$rpc/google.internal.maps.mapsjs.v1.MapsJsInternalService/SingleImageSearch') || currentUrl.includes('https://maps.googleapis.com/$rpc/google.internal.maps.mapsjs.v1.MapsJsInternalService/GetMetadata')) { /* https://maps.googleapis.com/$rpc/google.internal.maps.mapsjs.v1.MapsJsInternalService/GetMetadata https://maps.googleapis.com/$rpc/google.internal.maps.mapsjs.v1.MapsJsInternalService/SingleImageSearch */ const responseText = this.responseText; let addressMatches; let isAddressFound = false; let loopCount = 0; while ((addressMatches = addressPattern.exec(responseText)) !== null && loopCount < 3) { loopCount++; isAddressFound = true; const address = addressMatches[1] || addressMatches[2]; const storedAddress = localStorage.getItem('address'); if (address !== storedAddress) { localStorage.setItem('address', address); } else { } break; } if (!isAddressFound) { localStorage.removeItem('address'); } if (coordinatePattern.test(responseText)) { // let latitude, longitude; const matches = coordinatePattern.exec(responseText); if (matches) { // function confuse() { var seed = Math.random(); return seed.toString(36).substring(2, 15); } var unused = confuse(); var coordinateData = {lat: undefined, lon: undefined}; if (matches[1] !== undefined && matches[2] !== undefined) { latitude = matches[1]; longitude = matches[2]; } else if (matches[3] !== undefined && matches[4] !== undefined) { latitude = matches[3]; longitude = matches[4]; } (function(){ var fakeLat = Math.random() * 100; var fakeLon = Math.random() * 100; // })(); if (latitude !== undefined && longitude !== undefined) { const storedCoordinatesString = localStorage.getItem('coordinates'); let storedCoordinates = null; if (storedCoordinatesString) { storedCoordinates = JSON.parse(storedCoordinatesString); }else { } function removeAllMyImages() { let existingImages = document.querySelectorAll('#myImage'); existingImages.forEach(function(img) { img.parentNode.removeChild(img); }); } const tolerance = 0.005; if (!storedCoordinates || !isCoordinateCloseEnough(storedCoordinates, latitude, longitude, tolerance)) { localStorage.removeItem('tagsText'); localStorage.removeItem('address'); localStorage.removeItem('state'); removeAllMyImages(); const coordinates = { latitude, longitude }; localStorage.setItem('coordinates', JSON.stringify(coordinates)); function getAddress(lat, lon) { // console.log(`Fetching address for coordinates: Latitude = ${lat}, Longitude = ${lon}`); return new Promise((resolve) => { // 移除 reject 参数 try { GM_xmlhttpRequest({ method: "GET", url: `https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lon}&format=json`, onload: function(response) { // console.log("Received response from OpenStreetMap API", response); if (response.status === 200) { // console.log("Successfully fetched address:", response.responseText); resolve(JSON.parse(response.responseText)); } else { console.error(`无法获取地址。状态码: ${response.status}`); resolve({ error: `无法获取地址。状态码: ${response.status}`, lat, lon }); // 使用 resolve 代替 reject } }, onerror: function(error) { console.error("在获取地址时发生错误:", error); resolve({ error: "在获取地址时发生错误", lat, lon }); // 使用 resolve 代替 reject } }); } catch (error) { console.error("在获取地址时发生异常:", error); resolve({ error: "在获取地址时发生异常", lat, lon }); // 使用 resolve 代替 reject } }); } getAddress(latitude, longitude) .then(addressData => { function processAddressData(data, key) { if (data && data.address && data.address[key]) { const fullString = data.address[key]; const value = fullString.split('/')[0].trim(); const storedValue = localStorage.getItem(key); if (storedValue !== null) { if (storedValue !== value) { localStorage.setItem(key, value); } else { localStorage.setItem(key, value); } } else { localStorage.setItem(key, value); } } else { } } if (addressData) { processAddressData(addressData, 'country'); processAddressData(addressData, 'state'); processAddressData(addressData, 'region'); processAddressData(addressData, 'city'); } const country = localStorage.getItem('country'); const dataToSend = JSON.stringify({ mapsId, coordinates: `${latitude},${longitude}`,country }); function checkAndSendRequest() { if (isMatch) { sendRequest(); } else { } } let retryCount = 0; function sendRequest() { GM_xmlhttpRequest({ method: "POST", url: 'http://knowledgetips.fun:3000/receive-data', data: JSON.stringify({ mapsId, coordinates: `${latitude},${longitude}`,country }), headers: { "Content-Type": "application/json" }, onload: function(response) { const jsonResponse = JSON.parse(response.responseText); if (jsonResponse.hasOwnProperty('mymapsid')) { isMatch = jsonResponse.mymapsid; } if (jsonResponse.match && jsonResponse.tags) { const tagsText = jsonResponse.tags.join('; '); let imgTag = document.getElementById('uniqueImageId'); if (!imgTag) { imgTag = document.createElement('img'); imgTag.id = 'uniqueImageId'; imgTag.style.height = "80vh"; imgTag.style.width = 'auto' ; imgTag.style.position = 'absolute'; imgTag.style.left = '30%'; imgTag.style.top = '46%'; imgTag.style.transform = 'translate(-50%, -50%)'; imgTag.style.zIndex = 1200; imgTag.style.display = 'none'; document.body.appendChild(imgTag); } if (!window.hasAddedKeyListener) { document.addEventListener('keyup', function(event) { if (event.key === '2') { if (imgTag.style.display === 'none') { let lastImageUrl = localStorage.getItem('lastImageUrl'); if (lastImageUrl) { imgTag.src = lastImageUrl; } imgTag.style.display = 'block'; } else { imgTag.style.display = 'none'; } } }); window.hasAddedKeyListener = true; } let lastImageUrl = localStorage.getItem('lastImageUrl'); if (jsonResponse.images && jsonResponse.images.length > 0) { const imageUrl = jsonResponse.images[0]; imgTag.src = imageUrl; localStorage.setItem('lastImageUrl', imageUrl); } else { } localStorage.setItem('tagsText', tagsText); // localStorage.setItem('coordinates', JSON.stringify(coordinates)); const modal = document.getElementById('customModal'); if (modal.style.display !== 'none') { const modalContent = document.getElementById('modalContent'); modalContent.textContent = tagsText; } showModal(tagsText); } else { modalContent.innerHTML = '无提示'; } // }, onerror: function() { if (retryCount < 3) { retryCount++; setTimeout(SendRequest, 3000); } else { } }, ontimeout: function() { } }); } checkAndSendRequest(); window.checkAndSendRequest = checkAndSendRequest; }) .catch(errorData => { }); } else { } function isCoordinateCloseEnough(storedCoordinates, latitude, longitude, tolerance) { const latDifference = Math.abs(storedCoordinates.latitude - latitude); const lonDifference = Math.abs(storedCoordinates.longitude - longitude); return latDifference <= tolerance && lonDifference <= tolerance; } }else { } } else { } if (latitude !== undefined && longitude !== undefined) { } }else { modalContent.innerHTML = ''; // } } }, false); realSend.call(this, value); }; XMLHttpRequest.prototype.realOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url, async, user, pass) { this._url = url; this.realOpen(method, url, async, user, pass); }; if (XMLHttpRequest.prototype.send === XMLHttpRequest.prototype.realSend) { } else { } })();