Strava Global Heatmap TMS server link generator for JOSM

Generates Strava Global Heatmap TMS server link for OpenStreetMap JOSM editor

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください。
// ==UserScript==
// @name         Strava Global Heatmap TMS server link generator for JOSM
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  Generates Strava Global Heatmap TMS server link for OpenStreetMap JOSM editor
// @author       UrSuS
// @match        *.strava.com/maps/global-heatmap*
// @icon         https://www.google.com/s2/favicons?domain=strava.com
// @grant        GM_cookie
// @run-at document-body
// ==/UserScript==
(function () {
    "use strict";

    const specificHrefPartial = "/login?redirect";

    function waitForElm(selector) {
        return new Promise(resolve => {
            if (document.querySelector(selector)) {
                return resolve(document.querySelector(selector));
            }

            const observer = new MutationObserver(mutations => {
                if (document.querySelector(selector)) {
                    observer.disconnect();
                    resolve(document.querySelector(selector));
                }
            });

            // If you get "parameter 1 is not of type 'Node'" error, see https://stackoverflow.com/a/77855838/492336
            observer.observe(document.body, {
                childList: true,
                subtree: true
            });
        });
    }


    waitForElm(`a[href*="${specificHrefPartial}"]`).then((elm) => {
        elm.click();
    });


    waitForElm('[data-key="my-routes"]').then((elm) => {
        addButton(getTMSlink);
    });

    function addButton(onclick, cssObj) {

        const oFindDiv = document.querySelectorAll('[data-key="my-routes"]');
        const oParentDiv = oFindDiv[0].parentNode;

        let oBtnTMSDiv = document.createElement("Div");
        oBtnTMSDiv.innerHTML = "<div><a target='_blank'><span>Get TMS Link for JOSM</span></a></div>";

        const oAElem = oBtnTMSDiv.getElementsByTagName("a")[0];

        oAElem.style.cssText = 'background-color: #fc5200;color: #fff;border: 2px solid #da3400;border-radius: 16px;padding: 6px 10px; font-weight: 600;text-decoration: none;height: 36px;align-items: center;display: inline-flex;cursor: pointer;';
        oAElem.onclick = onclick;

        oParentDiv.appendChild(oBtnTMSDiv);

    }

    async function getCookies() {
        console.log("Start Fetching cookies");
        return new Promise((resolve) => GM_cookie.list({ domain: ".strava.com" }, (cookies) => resolve(cookies)));
    }

    async function getTMSlink() {
        //Valid values for heatmap color: hot, blue, purple, gray, bluered, orange
        //Valid values for type of data: all, ride, run (walk, hike), water, winter.

        const oUrlParams = new URLSearchParams(window.location.search);
        const aCookieNames = ["CloudFront-Policy", "CloudFront-Key-Pair-Id", "CloudFront-Signature"];

        let sCookieString = "";
        const aCookies = await getCookies();
        aCookies.forEach((cookie) => {
            if (aCookieNames.includes(cookie.name)) {
                sCookieString += `${cookie.name}=${cookie.value};`;
            }
        });

        if (sCookieString !== ""){
            console.log("Paste URL");

            const urlText = `tms[3,15]:https://heatmap-external-c.strava.com/tiles-auth/${oUrlParams.get('sport').toLowerCase()}/${oUrlParams.get('gColor').toLowerCase()}/{zoom}/{x}/{y}.png{header(cookie,${sCookieString})}`;

            navigator.clipboard.writeText(urlText).then(
                () => {
                    alert("TMS URL copied to clipboard!");
                },
                (oError) => {
                    console.error("Error ", oError);
                }
            );
        } else {
            alert("Cookie is empty, please refresh and try again");
        }

    }

})();