图寻复盘工具

多功能转换图寻复盘链接成街景链接,显示地点位置信息和拍摄时间以及百度街景的panoId

اعتبارا من 11-07-2024. شاهد أحدث إصدار.

// ==UserScript==
// @name         图寻复盘工具
// @namespace    https://greasyfork.org/users/1179204
// @version      1.0.1
// @description  多功能转换图寻复盘链接成街景链接,显示地点位置信息和拍摄时间以及百度街景的panoId
// @match        https://tuxun.fun/replay-pano?gameId=*&round=*
// @icon         data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNDggNDgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgZmlsbD0iIzAwMDAwMCI+PGcgaWQ9IlNWR1JlcG9fYmdDYXJyaWVyIiBzdHJva2Utd2lkdGg9IjAiPjwvZz48ZyBpZD0iU1ZHUmVwb190cmFjZXJDYXJyaWVyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjwvZz48ZyBpZD0iU1ZHUmVwb19pY29uQ2FycmllciI+PHRpdGxlPjcwIEJhc2ljIGljb25zIGJ5IFhpY29ucy5jbzwvdGl0bGU+PHBhdGggZD0iTTI0LDEuMzJjLTkuOTIsMC0xOCw3LjgtMTgsMTcuMzhBMTYuODMsMTYuODMsMCwwLDAsOS41NywyOS4wOWwxMi44NCwxNi44YTIsMiwwLDAsMCwzLjE4LDBsMTIuODQtMTYuOEExNi44NCwxNi44NCwwLDAsMCw0MiwxOC43QzQyLDkuMTIsMzMuOTIsMS4zMiwyNCwxLjMyWiIgZmlsbD0iI2ZmOTQyNyI+PC9wYXRoPjxwYXRoIGQ9Ik0yNS4zNywxMi4xM2E3LDcsMCwxLDAsNS41LDUuNUE3LDcsMCwwLDAsMjUuMzcsMTIuMTNaIiBmaWxsPSIjZmZmZmZmIj48L3BhdGg+PC9nPjwvc3ZnPg==
// @author       KaKa
// @grant        GM_setClipboard
// @grant        GM_addStyle
// @copyright    KaKa
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';
GM_addStyle(`
    #coordinates-container {
        position: fixed;
        top: 100px;
        left: 10px;
        padding: 10px;
        border-radius: 20px !important;
        z-index: 1000;
        display: flex;
        flex-direction: column;
        width: 180px;
    }

    #coordinates-container button {
        cursor: pointer;
        width: 100% !important;
        font-weight: bold !important;
        border: 8px solid #000000 !important;
        text-align: left !important;
        padding-left: 8px !important;
        padding-right: 8px !important;
        backdrop-filter: blur(10px);
        margin-bottom: 5px;
        border-radius: 4px;
        background-color: #000000 !important;
        color: #A0A0A0 !important;
    };

    #conversion-mode {
        font-family: Arial, sans-serif !important;
        color: #000000 !important;
        text-shadow: -1px -1px 0 #A0A0A0, 1px -1px 0 #A0A0A0, -1px 1px 0 #A0A0A0, 1px 1px 0 #A0A0A0 !important;
        margin-bottom: 5px !important;
    }

    .link-button {
        background: none!important;
        border: none;
        padding: 0!important;
        color: #FFCC00 !important;
        text-decoration: underline;
        cursor: pointer;
    }

    .link-button:hover {
        color: #FFCC00 !important;
    }
`);
    const container = document.createElement('div');
    container.id = 'coordinates-container';
    document.body.appendChild(container);

    const conversionModeLabel = document.createElement('div');
    conversionModeLabel.id = 'conversion-mode';
    conversionModeLabel.style.display='none'
    container.appendChild(conversionModeLabel);


    const openButton = document.createElement('button');
    openButton.textContent = 'Open in Map';
    container.appendChild(openButton);

    const copyButton = document.createElement('button');
    copyButton.textContent = 'Copy to Clipboard';
    container.appendChild(copyButton);

    let currentLink = '';
    let globalPanoId=null
    openButton.onclick = () => window.open(currentLink, '_blank');
    copyButton.onclick = () => {
        if (globalPanoId)currentLink=globalPanoId
        GM_setClipboard(currentLink, 'text');
        alert('Link copied to clipboard');
    };


const areaButton = document.createElement('button');
areaButton.textContent = 'Area';
container.appendChild(areaButton);

const streetButton = document.createElement('button');
streetButton.textContent = 'Street';
container.appendChild(streetButton);

const timeButton = document.createElement('button');
timeButton.textContent = 'Time';
container.appendChild(timeButton);

let globalTimeInfo = null;
let globalAreaInfo = null;
let globalStreetInfo = null;


function updateButtonContent() {
    areaButton.textContent = globalAreaInfo ? `${globalAreaInfo}` : 'Area';
    streetButton.textContent = globalStreetInfo ? `${globalStreetInfo}` : 'Street';
    timeButton.textContent = globalTimeInfo ? `${globalTimeInfo}` : 'Time';
    copyButton.textContent=globalPanoId ? `${globalPanoId.substring(6,10)}, ${globalPanoId.substring(25,27)}` : 'Copy to clipboard'
    copyButton.style.fontSize='15px'
}


setInterval(updateButtonContent, 1000);
    var realSend = XMLHttpRequest.prototype.send;

XMLHttpRequest.prototype.send = function(value) {
    this.addEventListener('load', function() {
        if (this._url && this._url.includes('https://tuxun.fun/api/v0/tuxun/mapProxy/getGooglePanoInfoPost')) {
            const responseText = this.responseText;
            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*\]/;
            const coordinateMatches = coordinatePattern.exec(responseText);
            if (coordinateMatches) {
                const latitude = coordinateMatches[1] || coordinateMatches[3];
                const longitude = coordinateMatches[2] || coordinateMatches[4];
                if (latitude && longitude) {
                    currentLink = `https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=${latitude},${longitude}`;
                }
            }

            const countryPattern = /,\s*"([A-Z]{2})"\s*\],null,\[/;
            const countryMatches = countryPattern.exec(responseText);
            let countryCode = countryMatches ? countryMatches[1] : '未知国家';

            const areaPattern = /\[\[\s*"([^"]+)",\s*"[a-z]{2}"\s*\],\s*\["([^"]+)",\s*"zh"\s*\]\]/;
            const areaMatches = areaPattern.exec(responseText);
            if (areaMatches && areaMatches.length >= 3) {
                globalAreaInfo = `${countryCode}, ${areaMatches[2]}`;
            }


            const fullAddressPattern = /\[\s*null,\s*null,\s*\[\s*\["([^"]+)",\s*"[a-z]{2}"\s*\]\]/;
            const addressMatches = fullAddressPattern.exec(responseText);

            if (addressMatches && addressMatches.length > 1) {
                globalStreetInfo = addressMatches[1];
            } else {
                globalStreetInfo = '未知地址';
            }

            const timePattern = /\[\d+,\d+,\d+,null,null,\[null,null,"launch",\[\d+\]\],null,\[(\d{4}),(\d{1,2})\]\]/;
            const timeMatches = timePattern.exec(responseText);
            if (timeMatches) {
                globalTimeInfo = `${timeMatches[1]}年${timeMatches[2]}月`;
            } else {
                globalTimeInfo = '未知时间';
            }
        }
        if (this._url && this._url.includes('mapProxy/getPanoInfo')) {
            var responseData
            const responseText = this.responseText;
            if (responseText) responseData=JSON.parse(responseText)
            if(responseData){

            const latitude = responseData.data.lat
            const longitude =responseData.data.lng
            globalPanoId=responseData.data.pano
            if (globalPanoId){
                const year=parseInt(globalPanoId.substring(9,12))
                const month=parseInt(globalPanoId.substring(12,14))
                const day=parseInt(globalPanoId.substring(14,16))
                globalTimeInfo = `20${year}年${month}月${day}日`;
            }
                else{
                    globalTimeInfo = '未知时间';
                }
            const heading=responseData.data.centerHeading
            if (latitude && longitude) {
                currentLink = `https://map.baidu.com/@12707848.16,2573405.14,21z,87t,-139.74h#panoid=${globalPanoId}&panotype=street&heading=${heading}&pitch=0&l=21&tn=B_NORMAL_MAP&sc=0&newmap=1&shareurl=1&pid=${globalPanoId}`;
            }

             getAddressFromApi(latitude,longitude) .then(address => {
                 var province,city,suburb,street
                 globalAreaInfo=''
                if (address) {
                    if (address.province) {
                        province = address.province;
                         globalAreaInfo += `中国, ${province}`
                    }

                    if (address.city) {
                        city = address.city;
                        globalAreaInfo +=`, ${city}`
                    }

                    if (address.suburb) {
                        suburb = address.suburb;
                        globalAreaInfo +=`, ${suburb}`
                    }

                    if (address.street) {
                        globalStreetInfo = address.street;
                    }

                }
            })
            .catch(error => {
                console.error('获取地址时发生错误:', error);
            });

            }
        }
    }, false);

    realSend.call(this, value);

    function getAddressFromApi(latitude, longitude) {
        return new Promise((resolve, reject) => {
            const apiUrl = `https://nominatim.openstreetmap.org/reverse?format=json&lat=${latitude}&lon=${longitude}&addressdetails=1&accept-language=cn`;

            fetch(apiUrl)
                .then(response => response.json())
                .then(data => {
                const addressInfo = {
                    province: data?.address?.state || '',
                    city: data?.address?.city || '',
                    suburb: data?.address?.suburb || '',
                    street: data?.address?.road || '',
                };
                resolve(addressInfo);
            })
                .catch(error => {
                console.error('Error fetching address:', error);
                reject(error);
            });
        });
    }
};

    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);
    };

    window.addEventListener('popstate', function(event) {
    const container = document.getElementById('coordinates-container');
    if (container) {
        container.remove();
    }
});


})();