Langage :
WebSocket — Socket.IO
Connexion temps réel via Socket.IO v4 — auth, rooms, heartbeat et gestion de la déconnexion.
Connexion & authentification
Le token JWT est passé dans l'option authlors de la connexion. Le gateway le vérifie, charge le profil de l'utilisateur, et émet READY en retour.
Connexion Socket.IO (utilisateur)
js
import { io } from 'socket.io-client';
const socket = io('https://gateway.alfychat.app', {
auth: { token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' },
reconnection: true,
reconnectionAttempts: 10,
reconnectionDelay: 1000,
});
socket.on('connect', () => console.log('✅ Connecté, id:', socket.id));
socket.on('disconnect', (reason) => console.log('❌', reason));
socket.on('connect_error', (err) => console.error('Auth error:', err.message));
// Premier événement reçu après connexion réussie
socket.on('READY', (data) => {
console.log('userId :', data.user.id);
console.log('sessionId :', data.sessionId);
});Connexion Socket.IO (bot)
js
const socket = io('https://gateway.alfychat.app', {
auth: { token: process.env.BOT_TOKEN, type: 'bot' },
});Événement READY
Reçu immédiatement après la connexion — contient l'état initial de la session.
Payload READY
json
{
"user": { "id": "u1a2b3c4-...", "username": "Alice", "avatarUrl": "..." },
"sessionId": "s9z8y7x6-...",
"servers": [],
"friends": [],
"conversations": []
}Rooms Socket.IO
À la connexion, le gateway auto-rejoint les rooms suivantes :
user:{userId}Room personnelle — notifications directes (DM, demandes d'ami, appels)conversation:{convId}Room d'une conversation DM ou de groupe — auto-jointe pour toutes les convs existantesserver:{serverId}Room d'un serveur — events membres, rôles, channelschannel:{channelId}Room d'un channel textuel — messages du serveurvoice:{channelId}Room vocale — signaling WebRTC entre participantscall:{callId}Room d'un appel — signaling offre/réponse/ICERejoindre une conversation manuellement
js
// Rejoindre une conversation (DM ou groupe)
socket.emit('conversation:join', { conversationId: 'uuid-de-la-conv' });
// ou pour un nouveau DM avec un utilisateur :
socket.emit('conversation:join', { recipientId: 'user-id-du-destinataire' });
// Confirmation
socket.on('conversation:joined', ({ conversationId }) => {
console.log('Rejoint :', conversationId);
});Heartbeat
Maintenir la connexion active (toutes les 30s)
js
// Envoyer le heartbeat
socket.emit('HEARTBEAT');
// Réponse immédiate du serveur
socket.on('HEARTBEAT_ACK', ({ timestamp }) => {
// timestamp = Date.now() côté serveur
});
// Automatiser
const hb = setInterval(() => socket.emit('HEARTBEAT'), 30_000);
socket.on('disconnect', () => clearInterval(hb));Délais de timeout
pingInterval = 25s · pingTimeout = 60s. Sans heartbeat, la connexion est terminée après 60 secondesd'inactivité.Envoyer un message (livraison optimiste)
L'event message:send utilise une livraison optimiste — le message est diffusé immédiatement avant la sauvegarde en base. Un message:failedest émis en cas d'erreur DB.
message:send (DM ou groupe)
js
socket.emit('message:send', {
conversationId: 'uuid-conversation', // ou recipientId pour un DM
recipientId: 'user-id', // optionnel — crée le convId déterministe
content: 'Salut !',
replyToId: 'msg-id', // optionnel
// Chiffrement E2EE (optionnel) :
senderContent: 'contenu chiffré pour le destinataire',
e2eeType: 1,
});
// Confirmation immédiate (avant DB)
socket.on('message:sent', ({ message }) => {
console.log('Envoyé (optimiste) :', message.id);
});
// Disponible pour tous les participants
socket.on('message:new', (message) => {
console.log(message.sender.username, ':', message.content);
});
// En cas d'échec DB
socket.on('message:failed', ({ messageId, error }) => {
console.error('Échec sauvegarde :', messageId, error);
});Rate limiting WebSocket
message:send5 messages / 5 secondesPar utilisateurRéponse en cas de rate limit
json
// event : message:error
{
"error": "RATE_LIMITED",
"message": "Trop de messages envoyés. Calme-toi !"
}Reconnexion & CALL_REJOIN
Gestion de la reconnexion
js
socket.on('disconnect', (reason) => {
console.log('Déconnecté :', reason);
// Socket.IO tente la reconnexion automatique
// Vos rooms sont restaurées automatiquement à la reconnexion
});
socket.on('connect', () => {
// Si vous étiez dans un appel, rejoindre à nouveau la call room
if (currentCallId) {
socket.emit('CALL_REJOIN', { callId: currentCallId });
}
});