// Configuration API
const API_URL = 'http://localhost:4001/api';
// State
let currentUser = null;
let isAuthenticated = false;
// Initialisation
document.addEventListener('DOMContentLoaded', () => {
checkAuth();
});
// Vérifier l'authentification
async function checkAuth() {
try {
const response = await fetch(`${API_URL}/auth/check`, {
credentials: 'include'
});
const data = await response.json();
if (data.authenticated) {
currentUser = data.user;
isAuthenticated = true;
showDashboard();
} else {
showLoginPage();
}
} catch (e) {
console.error('Erreur vérification auth:', e);
showLoginPage();
}
}
// Afficher la page de connexion
function showLoginPage() {
document.getElementById('app').innerHTML = `
`;
// Par défaut, montrer le formulaire de connexion
const regForm = document.getElementById('registerForm');
const loginForm = document.getElementById('loginForm');
if (regForm && loginForm) {
regForm.style.display = 'none';
loginForm.style.display = 'block';
}
}
// Connexion
async function handleLogin() {
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
if (!username || !password) {
showMessage('Veuillez remplir tous les champs', 'error', 'loginMessage');
return;
}
try {
const response = await fetch(`${API_URL}/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ username, password })
});
const data = await response.json();
if (response.ok) {
currentUser = data.user;
isAuthenticated = true;
showDashboard();
} else {
showMessage(data.error || 'Erreur de connexion', 'error', 'loginMessage');
}
} catch (e) {
console.error('Erreur connexion:', e);
showMessage('Erreur serveur', 'error', 'loginMessage');
}
}
// Enregistrement
async function handleRegister() {
const username = document.getElementById('regUsername').value;
const password = document.getElementById('regPassword').value;
const mcUsername = document.getElementById('mcUsername').value;
if (!username || !password || !mcUsername) {
showMessage('Veuillez remplir tous les champs', 'error', 'loginMessage');
return;
}
try {
const response = await fetch(`${API_URL}/auth/register`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ username, password, mcUsername })
});
const data = await response.json();
if (response.ok) {
showMessage('Compte créé! Connectez-vous maintenant.', 'success', 'loginMessage');
setTimeout(() => {
document.getElementById('registerForm').style.display = 'none';
document.getElementById('loginForm').style.display = 'block';
document.getElementById('username').value = username;
document.getElementById('password').value = '';
}, 1000);
} else {
showMessage(data.error || 'Erreur d\'enregistrement', 'error', 'loginMessage');
}
} catch (e) {
console.error('Erreur enregistrement:', e);
showMessage('Erreur serveur', 'error', 'loginMessage');
}
}
// Basculer vers le formulaire de connexion
function toggleToLogin(event) {
event.preventDefault();
const regForm = document.getElementById('registerForm');
const loginForm = document.getElementById('loginForm');
if (regForm && loginForm) {
regForm.style.display = 'none';
loginForm.style.display = 'block';
document.getElementById('loginMessage').innerHTML = '';
// Effacer les champs
document.getElementById('username').value = '';
document.getElementById('password').value = '';
}
}
// Basculer vers le formulaire d'enregistrement
function toggleToRegister(event) {
event.preventDefault();
const regForm = document.getElementById('registerForm');
const loginForm = document.getElementById('loginForm');
if (regForm && loginForm) {
loginForm.style.display = 'none';
regForm.style.display = 'block';
document.getElementById('loginMessage').innerHTML = '';
// Effacer les champs
document.getElementById('regUsername').value = '';
document.getElementById('regPassword').value = '';
document.getElementById('mcUsername').value = '';
}
}
// Afficher le dashboard
function showDashboard() {
document.getElementById('app').innerHTML = `
${getDashboardHTML()}
${getConsoleHTML()}
${getLogsHTML()}
${getPlayersHTML()}
${getWhitelistHTML()}
${getBackupsHTML()}
${getSettingsHTML()}
`;
// Charger les données
loadDashboardData();
}
// Changer d'onglet
function switchTab(tabName) {
// Masquer tous les onglets
document.querySelectorAll('.content-section').forEach(el => {
el.classList.remove('active');
});
// Afficher l'onglet sélectionné
document.getElementById(tabName).classList.add('active');
// Mettre à jour les boutons
document.querySelectorAll('.nav-tabs button').forEach(btn => {
btn.classList.remove('active');
});
event.target.classList.add('active');
// Charger les données spécifiques
if (tabName === 'console') loadConsoleData();
if (tabName === 'logs') loadLogsData();
if (tabName === 'players') loadPlayersData();
if (tabName === 'whitelist') loadWhitelistData();
if (tabName === 'backups') loadBackupsData();
if (tabName === 'settings') loadSettingsData();
}
// ========== DASHBOARD ==========
function getDashboardHTML() {
return `
🎮 Contrôle du Serveur
`;
}
async function loadDashboardData() {
try {
// Charger les joueurs en ligne
await window.loadOnlinePlayers();
const response = await fetch(`${API_URL}/server`, {
credentials: 'include'
});
const data = await response.json();
if (data.properties) {
const table = document.getElementById('quickInfoTable');
table.innerHTML = `
| Nom Serveur | ${data.properties['motd'] || 'NationsGlory'} |
| Mode Jeu | ${data.properties['gamemode'] || 'Survival'} |
| Difficulté | ${data.properties['difficulty'] || '2'} |
| PvP | ${data.properties['pvp'] === 'true' ? 'Activé' : 'Désactivé'} |
| Port | ${data.properties['server-port'] || '25565'} |
| Max Joueurs | ${data.properties['max-players'] || '20'} |
`;
}
// Mettre à jour le nombre de joueurs
const onlineResponse = await fetch(`${API_URL}/rcon/command`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ command: 'list' })
});
if (onlineResponse.ok) {
const rconData = await onlineResponse.json();
const output = rconData.response || '';
const cleanOutput = output.replace(/§[0-9a-fk-or]/gi, '');
const match = cleanOutput.match(/There are (\d+) out of maximum (\d+) players online/i);
if (match) {
const onlineCount = parseInt(match[1]);
const maxPlayers = parseInt(match[2]);
document.getElementById('playerCount').textContent = `${onlineCount}/${maxPlayers}`;
}
}
} catch (e) {
console.error('Erreur chargement dashboard:', e);
}
}
// ========== CONSOLE RCON ==========
function getConsoleHTML() {
return `
⌨️ Console RCON
Exécutez des commandes directement sur le serveur
�️ Actions Rapides
📜 Historique des Commandes
💬 Envoyer un Message
⏹️ Arrêter le Serveur
⚠️ Un message d'avertissement sera envoyé tous les 10 secondes
🔄 Redémarrer le Serveur
ℹ️ Un message d'avertissement sera envoyé tous les 10 secondes
`;
}
async function loadConsoleData() {
try {
const search = document.getElementById('historySearch')?.value || '';
const url = new URL(`${API_URL}/rcon/history`);
url.searchParams.set('limit', '50');
if (search) url.searchParams.set('search', search);
const response = await fetch(url, {
credentials: 'include'
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
const container = document.getElementById('historyContainer');
if (data.history && data.history.length > 0) {
container.innerHTML = data.history.map(h => {
const timestamp = new Date(h.timestamp).toLocaleString('fr-FR');
const statusIcon = h.success ? '✓' : '✗';
const statusColor = h.success ? '#28a745' : '#dc3545';
return `
${h.command}
${timestamp}
${statusIcon}
${h.response ? `
${h.response}
` : ''}
${h.error ? `
Erreur: ${h.error}
` : ''}
`;
}).join('');
} else {
container.innerHTML = 'Aucun historique
';
}
} catch (e) {
console.error('Erreur historique:', e);
const container = document.getElementById('historyContainer');
container.innerHTML = `Erreur lors du chargement: ${e.message}
`;
}
}
async function clearRconHistory() {
if (!confirm('Êtes-vous sûr de vouloir supprimer tout l\'historique?')) return;
try {
const response = await fetch(`${API_URL}/rcon/history`, {
method: 'DELETE',
credentials: 'include'
});
if (response.ok) {
showMessage('Historique supprimé', 'success', 'dashboardMessage');
loadConsoleData();
} else {
showMessage('Erreur lors de la suppression', 'error', 'dashboardMessage');
}
} catch (e) {
console.error('Erreur suppression historique:', e);
showMessage('Erreur serveur', 'error', 'dashboardMessage');
}
}
async function sendRconCommand() {
const commandInput = document.getElementById('commandInput');
const command = commandInput.value.trim();
if (!command) return;
const output = document.getElementById('consoleOutput');
output.textContent += `admin@nationsglory:~$ ${command}\n`;
commandInput.value = '';
try {
const response = await fetch(`${API_URL}/rcon/command`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ command })
});
const data = await response.json();
if (response.ok) {
const responseText = data.response || '(pas de réponse)';
output.textContent += `${responseText}\n`;
showMessage('Commande exécutée ✓', 'success', 'dashboardMessage');
loadConsoleData(); // Rafraîchir l'historique
} else {
output.textContent += `Erreur: ${data.error}\n`;
showMessage(data.error, 'error', 'dashboardMessage');
}
output.scrollTop = output.scrollHeight;
} catch (e) {
console.error('Erreur envoi commande:', e);
output.textContent += `Erreur serveur: ${e.message}\n`;
showMessage('Erreur serveur', 'error', 'dashboardMessage');
output.scrollTop = output.scrollHeight;
}
}
// Variables globales pour gérer l'arrêt du serveur
let shutdownInProgress = false;
let shutdownCancelToken = null;
window.openSayModal = function() {
document.getElementById('sayModal').style.display = 'flex';
};
window.sendSayCommand = async function() {
const message = document.getElementById('sayInput').value.trim();
if (!message) {
alert('Entrez un message');
return;
}
try {
const response = await fetch(`${API_URL}/rcon/command`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ command: `say ${message}` })
});
if (response.ok) {
showMessage('Message envoyé ✓', 'success', 'dashboardMessage');
document.getElementById('sayInput').value = '';
document.getElementById('sayModal').style.display = 'none';
loadConsoleData();
} else {
showMessage('Erreur lors de l\'envoi du message', 'error', 'dashboardMessage');
}
} catch (e) {
console.error('Erreur envoi message:', e);
showMessage('Erreur serveur', 'error', 'dashboardMessage');
}
};
window.openShutdownModal = function() {
document.getElementById('shutdownModal').style.display = 'flex';
};
window.shutdownServer = async function() {
const cooldown = parseInt(document.getElementById('shutdownCooldown').value);
const message = document.getElementById('shutdownMessage').value.trim();
if (cooldown < 10 || cooldown > 600) {
alert('Le cooldown doit être entre 10 et 600 secondes');
return;
}
if (!message) {
alert('Entrez un message d\'avertissement');
return;
}
if (!confirm(`Êtes-vous sûr de vouloir arrêter le serveur dans ${cooldown} secondes?`)) {
return;
}
try {
shutdownInProgress = true;
shutdownCancelToken = {};
document.getElementById('cancelShutdownBtn').style.display = 'block';
document.getElementById('shutdownModal').style.display = 'none';
showMessage(`⏳ Arrêt du serveur dans ${cooldown} secondes...`, 'warning', 'dashboardMessage');
let secondsRemaining = cooldown;
while (secondsRemaining > 0 && shutdownInProgress && shutdownCancelToken) {
if (secondsRemaining % 10 === 0 || secondsRemaining <= 10) {
// Envoyer un avertissement tous les 10 secondes (ou chaque seconde dans les 10 dernières)
const warningMsg = message.replace('{cooldown}', secondsRemaining);
await fetch(`${API_URL}/rcon/command`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ command: `say ${warningMsg}` })
}).catch(() => {});
}
await new Promise(resolve => setTimeout(resolve, 1000));
secondsRemaining--;
}
if (!shutdownInProgress || !shutdownCancelToken) {
// Envoyer un message dans le chat pour informer de l'annulation
await fetch(`${API_URL}/rcon/command`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ command: 'say Arrêt du serveur annulé!' })
}).catch(() => {});
showMessage('❌ Arrêt annulé', 'warning', 'dashboardMessage');
document.getElementById('cancelShutdownBtn').style.display = 'none';
document.getElementById('cancelShutdownBtnDash').style.display = 'none';
return;
}
// Envoyer la commande d'arrêt
const response = await fetch(`${API_URL}/rcon/command`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ command: 'stop' })
});
if (response.ok) {
showMessage('✓ Serveur arrêté', 'success', 'dashboardMessage');
} else {
showMessage('Erreur lors de l\'arrêt du serveur', 'error', 'dashboardMessage');
}
shutdownInProgress = false;
shutdownCancelToken = null;
document.getElementById('cancelShutdownBtn').style.display = 'none';
document.getElementById('cancelShutdownBtnDash').style.display = 'none';
loadConsoleData();
} catch (e) {
console.error('Erreur arrêt serveur:', e);
showMessage('Erreur serveur', 'error', 'dashboardMessage');
shutdownInProgress = false;
shutdownCancelToken = null;
document.getElementById('cancelShutdownBtn').style.display = 'none';
}
};
window.cancelShutdown = function() {
if (shutdownInProgress) {
shutdownInProgress = false;
shutdownCancelToken = null;
document.getElementById('cancelShutdownBtn').style.display = 'none';
document.getElementById('cancelShutdownBtnDash').style.display = 'none';
showMessage('❌ Arrêt annulé', 'warning', 'dashboardMessage');
}
};
// Variables globales pour gérer le redémarrage du serveur
let restartInProgress = false;
let restartCancelToken = null;
window.openRestartModal = function() {
document.getElementById('restartModal').style.display = 'flex';
};
window.restartServer = async function() {
const cooldown = parseInt(document.getElementById('restartCooldown').value);
const message = document.getElementById('restartMessage').value.trim();
if (cooldown < 10 || cooldown > 600) {
alert('Le cooldown doit être entre 10 et 600 secondes');
return;
}
if (!message) {
alert('Entrez un message d\'avertissement');
return;
}
if (!confirm(`Êtes-vous sûr de vouloir redémarrer le serveur dans ${cooldown} secondes?`)) {
return;
}
try {
restartInProgress = true;
restartCancelToken = {};
document.getElementById('cancelRestartBtn').style.display = 'block';
document.getElementById('restartModal').style.display = 'none';
showMessage(`⏳ Redémarrage du serveur dans ${cooldown} secondes...`, 'warning', 'dashboardMessage');
let secondsRemaining = cooldown;
while (secondsRemaining > 0 && restartInProgress && restartCancelToken) {
if (secondsRemaining % 10 === 0 || secondsRemaining <= 10) {
// Envoyer un avertissement tous les 10 secondes (ou chaque seconde dans les 10 dernières)
const warningMsg = message.replace('{cooldown}', secondsRemaining);
await fetch(`${API_URL}/rcon/command`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ command: `say ${warningMsg}` })
}).catch(() => {});
}
await new Promise(resolve => setTimeout(resolve, 1000));
secondsRemaining--;
}
if (!restartInProgress || !restartCancelToken) {
// Envoyer un message dans le chat pour informer de l'annulation
await fetch(`${API_URL}/rcon/command`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ command: 'say Redémarrage du serveur annulé!' })
}).catch(() => {});
showMessage('❌ Redémarrage annulé', 'warning', 'dashboardMessage');
document.getElementById('cancelRestartBtn').style.display = 'none';
return;
}
// Envoyer la commande de redémarrage
const response = await fetch(`${API_URL}/rcon/command`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ command: 'stop' })
});
if (response.ok) {
showMessage('✓ Serveur redémarré', 'success', 'dashboardMessage');
} else {
showMessage('Erreur lors du redémarrage du serveur', 'error', 'dashboardMessage');
}
restartInProgress = false;
restartCancelToken = null;
document.getElementById('cancelRestartBtn').style.display = 'none';
loadDashboardData();
} catch (e) {
console.error('Erreur redémarrage serveur:', e);
showMessage('Erreur serveur', 'error', 'dashboardMessage');
restartInProgress = false;
restartCancelToken = null;
document.getElementById('cancelRestartBtn').style.display = 'none';
}
};
window.cancelRestart = function() {
if (restartInProgress) {
restartInProgress = false;
restartCancelToken = null;
document.getElementById('cancelRestartBtn').style.display = 'none';
showMessage('❌ Redémarrage annulé', 'warning', 'dashboardMessage');
}
};
// ========== LOGS ==========
function getLogsHTML() {
return `
📜 Logs
`;
}
async function loadLogsData() {
try {
const response = await fetch(`${API_URL}/logs?lines=200`, {
credentials: 'include'
});
const data = await response.json();
const container = document.getElementById('logsContainer');
container.innerHTML = data.logs.map((line, idx) => {
let className = '';
if (line.includes('ERROR')) className = 'error';
else if (line.includes('WARN')) className = 'warning';
return `${escapeHtml(line)}
`;
}).join('');
container.scrollTop = container.scrollHeight;
} catch (e) {
console.error('Erreur chargement logs:', e);
document.getElementById('logsContainer').innerHTML = 'Erreur chargement
';
}
}
async function reloadLogs() {
showMessage('Rechargement...', 'success', 'dashboardMessage');
await loadLogsData();
showMessage('Logs rechargés', 'success', 'dashboardMessage');
}
function openSearchLogsModal() {
const query = prompt('Chercher dans les logs:');
if (query) searchLogs(query);
}
async function searchLogs(query) {
try {
const response = await fetch(`${API_URL}/logs/search?query=${encodeURIComponent(query)}`, {
credentials: 'include'
});
const data = await response.json();
const container = document.getElementById('logsContainer');
container.innerHTML = data.results.map((r, idx) => `
[${r.index}] ${escapeHtml(r.line)}
`).join('');
} catch (e) {
console.error('Erreur recherche:', e);
}
}
// ========== JOUEURS ==========
function getPlayersHTML() {
return `
👥 Joueurs en Ligne
📋 Tous les Joueurs
Liste des joueurs qui se sont connectés au serveur
| Nom |
UUID |
Dernière Connexion |
| Chargement... |
`;
}
async function loadPlayersData() {
// Charger les joueurs en ligne
await window.loadOnlinePlayers();
// Charger tous les joueurs
try {
const response = await fetch(`${API_URL}/players`, {
credentials: 'include'
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
const table = document.getElementById('playersTable');
if (data.players && data.players.length > 0) {
table.innerHTML = data.players.map(p => `
| ${p.name} |
${p.uuid} |
${new Date(p.lastPlayed).toLocaleString()} |
`).join('');
} else {
table.innerHTML = '| Aucun joueur |
';
}
} catch (e) {
console.error('Erreur joueurs:', e);
document.getElementById('playersTable').innerHTML = `| Erreur: ${e.message} |
`;
}
}
window.loadOnlinePlayers = async function() {
console.log('Chargement des joueurs en ligne...');
const infoDiv = document.getElementById('onlinePlayersInfo');
const listDiv = document.getElementById('onlinePlayersList');
if (!infoDiv || !listDiv) {
console.error('Éléments DOM non trouvés');
return;
}
try {
infoDiv.innerHTML = '⏳ Chargement...
';
const response = await fetch(`${API_URL}/rcon/command`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
credentials: 'include',
body: JSON.stringify({ command: 'list' })
});
console.log('Réponse RCON reçue:', response.status);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
const output = data.response || data.output || '';
console.log('Données reçues:', data);
console.log('Output RCON:', output);
// Supprimer les codes de couleur Minecraft (§X)
const cleanOutput = output.replace(/§[0-9a-fk-or]/gi, '');
console.log('Output nettoyé:', cleanOutput);
// Parser différents formats possibles:
// Format moderne: "There are 1/20 players online: player1, player2"
// Format 1.6.4: "There are 1 out of maximum 20 players online. Connected players: player1"
let match = cleanOutput.match(/There are (\d+)\/(\d+) players online:?\s*(.*)/i);
if (!match) {
// Essayer le format 1.6.4
match = cleanOutput.match(/There are (\d+) out of maximum (\d+) players online/i);
if (match) {
const onlineCount = parseInt(match[1]);
const maxPlayers = parseInt(match[2]);
// Chercher les noms de joueurs après "Connected players:"
const playersMatch = cleanOutput.match(/Connected players[:\s]+(.+)/i);
const playerNames = playersMatch ?
playersMatch[1].split(',').map(n => n.trim().replace(/\[AFK\]/gi, '').trim()).filter(n => n) :
[];
match = [cleanOutput, onlineCount.toString(), maxPlayers.toString(), playerNames.join(', ')];
}
}
if (match) {
const onlineCount = parseInt(match[1]);
const maxPlayers = parseInt(match[2]);
const playerNames = match[3] ? match[3].split(',').map(n => n.trim()).filter(n => n) : [];
console.log(`Joueurs: ${onlineCount}/${maxPlayers}`, playerNames);
infoDiv.innerHTML = `
${onlineCount} joueur${onlineCount !== 1 ? 's' : ''}
en ligne sur ${maxPlayers}
${onlineCount > 0 ? '🟢' : '⚪'}
`;
if (onlineCount > 0 && playerNames.length > 0) {
listDiv.innerHTML = `
${playerNames.map(name => `
🎮 ${name}
`).join('')}
`;
} else {
listDiv.innerHTML = '';
}
} else {
infoDiv.innerHTML = `Aucun joueur en ligne
`;
listDiv.innerHTML = '';
}
} catch (e) {
console.error('Erreur chargement joueurs en ligne:', e);
infoDiv.innerHTML = `
Erreur: ${e.message}
`;
listDiv.innerHTML = '';
}
}
// ========== WHITELIST ==========
function getWhitelistHTML() {
return `
✅ Whitelist
| Joueur |
Actions |
| Chargement... |
`;
}
async function loadWhitelistData() {
try {
const response = await fetch(`${API_URL}/whitelist`, {
credentials: 'include'
});
const data = await response.json();
const table = document.getElementById('whitelistTable');
if (data.whitelist && data.whitelist.length > 0) {
const players = data.whitelist.map(w => typeof w === 'string' ? w : w.name);
table.innerHTML = players.map(p => `
| ${p} |
|
`).join('');
} else {
table.innerHTML = '| Whitelist vide |
';
}
} catch (e) {
console.error('Erreur whitelist:', e);
document.getElementById('whitelistTable').innerHTML = '| Erreur |
';
}
}
function openAddWhitelistModal() {
const username = prompt('Nom du joueur à ajouter:');
if (username) addToWhitelist(username);
}
async function addToWhitelist(username) {
try {
const response = await fetch(`${API_URL}/whitelist/add`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ username })
});
const data = await response.json();
if (response.ok) {
showMessage(`${username} ajouté à la whitelist`, 'success', 'dashboardMessage');
loadWhitelistData();
} else {
showMessage(data.error, 'error', 'dashboardMessage');
}
} catch (e) {
console.error('Erreur:', e);
showMessage('Erreur serveur', 'error', 'dashboardMessage');
}
}
async function removeFromWhitelist(username) {
if (!confirm(`Confirmer la suppression de ${username}?`)) return;
try {
const response = await fetch(`${API_URL}/whitelist/remove`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ username })
});
const data = await response.json();
if (response.ok) {
showMessage(`${username} retiré de la whitelist`, 'success', 'dashboardMessage');
loadWhitelistData();
} else {
showMessage(data.error, 'error', 'dashboardMessage');
}
} catch (e) {
console.error('Erreur:', e);
showMessage('Erreur serveur', 'error', 'dashboardMessage');
}
}
async function reloadWhitelist() {
showMessage('Rechargement...', 'success', 'dashboardMessage');
await loadWhitelistData();
showMessage('Whitelist rechargée', 'success', 'dashboardMessage');
}
// ========== BACKUPS ==========
function getBackupsHTML() {
return `
💾 Backups
| Nom |
Taille |
Date |
Actions |
| Chargement... |
`;
}
async function loadBackupsData() {
try {
const response = await fetch(`${API_URL}/backup`, {
credentials: 'include'
});
const data = await response.json();
const table = document.getElementById('backupsTable');
if (Array.isArray(data) && data.length > 0) {
table.innerHTML = data.map(b => `
| ${b.name} |
${b.size} |
${new Date(b.created).toLocaleString()} |
|
`).join('');
} else {
table.innerHTML = '| Aucun backup |
';
}
} catch (e) {
console.error('Erreur backups:', e);
document.getElementById('backupsTable').innerHTML = '| Erreur |
';
}
}
async function createBackup() {
if (!confirm('Créer un nouveau backup? (cela peut prendre du temps)')) return;
showMessage('Création du backup en cours...', 'success', 'dashboardMessage');
try {
const response = await fetch(`${API_URL}/backup/create`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({})
});
const data = await response.json();
if (response.ok) {
showMessage(data.message, 'success', 'dashboardMessage');
setTimeout(() => loadBackupsData(), 2000);
} else {
showMessage(data.error, 'error', 'dashboardMessage');
}
} catch (e) {
console.error('Erreur:', e);
showMessage('Erreur serveur', 'error', 'dashboardMessage');
}
}
async function deleteBackup(filename) {
if (!confirm(`Confirmer la suppression du backup ${filename}?`)) return;
try {
const response = await fetch(`${API_URL}/backup/delete/${filename}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({})
});
const data = await response.json();
if (response.ok) {
showMessage('Backup supprimé', 'success', 'dashboardMessage');
loadBackupsData();
} else {
showMessage(data.error, 'error', 'dashboardMessage');
}
} catch (e) {
console.error('Erreur:', e);
showMessage('Erreur serveur', 'error', 'dashboardMessage');
}
}
async function reloadBackups() {
showMessage('Rechargement...', 'success', 'dashboardMessage');
await loadBackupsData();
showMessage('Backups rechargés', 'success', 'dashboardMessage');
}
// ========== PARAMÈTRES ==========
function getSettingsHTML() {
return `
⚙️ Paramètres du Serveur
Modifiez les paramètres du serveur en temps réel
| Paramètre |
Valeur |
| Chargement... |
`;
}
async function loadSettingsData() {
try {
const response = await fetch(`${API_URL}/server`, {
credentials: 'include'
});
const data = await response.json();
const table = document.getElementById('settingsTable');
const tbody = table.querySelector('tbody');
if (data.properties) {
const keys = Object.keys(data.properties).sort();
tbody.innerHTML = keys.map(k => {
const isPassword = k.toLowerCase().includes('password') || k.toLowerCase().includes('rcon');
const inputType = isPassword ? 'password' : 'text';
const value = data.properties[k];
return `
| ${k} |
|
`;
}).join('');
}
} catch (e) {
console.error('Erreur paramètres:', e);
}
}
async function updateSetting(input) {
const key = input.getAttribute('data-key');
const newValue = input.value;
try {
const response = await fetch(`${API_URL}/server/settings`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ key, value: newValue })
});
if (response.ok) {
showMessage(`✓ Paramètre ${key} modifié`, 'success', 'dashboardMessage');
} else {
const error = await response.json();
showMessage(`Erreur: ${error.error}`, 'error', 'dashboardMessage');
await loadSettingsData(); // Recharger pour annuler la modification
}
} catch (e) {
console.error('Erreur modification paramètre:', e);
showMessage('Erreur serveur', 'error', 'dashboardMessage');
}
}
// ========== ACTIONS ==========
async function restartServer() {
if (!confirm('⚠️ Redémarrer le serveur? Les joueurs seront déconnectés.')) return;
showMessage('Redémarrage du serveur...', 'success', 'dashboardMessage');
try {
const response = await fetch(`${API_URL}/rcon/restart`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({})
});
const data = await response.json();
if (response.ok) {
showMessage(data.message, 'success', 'dashboardMessage');
} else {
showMessage(data.error, 'error', 'dashboardMessage');
}
} catch (e) {
console.error('Erreur:', e);
showMessage('Erreur serveur', 'error', 'dashboardMessage');
}
}
async function saveServer() {
showMessage('Sauvegarde du serveur...', 'success', 'dashboardMessage');
try {
const response = await fetch(`${API_URL}/rcon/save`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({})
});
const data = await response.json();
if (response.ok) {
showMessage(data.message, 'success', 'dashboardMessage');
} else {
showMessage(data.error, 'error', 'dashboardMessage');
}
} catch (e) {
console.error('Erreur:', e);
showMessage('Erreur serveur', 'error', 'dashboardMessage');
}
}
function openChangeRconPasswordModal() {
const oldPassword = prompt('Ancien mot de passe RCON:');
if (!oldPassword) return;
const newPassword = prompt('Nouveau mot de passe RCON:');
if (!newPassword) return;
changeRconPassword(oldPassword, newPassword);
}
async function changeRconPassword(oldPassword, newPassword) {
try {
const response = await fetch(`${API_URL}/auth/change-rcon-password`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ oldPassword, newPassword })
});
const data = await response.json();
if (response.ok) {
showMessage(data.message, 'success', 'dashboardMessage');
} else {
showMessage(data.error, 'error', 'dashboardMessage');
}
} catch (e) {
console.error('Erreur:', e);
showMessage('Erreur serveur', 'error', 'dashboardMessage');
}
}
// ========== UTILITAIRES ==========
function showMessage(text, type, elementId) {
const element = document.getElementById(elementId);
if (element) {
element.textContent = text;
element.className = `message show ${type}`;
setTimeout(() => {
element.classList.remove('show');
}, 4000);
}
}
function escapeHtml(text) {
const map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return text.replace(/[&<>"']/g, m => map[m]);
}
// Déconnexion
async function handleLogout() {
try {
await fetch(`${API_URL}/auth/logout`, {
method: 'POST',
credentials: 'include'
});
checkAuth();
} catch (e) {
console.error('Erreur:', e);
}
}