您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Tag your street views by date and address
当前为
// ==UserScript== // @name Geoguessr Map-Making Auto-Tag // @namespace http://tampermonkey.net/ // @version 2.4 // @description Tag your street views by date and address // @author KaKa // @match https://map-making.app/maps/* // @grant GM_setValue // @grant GM_getValue // @grant GM_setClipboard // @license MIT // ==/UserScript== (function() { 'use strict'; async function runScript(tags) { let api_key = GM_getValue("api_key"); if (!api_key) { api_key = prompt("Please enter your Google API key"); GM_setValue("api_key", api_key); } const option = confirm('Do you want to input data from the clipboard? If you click "Cancel", you will need to upload a JSON file.'); let data; if (option) { const text = await navigator.clipboard.readText(); try { data = JSON.parse(text); } catch (error) { alert('The input JSON data is invalid or incorrectly formatted.'); return; } } else { const input = document.createElement('input'); input.type = 'file'; document.body.appendChild(input); data = await new Promise((resolve) => { input.addEventListener('change', async () => { const file = input.files[0]; const reader = new FileReader(); reader.onload = (event) => { try { const result = JSON.parse(event.target.result); resolve(result); document.body.removeChild(input); } catch (error) { alert('The input JSON data is invalid or incorrectly formatted.'); } }; reader.readAsText(file); }); input.click(); }); } const newData = []; async function getMetaData(url) { try { const response = await fetch(url); const data = await response.json(); console.log(data); if (data.status == "OK") { let year = 'nodate'; const match = data.date.match(/\d{4}/); if (match) { year = match[0]; } let panoType = 'unofficial'; if (data.copyright.includes('Google')) { panoType = 'official'; } return [year, panoType]; } else { return ["nodata","nodata"]; } } catch (error) { console.error(`Error fetching metadata: ${error}`); } } function get_Meta(id) { const url = `https://maps.googleapis.com/maps/api/streetview/metadata?pano=${id}&key=${api_key}`; return getMetaData(url); } function search_Meta(lat, lng) { const url = `https://maps.googleapis.com/maps/api/streetview/metadata?location=${lat},${lng}&key=${api_key}`; return getMetaData(url); } let last_token = null; let last_token_expiry = 0; async function get_Token(api_key) { let current_time = Date.now() / 1000; if (last_token && last_token_expiry > current_time) { return last_token; } let url = `https://tile.googleapis.com/v1/createSession?key=${api_key}`; let headers = {'Content-Type': 'application/json'}; let data = { "mapType": "streetview", "language": "en-US", "region": "US"}; let response = await fetch(url, {method: 'POST', headers: headers, body: JSON.stringify(data)}); if (response.status == 200) { let token = (await response.json()).session; last_token_expiry = current_time + 5 * 60; last_token = token; return token; } else { console.log(`Error: ${response.status}, ${await response.text()}`); } } async function getAddress(url) { let country = 'nodata'; let subdivision = 'nodata'; let locality = 'nodata'; try { let response = await fetch(url); if (response.status == 200) { let data = await response.json(); for (let add of data.addressComponents) { if (add.types.includes('country')) { country = add.longName; } if (add.types.includes('administrative_area_level_1')) { subdivision = add.longName; } if (add.types.includes('locality')) { locality = add.longName; } } } } catch (error) { console.log(error); } return [country, subdivision, locality]; } async function get_add(id) { let tk = await get_Token(api_key); let url = `https://tile.googleapis.com/v1/streetview/metadata?session=${tk}&key=${api_key}&panoId=${id}`; return getAddress(url); } async function search_add(lat,lng) { let tk = await get_Token(api_key); let url = `https://tile.googleapis.com/v1/streetview/metadata?session=${tk}&key=${api_key}&lat=${lat}&lng=${lng}&radius=50`; return getAddress(url); } var CHUNK_SIZE = 1000; var promises = []; async function processCoord(coord, tags) { if (!coord.extra) { coord.extra = {}; } if (!coord.extra.tags) { coord.extra.tags = []; } var meta; var address; if (coord.panoId) { meta = await get_Meta(coord.panoId); address= await get_add(coord.panoId); } else { meta = await search_Meta(coord.lat, coord.lng); address= await search_add(coord.lat, coord.lng); } if (meta && meta.length >= 2) { var year_tag = meta[0]; var type_tag = meta[1]; var country_tag=address[0] var subdivision_tag=address[1] var locality_tag=address[2] if (tags.includes('year')) coord.extra.tags.push(year_tag); if (tags.includes('type')) coord.extra.tags.push(type_tag); if (tags.includes('country')) coord.extra.tags.push(country_tag); if (tags.includes('subdivision')) coord.extra.tags.push(subdivision_tag); if (tags.includes('locality')) coord.extra.tags.push(locality_tag); newData.push(coord); } } async function processChunk(chunk) { var promises = chunk.map(async coord => await processCoord(coord, tags)); await Promise.all(promises); } async function processData(tags) { for (let i = 0; i < data.customCoordinates.length; i += CHUNK_SIZE) { let chunk = data.customCoordinates.slice(i, i + CHUNK_SIZE); await processChunk(chunk); } GM_setClipboard(JSON.stringify(newData)); alert("New JSON data has been copied to the clipboard!"); } processData(tags); } var buttonContainer = document.createElement('div'); buttonContainer.style.position = 'absolute'; buttonContainer.style.left = '20px'; buttonContainer.style.bottom = '48px'; document.body.appendChild(buttonContainer); function createButton(text, tags) { var button = document.createElement('button'); button.textContent = text; button.style.display = 'none'; button.addEventListener('click', async function() { await runScript(tags); }); buttonContainer.appendChild(button); return button; } var mainButton = document.createElement('button'); mainButton.textContent = 'Auto-Tag'; mainButton.addEventListener('click', function() { for (var i = 0; i < buttonContainer.children.length; i++) { var button = buttonContainer.children[i]; if (button.style.display === 'none') { button.style.display = 'block'; } else { button.style.display = 'none'; } } }); document.body.appendChild(mainButton); createButton('Tag by Year', ['year']); createButton('Tag by Type',[ 'type']); createButton('Tag by Country', ['country']); createButton('Tag by Subdivision', ['subdivision']); createButton('Tag by Locality', ['locality']); })();