Export guild data to CSV
// ==UserScript==
// @name [MWI] Guild Data Exporter
// @namespace http://tampermonkey.net/
// @version 1.09
// @description Export guild data to CSV
// @author WataFX
// @license MIT
// @icon https://www.google.com/s2/favicons?sz=64&domain=milkywayidle.com
// @match https://www.milkywayidle.com/game?characterId=*
// @grant none
// ==/UserScript==
(function() {
'use strict';
const csvHeader = "type,guild_name,guild_exp,guild_level,export_date,game_mode,player_name,member_exp";
let guildDataRow = "";
let guildCharactersRows = [];
const now = new Date();
const day = String(now.getDate()).padStart(2, '0');
const month = String(now.getMonth() + 1).padStart(2, '0');
const year = String(now.getFullYear()).slice(-2);
const currentDate = `${day}.${month}.${year}`;
function hookWS() {
const dataProperty = Object.getOwnPropertyDescriptor(MessageEvent.prototype, "data");
const originalGetter = dataProperty.get;
dataProperty.get = function hookedGet() {
const socket = this.currentTarget;
if (!(socket instanceof WebSocket)) {
return originalGetter.call(this);
}
if (socket.url.indexOf("api.milkywayidle.com/ws") === -1 &&
socket.url.indexOf("api-test.milkywayidle.com/ws") === -1) {
return originalGetter.call(this);
}
const message = originalGetter.call(this);
Object.defineProperty(this, "data", { value: message });
return handleMessage(message);
};
Object.defineProperty(MessageEvent.prototype, "data", dataProperty);
}
function handleMessage(message) {
try {
const obj = JSON.parse(message);
if (obj && obj.type === "guild_updated") {
const guildExperience = Math.floor(obj.guild.experience);
guildDataRow = [
"guild",
obj.guild.name,
guildExperience,
obj.guild.level,
currentDate,
"", "", ""
].map(cell => `"${String(cell).replace(/"/g, '""')}"`).join(',');
} else if (obj && obj.type === "guild_characters_updated") {
guildCharactersRows = [];
for (const key in obj.guildSharableCharacterMap) {
if (Object.prototype.hasOwnProperty.call(obj.guildSharableCharacterMap, key)) {
const character = obj.guildSharableCharacterMap[key];
const memberExperience = Math.floor(obj.guildCharacterMap[key].guildExperience);
const row = [
"member",
"", // guild_name
"", // guild_experience
"", // level
"", // export_date
character.gameMode,
character.name,
memberExperience
].map(cell => `"${String(cell).replace(/"/g, '""')}"`).join(',');
guildCharactersRows.push(row);
}
}
addExportButton();
}
} catch (error) {
console.error("Error processing message:", error);
}
return message;
}
function downloadCSV() {
const csvContent = [csvHeader].concat(guildDataRow ? [guildDataRow] : [], guildCharactersRows).join('\n');
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
const filename = `guild_data_${currentDate.replace(/\./g, '_')}.csv`;
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = filename;
link.click();
URL.revokeObjectURL(url);
}
function addExportButton() {
if (document.querySelector('.guild_data_export_button')) return;
const exportButton = document.createElement('button');
exportButton.textContent = '📥 Export data to CSV';
exportButton.classList.add('Button_button__1Fe9z', 'guild_data_export_button');
exportButton.addEventListener('click', downloadCSV);
const targetElement = document.querySelector('.GuildPanel_overviewTab__v1IdE');
if (targetElement) {
targetElement.appendChild(exportButton);
} else {
console.error('Target object not found.');
}
}
hookWS();
})();