Tag your street views by date&address&generations(API key is need)
目前為
// ==UserScript==
// @name Geoguessr Map-Making Auto-Tag
// @namespace http://tampermonkey.net/
// @version 2.9
// @description Tag your street views by date&address&generations(API key is need)
// @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 = [];
let last_token = null;
let last_token_expiry = 0;
function getGeneration(data,country){
if (data&&data.imageHeight) {
if (data.imageHeight === 1664) {
return 'Gen1'
} else if (data.imageHeight === 6656) {
let lat=data.lat
let date;
if (data.date) {
date = new Date(data.date);
} else {
date = 'nodata';
}
if (date!=='nodata'&&((country == 'Bangladesh' && (date >= new Date('2021-04'))) ||
(country == 'Ecuador' && (date >= new Date('2022-03'))) ||
(country == 'Finland' && (date >= new Date('2020-09'))) ||
(country == 'India' && (date >= new Date('2021-10'))) ||
(country == 'Sri Lanka' && (date >= new Date('2021-02'))) ||
(country == 'Cambodia' && (date >= new Date('2022-10'))) ||
(country == 'Nigeria' && (date >= new Date('2021-06'))) ||
(country == 'United States' && lat > 52 && (date >= new Date('2019-01'))))) {
return 'Shitcam'
}
else if ((country === 'Australia' || 'Brazil'||'Canada' || 'Chile'|| 'Japan' || 'United Kingdom' || 'Ireland' || 'New Zealand'
|| 'Mexico'|| 'Russia' || 'United States' || 'Italy'||'Denmark' || 'Greece' || 'Romania' || 'Poland'
|| 'Czechia' )|| 'Switzerland'|| 'Sweden' || 'Finland'|| 'Belgium' || 'Luxembourg' || 'Netherlands' || 'South Africa'
|| 'Singapore' || 'Taiwan' || 'Hong Kong' || 'Monaco'||'Macao' || 'San Marino' || 'Andorra' || 'Isle of Man'
||'Jersey'||'France' ||'Germany' || 'Spain'|| 'Portugal' ) {
return 'Gen2or3'
}
else {return 'Gen3'}
}
else if(data.imageHeight === 8192){
return 'Gen4'
}
}
}
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 {
alert(`Error: ${response.status}, ${await response.text()}`);
}
}
async function getMeta(url) {
let country = 'nocountry',subdivision = 'nosub',locality = 'nolocality',route='noroute'
let year='noyear',month='nomonth'
let panoType='Unofficial',generation
try {
let response = await fetch(url);
if (response.status == 200) {
let data = await response.json();
if (data.date) {
const matchYear = data.date.match(/\d{4}/);
if (matchYear) {
year = matchYear[0];
}
const matchMonth = data.date.match(/-(\d{2})/);
if (matchMonth) {
month = matchMonth[1];
}
}
if (data.copyright.includes('Google')) {
panoType = 'Official';
}
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;
}
if (add.types.includes('route')) {
route = add.longName;
}
}
generation=getGeneration(data,country)
}
return [country, subdivision, locality,route,year,month,panoType,generation]
}
catch (error) {
console.log(error);
}
}
async function get_meta(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 getMeta(url);
}
async function search_meta(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 getMeta(url);
}
var CHUNK_SIZE = 1200;
var promises = [];
async function processCoord(coord, tags) {
if (!coord.extra) {
coord.extra = {};
}
if (!coord.extra.tags) {
coord.extra.tags = [];
}
var meta;
if (coord.panoId ) {
meta = await get_meta(coord.panoId)
}
else {
meta =await search_meta(coord.lat,coord.lng)
}
if (meta){
let countryTag=meta[0]
let subdivisionTag=meta[1]
let localityTag=meta[2]
let routeTag=meta[3]
let yearTag=meta[4]
let monthTag=meta[5]
let typeTag=meta[6]
let generationTag=meta[7]
if (tags.includes('country')) coord.extra.tags.push(countryTag);
if (tags.includes('subdivision')) coord.extra.tags.push(subdivisionTag);
if (tags.includes('locality')) coord.extra.tags.push(localityTag);
if (tags.includes('route')) coord.extra.tags.push(routeTag);
if (tags.includes('year')) coord.extra.tags.push(yearTag);
if (tags.includes('month')) coord.extra.tags.push(monthTag);
if (tags.includes('type')) coord.extra.tags.push(typeTag);
if (tags.includes('generation')&&typeTag=='Official') coord.extra.tags.push(generationTag);
}
else{
coord.extra.tags.push('nopano')
}
newData.push(coord);
}
async function processChunk(chunk, tags) {
var promises = chunk.map(async coord => {
let panoId = coord.panoId;
let latLng = {lat: coord.lat, lng: coord.lng};
await processCoord(coord, tags)
});
await Promise.all(promises);
}
async function processData(tags) {
try {
for (let i = 0; i < data.customCoordinates.length; i += CHUNK_SIZE) {
let chunk = data.customCoordinates.slice(i, i + CHUNK_SIZE);
await processChunk(chunk, tags);
}
GM_setClipboard(JSON.stringify(newData));
alert("New JSON data has been copied to the clipboard!");
} catch (error) {
alert("Invalid JSON data");
console.error('Error processing JSON data:', error);
}
}
processData(tags);
}
var mainButtonContainer = document.createElement('div');
mainButtonContainer.style.position = 'fixed';
mainButtonContainer.style.right = '20px';
mainButtonContainer.style.bottom = '20px';
document.body.appendChild(mainButtonContainer);
var buttonContainer = document.createElement('div');
buttonContainer.style.position = 'fixed';
buttonContainer.style.right = '20px';
buttonContainer.style.bottom = '60px';
buttonContainer.style.display = 'none';
document.body.appendChild(buttonContainer);
function createCheckbox(text, tags) {
var label = document.createElement('label');
var checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.value = text;
checkbox.name = 'tags';
checkbox.id = tags;
label.appendChild(checkbox);
label.appendChild(document.createTextNode(text));
buttonContainer.appendChild(label);
return checkbox;
}
var triggerButton = document.createElement('button');
triggerButton.textContent = 'Star Tagging';
triggerButton.addEventListener('click', function() {
var checkboxes = document.getElementsByName('tags');
var checkedTags = [];
for (var i=0; i<checkboxes.length; i++) {
if (checkboxes[i].checked) {
checkedTags.push(checkboxes[i].id);
}
}
runScript(checkedTags);
});
buttonContainer.appendChild(triggerButton);
var mainButton = document.createElement('button');
mainButton.textContent = 'Auto-Tag';
mainButton.addEventListener('click', function() {
if (buttonContainer.style.display === 'none') {
buttonContainer.style.display = 'block';
} else {
buttonContainer.style.display = 'none';
}
});
mainButtonContainer.appendChild(mainButton);
createCheckbox('Year', 'year');
createCheckbox('Month', 'month');
createCheckbox('Type', 'type');
createCheckbox('Country', 'country');
createCheckbox('Subdivision', 'subdivision');
createCheckbox('Locality', 'locality');
createCheckbox('Route', 'route');
createCheckbox('Generations', 'generation');
})();