AlfyChat
Langage :

WebSocket — Socket.IO

Connexion temps réel via Socket.IO v4 — auth, rooms, heartbeat et gestion de la déconnexion.

URL WebSocket

wss://gateway.alfychat.app

Librairie

Socket.IO v4

Namespace bots

/

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 existantes
server:{serverId}Room d'un serveur — events membres, rôles, channels
channel:{channelId}Room d'un channel textuel — messages du serveur
voice:{channelId}Room vocale — signaling WebRTC entre participants
call:{callId}Room d'un appel — signaling offre/réponse/ICE
Rejoindre 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 utilisateur
Ré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 });
  }
});