// ==UserScript==
// @name Grepolis Data Sender (Deep Scan v6.7 β Toolbar Pause Button + Soft Refresh & Full Stats)
// @namespace http://tampermonkey.net/
// @version 6.7
// @description Sends town stats, extracts Premium Exchange title, and soft-refreshes tab every 30s via Marketplace building click. Includes pause/resume button in top toolbar.
// @author Dimitrios
// @match https://*.grepolis.com/game/*
// @grant unsafeWindow
// @updateURL https://git.haunter-pets.top/haunter/grepodata/raw/branch/main/Grepolis_Data_Sender.user.js
// @downloadURL https://git.haunter-pets.top/haunter/grepodata/raw/branch/main/Grepolis_Data_Sender.user.js
// ==/UserScript==
(function () {
'use strict';
console.log("π° DeepScan v6.7 loaded β Soft refresh + Toolbar pause button + full stats");
const uw = typeof unsafeWindow !== "undefined" ? unsafeWindow : window;
let latestBasicPayload = null;
let paused = false;
// π§ Toolbar button HTML
const deepScanButtonHtml =
'
' +
'';
// π§ Toggle pause/resume
function toggleDeepScanButton() {
paused = !paused;
const label = document.getElementById('dslabel');
const btn = document.getElementById('dsbutton');
if (paused) {
label.textContent = 'Paused';
btn.style.filter = 'brightness(70%) sepia(100%) hue-rotate(-50deg) saturate(1000%) contrast(0.8)';
} else {
label.textContent = 'DeepScan';
btn.style.filter = 'brightness(294%) sepia(100%) hue-rotate(15deg) saturate(1000%) contrast(0.8)';
}
console.log(`π DeepScan is now ${paused ? 'paused' : 'running'}`);
}
// π§ Inject button into toolbar
setTimeout(() => {
if (!document.getElementById('dsbutton')) {
uw.$('.tb_activities, .toolbar_activities').find('.middle').append(deepScanButtonHtml);
}
}, 4000);
uw.$(document).on('click', '#dsbutton', toggleDeepScanButton);
// π Extract Premium Exchange title
function getGoldMarketTitle() {
const titleEl = document.querySelector(
".classic_window.market #premium_exchange .game_border_header .title.exchange_title"
);
const titleText = titleEl?.textContent.trim() || "";
console.log("π Gold Market Title:", titleText);
return titleText;
}
// π Extract gold market data
function scrapeGoldMarketExchange() {
const exchange = {};
const resourceTypes = ["wood", "stone", "iron"];
const isSellTabActive =
document.querySelector("#premium_exchange .gp_page_caption.js-page-caption-1.active") &&
document.querySelector("#premium_exchange .gp_tab_page.js-page-1.active");
if (!isSellTabActive) {
console.warn("π« Sell tab not active β skipping gold extraction");
return null;
}
const blocks = document.querySelectorAll(
"#premium_exchange .gp_tab_page.js-page-1.active .resources_wrapper .resource"
);
blocks.forEach((block, i) => {
const type = resourceTypes[i] || `res_${i}`;
const currentEl = block.querySelector(".progressbar_bg .caption span.current");
const maxEl = block.querySelector(".progressbar_bg .caption span.max");
exchange[type] = {
current: currentEl?.textContent.trim() || "0",
max: maxEl?.textContent.trim() || "0"
};
});
console.log("π Gold Market Sell Tab data:", exchange);
return exchange;
}
// π€ Send town + gold data
function sendBasicStats() {
if (paused) {
console.log("βΈοΈ DeepScan is paused β skipping data send");
return;
}
try {
const towns = uw.ITowns?.towns || {};
const player = uw.Game?.player_name || "unknown";
const player_id = uw.Game?.player_id || "unknown";
const stats = Object.values(towns).map(town => {
const res = town.resources();
const buildings = town.buildings()?.attributes ?? {};
const marketLevel = typeof town.getMarketplaceLevel === "function"
? town.getMarketplaceLevel()
: buildings.market || null;
return {
town_id: town.id,
town_name: town.name,
wood: res.wood,
stone: res.stone,
iron: res.iron,
population: res.population,
points: town.getPoints(),
buildings,
market: { level: marketLevel }
};
});
const goldMarket = scrapeGoldMarketExchange();
const goldTitle = getGoldMarketTitle();
latestBasicPayload = {
type: "basic",
timestamp: new Date().toISOString(),
player,
player_id,
towns: stats,
gold_market: goldMarket || {},
gold_market_title: goldTitle || ""
};
console.log("π€ Sending payload:", latestBasicPayload);
fetch("https://grepo.haunter-pets.top/api/grepolis-data", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(latestBasicPayload)
})
.then(res => res.text())
.then(txt => console.log("β
Data sent:", txt))
.catch(err => console.error("β Failed to send:", err));
} catch (e) {
console.error("π₯ Error sending stats:", e);
}
}
// ποΈ Soft refresh: click building and switch tab
function refreshGoldWindow() {
if (paused) {
console.log("βΈοΈ DeepScan is paused β skipping refresh");
return;
}
try {
const marketArea = document.querySelector("area#building_main_area_market");
if (marketArea) {
marketArea.dispatchEvent(new MouseEvent("click", { bubbles: true }));
console.log("ποΈ Clicked Marketplace area to trigger Premium Exchange");
// Wait 1.5s and switch to Sell tab
setTimeout(() => {
const newWin = Array.from(document.querySelectorAll(".classic_window.market"))
.find(win => win.querySelector("#premium_exchange"));
if (newWin) {
const sellTab = newWin.querySelector(".gp_page_caption.js-page-caption-1");
if (sellTab) {
sellTab.click();
console.log("π Switched to Premium Exchange Sell tab");
} else {
console.warn("β οΈ Sell tab not found in window");
}
} else {
console.warn("β Premium Exchange window not found after click");
}
}, 1500);
} else {
console.warn("β Marketplace area not found β cannot trigger Premium Exchange");
}
} catch (err) {
console.error("π₯ Error in refreshGoldWindow:", err);
}
}
// π Main loop
function runDataCycle() {
setInterval(() => {
console.log("π Data cycle tick β soft refresh + send stats");
refreshGoldWindow();
setTimeout(sendBasicStats, 3000);
}, 30000);
}
window.addEventListener("load", () => {
console.log("π DeepScan v6.5 booting up...");
runDataCycle();
});
})();