// ==UserScript==
// @name The West Rankings CSV Exporter
// @namespace TW-Export-Player-CSV
// @version 1.0
// @description Extract player rankings data (name, level, experience) and export to CSV
// @author Frozah
// @include https://*.the-west.*/game.php*
// @grant none
// ==/UserScript==
(function (fn) {
var script = document.createElement('script');
script.setAttribute('type', 'application/javascript');
script.textContent = '(' + fn + ')();';
document.body.appendChild(script);
document.body.removeChild(script);
})(function () {
RankingExporter = {
version: '1.0',
name: 'Rankings CSV Exporter',
author: 'Assistant',
preferences: {
includeAllPages: true,
maxPages: 16
},
// Données collectées
playersData: [],
currentPage: 1,
totalPages: 16,
isScrapingInProgress: false,
progressBar: null,
// Interface utilisateur
selectBox: null,
// Initialisation du script
init: function() {
this.createSelectBox();
this.addMenuButton();
},
// Création de la boîte de sélection
createSelectBox: function() {
var self = this;
var listener = function(action) {
switch(action) {
case 'export_current':
self.exportCurrentPage();
break;
case 'export_all':
self.exportAllPages();
break;
case 'stop_scraping':
self.stopScraping();
break;
}
};
this.selectBox = new west.gui.Selectbox()
.setWidth(200)
.addListener(listener)
.addItem('export_current', 'Exporter page actuelle')
.addItem('export_all', 'Exporter toutes les pages')
.addItem('stop_scraping', 'Arrêter le scraping');
},
// Ajout du bouton dans le menu
addMenuButton: function() {
var self = this;
// Création d'un bouton simple (carré coloré)
var menuButton = $('<div id="RankingExportermenu" class="menulink" title="' + this.name + '" />')
.css({
'background-color': '#8B4513',
'width': '25px',
'height': '25px',
'cursor': 'pointer',
'border': '2px solid #654321',
'margin': '2px'
})
.on('mouseenter', function() {
$(this).css('background-color', '#A0522D');
})
.on('mouseleave', function() {
$(this).css('background-color', '#8B4513');
})
.click(function() {
self.toggleSelectbox();
});
var div = $('<div class="ui_menucontainer" />')
.append(menuButton)
.append('<div class="menucontainer_bottom" />');
$('#ui_menubar').append(div);
},
// Affichage/masquage de la boîte de sélection
toggleSelectbox: function() {
var pos = $('div#RankingExportermenu').offset();
pos = {
clientX: pos.left,
clientY: pos.top
};
this.selectBox.show(pos);
},
// Extraction des données de la page actuelle
extractCurrentPageData: function() {
var data = [];
var rows = $('.ranking-experience .tbody .tw2gui_scrollpane_clipper_contentpane .row');
rows.each(function(index) {
var row = $(this);
// Extraire le nom du joueur
var playerNameCell = row.find('.exp_playername a');
var playerName = '';
if (playerNameCell.length > 0) {
playerName = playerNameCell.text().trim();
} else {
// Si pas de lien, prendre le texte direct
playerName = row.find('.exp_playername').text().trim();
}
// Extraire le niveau
var level = row.find('.exp_level').text().trim();
// Extraire l'expérience
var experience = row.find('.exp_exp').text().trim();
// Extraire le rang
var rank = row.find('.exp_rank').text().trim();
if (playerName && level && experience && rank) {
data.push({
rank: rank,
name: playerName,
level: level,
experience: experience
});
}
});
return data;
},
// Export de la page actuelle
exportCurrentPage: function() {
var data = this.extractCurrentPageData();
if (data.length === 0) {
new UserMessage('Aucune donnée trouvée sur cette page', UserMessage.TYPE_ERROR).show();
return;
}
this.generateCSV(data, 'rankings_current_page.csv');
new UserMessage('Export de la page actuelle terminé (' + data.length + ' joueurs)', UserMessage.TYPE_SUCCESS).show();
},
// Export de toutes les pages
exportAllPages: function() {
if (this.isScrapingInProgress) {
new UserMessage('Scraping déjà en cours...', UserMessage.TYPE_ERROR).show();
return;
}
this.isScrapingInProgress = true;
this.playersData = [];
this.currentPage = 1;
// Déterminer le nombre total de pages
this.getTotalPages();
new UserMessage('Début du scraping de ' + this.totalPages + ' pages...', UserMessage.TYPE_HINT).show();
// Créer une barre de progression
this.createProgressDialog();
// Commencer le scraping
this.scrapePage(1);
},
// Déterminer le nombre total de pages
getTotalPages: function() {
// Méthode 1: Chercher dans la pagination
var paginationText = $('.rl_pagebar_ranking .maxpages').text();
if (paginationText) {
var match = paginationText.match(/\/\s*(\d+)/);
if (match) {
this.totalPages = parseInt(match[1]);
return;
}
}
// Méthode 2: Compter les liens de pagination
var pageLinks = $('.rl_pagebar_ranking .pagebar_page');
if (pageLinks.length > 0) {
var lastPage = 1;
pageLinks.each(function() {
var pageNum = parseInt($(this).text());
if (!isNaN(pageNum) && pageNum > lastPage) {
lastPage = pageNum;
}
});
this.totalPages = lastPage;
return;
}
// Par défaut, utiliser 16 pages
this.totalPages = 16;
},
// Créer la boîte de dialogue de progression
createProgressDialog: function() {
var self = this;
var content = $('<div><p>Scraping en cours...</p></div>');
this.progressBar = new west.gui.Progressbar(0, this.totalPages);
content.append(this.progressBar.getMainDiv());
this.progressDialog = new west.gui.Dialog("Export en cours", content);
this.progressDialog.addButton("Annuler", function() {
self.stopScraping();
self.progressDialog.hide();
});
this.progressDialog.show();
},
// Scraping d'une page spécifique
scrapePage: function(pageNumber) {
var self = this;
if (!this.isScrapingInProgress || pageNumber > this.totalPages) {
this.finalizeScraping();
return;
}
// Mettre à jour la barre de progression
if (this.progressBar) {
this.progressBar.setValue(pageNumber - 1);
}
new UserMessage('Scraping de la page ' + pageNumber + '/' + this.totalPages + '...', UserMessage.TYPE_HINT).show();
// Aller à la page
this.goToPage(pageNumber, function() {
setTimeout(function() {
// Attendre que la page soit complètement chargée
self.waitForPageLoad(function() {
var pageData = self.extractCurrentPageData();
self.playersData = self.playersData.concat(pageData);
console.log('Page ' + pageNumber + ' scrapée: ' + pageData.length + ' joueurs');
// Passer à la page suivante
setTimeout(function() {
self.scrapePage(pageNumber + 1);
}, 1500); // Délai entre les pages augmenté
});
}, 1000); // Délai initial pour laisser la page se charger
});
},
// Attendre que la page soit chargée
waitForPageLoad: function(callback) {
var self = this;
var attempts = 0;
var maxAttempts = 10;
var checkLoad = function() {
attempts++;
var rows = $('.ranking-experience .tbody .tw2gui_scrollpane_clipper_contentpane .row');
if (rows.length > 0 || attempts >= maxAttempts) {
callback();
} else {
setTimeout(checkLoad, 500);
}
};
checkLoad();
},
// Navigation vers une page spécifique (améliorée)
goToPage: function(pageNumber, callback) {
var self = this;
try {
// Méthode 1: Utiliser le champ de saisie de page
var pageInput = $('.rl_pagebar_ranking .tw2gui_textfield input[type="text"]');
if (pageInput.length > 0) {
pageInput.val(pageNumber);
// Déclencher les événements pour valider la saisie
pageInput.trigger('input');
pageInput.trigger('change');
// Simuler la touche Entrée
var enterEvent = jQuery.Event('keypress');
enterEvent.which = 13; // Code de la touche Entrée
enterEvent.keyCode = 13;
pageInput.trigger(enterEvent);
setTimeout(function() {
if (callback) callback();
}, 800);
return;
}
// Méthode 2: Utiliser Ajax directement (inspirée du second script)
if (typeof Ajax !== 'undefined' && Ajax.remoteCall) {
Ajax.remoteCall("ranking", "get_ranking_page", {
page: pageNumber,
type: "experience"
}, function(response) {
// Attendre que la page soit mise à jour
setTimeout(function() {
if (callback) callback();
}, 500);
});
return;
}
// Méthode 3: Cliquer sur le lien de pagination
var pageLink = $('.rl_pagebar_ranking .pagebar_page').filter(function() {
return $(this).text() == pageNumber;
});
if (pageLink.length > 0) {
pageLink.click();
setTimeout(function() {
if (callback) callback();
}, 800);
return;
}
// Si aucune méthode ne fonctionne, continuer quand même
console.log('Impossible de naviguer vers la page ' + pageNumber);
if (callback) callback();
} catch (e) {
console.error('Erreur lors de la navigation vers la page ' + pageNumber + ':', e);
if (callback) callback();
}
},
// Finalisation du scraping
finalizeScraping: function() {
this.isScrapingInProgress = false;
// Fermer la boîte de dialogue de progression
if (this.progressDialog) {
this.progressDialog.hide();
}
if (this.playersData.length === 0) {
new UserMessage('Aucune donnée collectée', UserMessage.TYPE_ERROR).show();
return;
}
// Tri par rang
this.playersData.sort(function(a, b) {
return parseInt(a.rank) - parseInt(b.rank);
});
// Supprimer les doublons (au cas où)
var uniqueData = [];
var seenRanks = {};
for (var i = 0; i < this.playersData.length; i++) {
var player = this.playersData[i];
if (!seenRanks[player.rank]) {
uniqueData.push(player);
seenRanks[player.rank] = true;
}
}
this.generateCSV(uniqueData, 'rankings_all_pages.csv');
new UserMessage('Export terminé ! ' + uniqueData.length + ' joueurs exportés', UserMessage.TYPE_SUCCESS).show();
},
// Arrêt du scraping
stopScraping: function() {
this.isScrapingInProgress = false;
if (this.progressDialog) {
this.progressDialog.hide();
}
new UserMessage('Scraping arrêté', UserMessage.TYPE_ERROR).show();
},
// Génération du fichier CSV
generateCSV: function(data, filename) {
if (data.length === 0) {
return;
}
// En-têtes CSV
var csv = 'Rang,Nom du joueur,Niveau,Expérience\n';
// Données
data.forEach(function(player) {
// Échapper les guillemets et virgules
var name = '"' + player.name.replace(/"/g, '""') + '"';
var experience = '"' + player.experience.replace(/"/g, '""') + '"';
csv += player.rank + ',' + name + ',' + player.level + ',' + experience + '\n';
});
// Téléchargement du fichier
this.downloadCSV(csv, filename);
},
// Téléchargement du fichier CSV
downloadCSV: function(csvContent, filename) {
var blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
var link = document.createElement('a');
if (link.download !== undefined) {
var url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
}
},
// Vérification si on est sur la page des classements
isOnRankingsPage: function() {
return $('.ranking-experience').length > 0;
}
};
// Initialisation une fois le document prêt
$(document).ready(function() {
try {
// Attendre que les objets du jeu soient disponibles
var initInterval = setInterval(function() {
if (typeof west !== 'undefined' &&
typeof west.gui !== 'undefined' &&
typeof west.gui.Selectbox !== 'undefined' &&
typeof UserMessage !== 'undefined') {
clearInterval(initInterval);
RankingExporter.init();
}
}, 1000);
} catch (e) {
console.log('Erreur lors de l\'initialisation du script Rankings Exporter:', e);
}
});
// Debug : afficher le nom du script dans la console
console.log('Script Rankings CSV Exporter v' + RankingExporter.version + ' chargé');
});