const { WebSocketServer } = require('ws'); const fs = require('fs'); const path = require('path'); // Les hébergeurs en ligne imposent leur propre PORT via la variable d'environnement process.env.PORT. // Si aucune n'est fournie, il écoutera sur le port 7860. const PORT = process.env.PORT || 7860; // En ligne, on écoute sur '0.0.0.0' pour accepter toutes les connexions entrantes (Internet) const wss = new WebSocketServer({ port: PORT, host: '0.0.0.0' }); // Dossier où stocker les utilisateurs en persistance locale const DOSSIER_USER = path.join(__dirname, 'user'); // Crée le dossier 'user' automatiquement s'il n'existe pas encore if (!fs.existsSync(DOSSIER_USER)) { fs.mkdirSync(DOSSIER_USER); } console.log("=== SERVEUR DE CHAT PRODUCTION EN LIGNE ==="); console.log(`Serveur WebSocket actif sur le port ${PORT}...\n`); wss.on('connection', (ws) => { console.log("[CONNEXION] Un client distant s'est connecté."); ws.on('message', (message) => { const texteRecu = message.toString(); try { const donnees = JSON.parse(texteRecu); // --- CAS 1 : ENREGISTREMENT EN LIGNE --- if (donnees.type === "enregistrement" && donnees.email && donnees.pseudo) { const contenuFichier = `pseudo: ${donnees.pseudo}\nemail: ${donnees.email}`; // Sécurisation du nom de fichier const nomFichier = `${donnees.email.replace(/[^a-zA-Z0-9@.]/g, "_")}.txt`; const cheminFichier = path.join(DOSSIER_USER, nomFichier); // On écrit le fichier sur le disque du serveur en ligne fs.writeFileSync(cheminFichier, contenuFichier, 'utf8'); console.log(`[PROD-USER] Nouvel enregistrement : user/${nomFichier}`); ws.send(JSON.stringify({ type: "reponse_enregistrement", statut: "succes" })); return; } // --- CAS 2 : COMPARAISON / VÉRIFICATION EN LIGNE --- if (donnees.type === "comparer" && donnees.email && donnees.pseudo) { const nomFichier = `${donnees.email.replace(/[^a-zA-Z0-9@.]/g, "_")}.txt`; const cheminFichier = path.join(DOSSIER_USER, nomFichier); if (fs.existsSync(cheminFichier)) { const contenu = fs.readFileSync(cheminFichier, 'utf8'); const contenuAttendu = `pseudo: ${donnees.pseudo}\nemail: ${donnees.email}`; if (contentsMatch(contenu, contenuAttendu)) { console.log(`[PROD-AUTH] Succès pour : ${donnees.email}`); ws.send(JSON.stringify({ type: "reponse_comparer", valide: true, message: "Infos correctes" })); } else { console.log(`[PROD-AUTH] Échec (Pseudo invalide) pour : ${donnees.email}`); ws.send(JSON.stringify({ type: "reponse_comparer", valide: false, message: "Pseudo incorrect" })); } } else { console.log(`[PROD-AUTH] Échec (Inconnu) pour : ${donnees.email}`); ws.send(JSON.stringify({ type: "reponse_comparer", valide: false, message: "Utilisateur inconnu" })); } return; } } catch (e) { // Pas du JSON -> Chat classique } // --- CODE DE CHAT CLASSIQUE --- wss.clients.forEach((client) => { if (client.readyState === 1) { client.send(texteRecu); } }); }); ws.on('close', () => { console.log("[DÉCONNEXION] Un client s'est déconnecté."); }); }); // Fonction utilitaire pour nettoyer et comparer les textes sans être bloqué par des retours à la ligne cachés (\r) function contentsMatch(str1, str2) { return str1.replace(/\r/g, '').trim() === str2.replace(/\r/g, '').trim(); }