Skip to content

Instantly share code, notes, and snippets.

@gmoz22
Last active November 5, 2025 16:58
Show Gist options
  • Select an option

  • Save gmoz22/3daa61753f27562dd7af460cb8a12eb6 to your computer and use it in GitHub Desktop.

Select an option

Save gmoz22/3daa61753f27562dd7af460cb8a12eb6 to your computer and use it in GitHub Desktop.
GL.iNet GoodCloud dynamic world map - Tampermonkey
// ==UserScript==
// @name GoodCloud Dynamic Map
// @namespace https://www.steveinnovates.com
// @version 2025-07-24
// @description Displays a dynamic map of your bounded devices
// @author Steve Oziel
// @match https://www.goodcloud.xyz/
// @icon https://www.google.com/s2/favicons?sz=64&domain=goodcloud.xyz
// @grant none
// @downloadURL https://gist.github.com/gmoz22/3daa61753f27562dd7af460cb8a12eb6
// @updateURL https://gist.githubusercontent.com/gmoz22/3daa61753f27562dd7af460cb8a12eb6/raw/tampermonkey-glinet-goodcloud-map.js
// ==/UserScript==
// (function() {
(async () => {
'use strict';
// Inject Leaflet CSS
const leafletCSS = document.createElement('link');
leafletCSS.rel = 'stylesheet';
leafletCSS.href = 'https://unpkg.com/[email protected]/dist/leaflet.css';
leafletCSS.integrity = 'sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=';
leafletCSS.crossOrigin = '';
document.head.appendChild(leafletCSS);
// Inject Leaflet JS
const leafletJS = document.createElement('script');
leafletJS.src = 'https://unpkg.com/[email protected]/dist/leaflet.js';
leafletJS.integrity = 'sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=';
leafletJS.crossOrigin = '';
document.head.appendChild(leafletJS);
const colors = {
online: "#00c8b5",
offline: "#8c8c8c",
unsynced: "#e04c7e",
deactivated: "#f5a623",
blue: "#2196f3",
}
var map;
// Get devices
async function getDevices() {
const token = document.cookie.split("=")[1];
await fetch("https://api.goodcloud.xyz/cloud-api/cloud/v2/device?pageNum=1&pageSize=1000&groupId=&ssid=&mac=&ip=&version=&model=&network_mode=&buttonsh=false&Intermediate=&services=&firmware_path=&data_path=&status=&name_desc=none&modem_version=&name=&description=&version_date=&version_time=&fuzzyKey=&test=&productType=Router&fuzzy_query=", {
"headers": {
"accept": "application/json, text/plain, */*",
"accept-language": "en-US,en;q=0.9,fr;q=0.8",
"cache-control": "no-cache",
"pragma": "no-cache",
"priority": "u=1, i",
"sec-ch-ua": "\"Not)A;Brand\";v=\"8\", \"Chromium\";v=\"138\", \"Google Chrome\";v=\"138\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"macOS\"",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-site",
token
},
"referrer": "https://www.goodcloud.xyz/",
"body": null,
"method": "GET",
"mode": "cors",
"credentials": "omit"
})
.then((response) => {
const reader = response.body.getReader();
return new ReadableStream({
start(controller) {
return pump();
function pump() {
return reader.read().then(({ done, value }) => {
if (done) {
controller.close();
return;
}
controller.enqueue(value);
return pump();
});
}
},
});
})
.then((stream) => new Response(stream))
.then((response) => response.json())
.then((result) => {
for (let x = 0; x < result.info.rows.length; x++) {
let device = result.info.rows[x];
// console.log(device);
L.circleMarker(
[parseInt(device.lat), parseInt(device.lng)],
{
color: (device.status?colors.online:colors.offline),
weight: 5,
opacity: 0.5,
fillOpacity: 0.8
}
)
.addTo(map)
.bindPopup(popupInfo(device));
}
})
}
// Pin info bubble
function popupInfo(device) {
let deviceInfo = "<div>" + (device.status ? "<span title='Online' style='cursor: default; color: "+colors.online+"; font-weight: bold; font-size: 1.3em;'>&#9673;</span>" : "<span title='Offline' style='color: "+colors.offline+"; font-weight: bold;'>Offline</span> ") + " <a style='font-size: 1.3em; font-weight: bold; margin-bottom: 4px;' href='#/share-device/editDevice/"+device.id+"?from=deviceListPage'>" + device.name + "</a></div>"
+ "<br/><div><b>Model</b>: " + device.boardInfoModel + "</div>"
+ "<div><b>MAC</b>: " + device.mac + "</div>"
+ "<div><b>IP</b>: " + device.ip + "</div>"
if (device.position) {
deviceInfo += "<br/><b>Location</b>:<div style='padding-left: 8px;'>" + device.position + "</div>"
}
if (device.description) {
deviceInfo += "<br/><b>Description</b>:<div style='margin-left: 8px;'>" + device.description.split("\n").join("<br/>") + "</div>"
}
return deviceInfo;
}
// Draw Map Leaflet map is loaded and the target div exists
function initMap() {
const targetDiv = document.querySelector('div.map-img');
if (!window.L || !targetDiv) {
setTimeout(initMap, 100);
return;
}
// Remove existing background image, set height and add ID property
targetDiv.style.background = 'none';
targetDiv.style.height = '600px';
targetDiv.id = 'map';
// Initialize Leaflet map
map = L.map('map')
.setView([22, -22], 2)
// .setMaxZoom(5)
// Atrribution
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map);
// Get devices
getDevices();
}
// Display initial map
initMap();
// Display map again when we navigate back to dashboard
window.navigation.addEventListener("navigate", (event) => {
const currentHash = event.destination.url.split("#")[1];
if (currentHash === "/dashboard/index") {
initMap();
}
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment