AlfyChat
Langage :

Référence des événements Socket.IO

80+

Tous les events client → serveur et serveur → client — payload exact, callback, et exemples de code.

Écouter les événements — exemple complet
js
import { io } from 'socket.io-client';

const socket = io('https://gateway.alfychat.app', {
  auth: { token: sessionStorage.getItem('token') },
});

socket.on('READY', ({ userId, guilds }) => {
  console.log('Connecté', userId, '—', guilds.length, 'serveur(s)');
});

socket.on('MESSAGE_CREATE', (msg) => {
  console.log(`[${msg.channelId}] ${msg.author.username}: ${msg.content}`);
});

socket.on('MESSAGE_UPDATE', (msg) => {
  console.log('Édité :', msg.id, '→', msg.content);
});

socket.on('MESSAGE_DELETE', ({ id, channelId }) => {
  console.log('Supprimé :', id, 'dans', channelId);
});

socket.on('PRESENCE_UPDATE', ({ userId, status }) => {
  console.log(`${userId} est maintenant ${status}`);
});

socket.on('FRIEND_REQUEST', ({ from }) => {
  console.log('Demande d\'ami de', from.username);
});

// Maintenir la connexion active
setInterval(() => socket.emit('HEARTBEAT'), 30_000);

Événements émis par le client (client → serveur)

Connexion & session

HEARTBEAT
—↩ HEARTBEAT_ACK → { timestamp }Maintenir la connexion active (toutes les 30s)
PRESENCE_UPDATE
{ status, customStatus? }"online" | "idle" | "dnd" | "invisible"
PROFILE_UPDATE
{ username?, displayName?, avatarUrl?, bio? }Met à jour le profil et notifie les amis/serveurs
GET_BULK_PRESENCE
{ userIds: string[] }↩ { presences: Record<userId, PresenceState> }Récupérer la présence de plusieurs utilisateurs

Messages directs & conversations

conversation:join
{ conversationId?, recipientId? }↩ conversation:joined → { conversationId }Rejoindre une conversation DM (crée le convId déterministe si besoin)
message:send
{ conversationId, recipientId?, content, replyToId?, senderContent?, e2eeType? }↩ message:sent → { message }Envoyer un message DM (livraison optimiste)
message:edit
{ messageId, content }Modifier un message
message:delete
{ messageId, conversationId? }Supprimer un message
TYPING_START
{ conversationId }Afficher l'indicateur "en train d'écrire"
TYPING_STOP
{ conversationId }Masquer l'indicateur de frappe
REACTION_ADD
{ messageId, conversationId, emoji }Ajouter une réaction à un DM
REACTION_REMOVE
{ messageId, conversationId, emoji }Retirer une réaction d'un DM

Archive DM (P2P)

DM_ARCHIVE_REQUEST
{ conversationId, before, limit }Demander des messages archivés à l'autre pair en ligne
DM_ARCHIVE_PEER_RESPONSE
{ conversationId, messages[], archiveLogId }Répondre à une demande d'archive d'un pair
DM_ARCHIVE_CONFIRM
{ conversationId, archiveLogId }Confirmer la réception d'une archive
DM_ARCHIVE_STATUS
{ conversationId }↩ { status: ArchiveStatus }Demander le statut d'archive d'une conversation

Amis

FRIEND_REQUEST
{ toUserId, message? }Envoyer une demande d'ami
FRIEND_ACCEPT
{ requestId }Accepter une demande d'ami

Appels (WebRTC)

CALL_INITIATE
{ type, recipientId?, conversationId?, channelId? }↩ (callId: string)"audio" | "video" | "channel" — callback avec l'ID d'appel
CALL_ACCEPT
{ callId }Accepter un appel entrant
CALL_REJECT
{ callId }Refuser un appel entrant
CALL_END
{ callId }Terminer un appel en cours
CALL_REJOIN
{ callId }Rejoindre un appel après reconnexion WebSocket
WEBRTC_OFFER
{ callId, offer: RTCSessionDescription }Signaling — envoyer l'offer SDP
WEBRTC_ANSWER
{ callId, answer: RTCSessionDescription }Signaling — répondre à une offer SDP
WEBRTC_ICE_CANDIDATE
{ callId, candidate: RTCIceCandidate }Signaling — partager un candidat ICE

Canaux vocaux (serveurs)

VOICE_JOIN
{ serverId, channelId }Rejoindre un canal vocal
VOICE_LEAVE
{ serverId, channelId }Quitter un canal vocal
VOICE_STATE_UPDATE
{ channelId, muted, deafened }Mettre à jour son état micro/casque
VOICE_OFFER
{ channelId, targetUserId, offer }Signaling vocal — offer vers un participant
VOICE_ANSWER
{ channelId, targetUserId, answer }Signaling vocal — answer vers un participant
VOICE_ICE_CANDIDATE
{ channelId, targetUserId, candidate }Signaling vocal — candidat ICE
GET_VOICE_STATE
{ serverId }↩ { voiceStates: VoiceState[] }Récupérer les états vocaux d'un serveur

Messages de serveur

SERVER_MESSAGE_SEND
{ serverId, channelId, content, replyToId? }Envoyer un message dans un salon de serveur
SERVER_MESSAGE_EDIT
{ serverId, channelId, messageId, content }Modifier un message de serveur
SERVER_MESSAGE_DELETE
{ serverId, channelId, messageId }Supprimer un message de serveur
SERVER_MESSAGE_HISTORY
{ serverId, channelId, before?, limit? }↩ { messages[] }Récupérer l'historique (100 max, paginer avec before)
SERVER_REACTION_ADD
{ serverId, channelId, messageId, emoji }Ajouter une réaction dans un serveur
SERVER_REACTION_REMOVE
{ serverId, channelId, messageId, emoji }Retirer une réaction dans un serveur
SERVER_TYPING_START
{ serverId, channelId }Afficher l'indicateur de frappe dans un salon
SERVER_TYPING_STOP
{ serverId, channelId }Masquer l'indicateur de frappe

Gestion des serveurs & membres

SERVER_JOIN
{ serverId }Rejoindre un serveur existant (room auto-join)
SERVER_LEAVE
{ serverId }Quitter un serveur
SERVER_INFO
{ serverId }↩ { server: ServerDetails }Récupérer les infos complètes d'un serveur
SERVER_GET_CHANNELS
{ serverId }↩ { channels[] }Lister les canaux d'un serveur
MEMBER_LIST
{ serverId }↩ { members[] }Lister les membres d'un serveur
MEMBER_UPDATE
{ serverId, targetUserId, roleIds[], nickname? }↩ { member }Modifier le rôle ou le pseudo d'un membre
MEMBER_KICK
{ serverId, targetUserId, reason? }Exclure un membre (permission requis)
MEMBER_BAN
{ serverId, targetUserId, reason? }Bannir un membre

Canaux

CHANNEL_CREATE
{ serverId, name, type }Créer un canal dans un serveur
CHANNEL_UPDATE
{ serverId, channelId, name?, position? }Modifier un canal
CHANNEL_DELETE
{ serverId, channelId }Supprimer un canal

Rôles

ROLE_LIST
{ serverId }↩ { roles[] }Lister les rôles d'un serveur
ROLE_CREATE
{ serverId, name, color?, permissions? }Créer un rôle
ROLE_UPDATE
{ serverId, roleId, name?, color?, permissions? }Modifier un rôle
ROLE_DELETE
{ serverId, roleId }Supprimer un rôle

Invitations

INVITE_LIST
{ serverId }↩ { invites[] }Lister les invitations actives
INVITE_CREATE
{ serverId, maxUses?, expiresIn? }↩ { invite }Créer un lien d'invitation
INVITE_DELETE
{ serverId, code }Révoquer une invitation
INVITE_VERIFY
{ code }↩ { valid, server? }Vérifier un code d'invitation

Groupes (DM multi)

GROUP_CREATE
{ name, memberIds[] }↩ { group }Créer un groupe
GROUP_UPDATE
{ groupId, name?, avatarUrl? }Modifier un groupe
GROUP_LEAVE
{ groupId }Quitter un groupe
GROUP_DELETE
{ groupId }Supprimer un groupe (propriétaire uniquement)

Événements reçus (serveur → client)

Connexion & session

READY
{ user, sessionId, servers[], friends[], conversations[] }État initial de la session, émis juste après la connexion
HEARTBEAT_ACK
{ timestamp }Accusé de réception du heartbeat
PENDING_PINGS
{ pings: Notification[] }Notifications manquées reçues lors de la reconnexion
PRESENCE_UPDATE
{ userId, status, customStatus? }Changement de statut d'un ami (online/idle/dnd/invisible)
PROFILE_UPDATE
{ userId, username?, displayName?, avatarUrl?, bio? }Mise à jour de profil d'un utilisateur dans nos serveurs/amis

Messages directs

message:new
{ id, conversationId, sender, content, replyTo?, createdAt, reactions[] }Nouveau DM reçu (et copie pour l'expéditeur)
message:sent
{ message }Confirmation d'envoi optimiste pour l'expéditeur
message:edited
{ id, conversationId, content, editedAt }DM modifié
message:deleted
{ id, conversationId }DM supprimé
message:failed
{ messageId, error }Échec sauvegarde (livraison optimiste)
TYPING_START
{ userId, conversationId }Indicateur de frappe dans un DM
TYPING_STOP
{ userId, conversationId }Fin de l'indicateur dans un DM

Archive DM (P2P)

DM_ARCHIVE_PUSH
{ conversationId, messages[], total }Messages archivés envoyés par un pair (réponse à DM_ARCHIVE_REQUEST)
DM_ARCHIVE_PEER_REQUEST
{ conversationId, before, limit, fromUserId }Un pair demande vos archives — répondre avec DM_ARCHIVE_PEER_RESPONSE
DM_ARCHIVE_RESPONSE
{ conversationId, status }Statut de réponse à une demande (from server)

Amis

FRIEND_REQUEST
{ requestId, from: { id, username, avatarUrl } }Demande d'ami reçue
FRIEND_ACCEPT
{ requestId, friend: { id, username, avatarUrl } }Votre demande d'ami a été acceptée
FRIEND_REMOVE
{ userId }Ami supprimé ou vous avez été retiré

Appels WebRTC

CALL_INCOMING
{ callId, type, from: { id, username, avatarUrl } }Appel entrant (accepter avec CALL_ACCEPT)
CALL_ACCEPT
{ callId, userId }Un participant a accepté l'appel
CALL_REJECT
{ callId, userId }Un participant a refusé l'appel
CALL_END
{ callId }Appel terminé
CALL_PARTICIPANT_JOINED
{ callId, userId, username }Nouveau participant dans l'appel
CALL_PEER_RECONNECTED
{ callId, userId }Un participant a reconnecté après perte de connexion
WEBRTC_OFFER
{ callId, offer, from: userId }Offer SDP reçue d'un pair
WEBRTC_ANSWER
{ callId, answer, from: userId }Answer SDP reçue d'un pair
WEBRTC_ICE_CANDIDATE
{ callId, candidate, from: userId }Candidat ICE reçu

Canaux vocaux

VOICE_USER_JOINED
{ channelId, userId, username }Un utilisateur a rejoint le canal vocal
VOICE_USER_LEFT
{ channelId, userId }Un utilisateur a quitté le canal vocal
VOICE_STATE_UPDATE
{ channelId, userId, muted, deafened }Changement d'état micro/casque d'un participant
VOICE_OFFER
{ channelId, from: userId, offer }Signaling vocal — offer
VOICE_ANSWER
{ channelId, from: userId, answer }Signaling vocal — answer
VOICE_ICE_CANDIDATE
{ channelId, from: userId, candidate }Signaling vocal — candidat ICE

Messages de serveur

SERVER_TYPING_START
{ serverId, channelId, userId }Frappe en cours dans un canal de serveur
SERVER_TYPING_STOP
{ serverId, channelId, userId }Fin frappe dans un canal

Membres & structure

MEMBER_JOIN
{ serverId, member: { userId, username, roles[] } }Nouveau membre arrivé dans un serveur
CHANNEL_CREATE
{ serverId, channel: { id, name, type } }Nouveau canal créé dans un serveur
CHANNEL_UPDATE
{ serverId, channel }Canal modifié
CHANNEL_DELETE
{ serverId, channelId }Canal supprimé
ROLE_CREATE
{ serverId, role }Rôle créé
ROLE_UPDATE
{ serverId, role }Rôle modifié
ROLE_DELETE
{ serverId, roleId }Rôle supprimé

Exemples de code

Appel WebRTC — initiation + signaling
js
// 1. Initier un appel (callback avec l'id de l'appel)
socket.emit('CALL_INITIATE', { type: 'video', recipientId: 'user-uuid' }, (callId) => {
  console.log('Appel créé :', callId);
});

// 2. L'autre end reçoit
socket.on('CALL_INCOMING', ({ callId, from }) => {
  const accept = window.confirm(`Appel de ${from.username} ?`);
  socket.emit(accept ? 'CALL_ACCEPT' : 'CALL_REJECT', { callId });
});

// 3. Signaling WebRTC (après CALL_ACCEPT)
const pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.alfychat.app' }] });

pc.onicecandidate = ({ candidate }) => {
  if (candidate) socket.emit('WEBRTC_ICE_CANDIDATE', { callId, candidate });
};

const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
socket.emit('WEBRTC_OFFER', { callId, offer });

socket.on('WEBRTC_ANSWER', async ({ answer }) => {
  await pc.setRemoteDescription(new RTCSessionDescription(answer));
});
socket.on('WEBRTC_ICE_CANDIDATE', async ({ candidate }) => {
  await pc.addIceCandidate(new RTCIceCandidate(candidate));
});
Canal vocal de serveur — rejoindre + signaling
js
// Rejoindre le canal vocal
socket.emit('VOICE_JOIN', { serverId: 'srv-uuid', channelId: 'ch-uuid' });

socket.on('VOICE_USER_JOINED', async ({ channelId, userId }) => {
  // Créer une connexion WebRTC par participant
  const pc = createPeerConnectionFor(userId);
  const offer = await pc.createOffer();
  await pc.setLocalDescription(offer);
  socket.emit('VOICE_OFFER', { channelId, targetUserId: userId, offer });
});

socket.on('VOICE_OFFER',  async ({ from, offer }) => {
  const pc = getOrCreatePC(from);
  await pc.setRemoteDescription(offer);
  const answer = await pc.createAnswer();
  await pc.setLocalDescription(answer);
  socket.emit('VOICE_ANSWER', { channelId: 'ch-uuid', targetUserId: from, answer });
});
Commandes de serveur avec callback
js
// Historique paginé
socket.emit('SERVER_MESSAGE_HISTORY',
  { serverId: 'srv-id', channelId: 'ch-id', limit: 50 },
  ({ messages }) => {
    messages.forEach(m => console.log(m.author.username, ':', m.content));
  }
);

// Mettre à jour un membre (rôle)
socket.emit('MEMBER_UPDATE',
  { serverId: 'srv-id', targetUserId: 'usr-id', roleIds: ['role-id-1'] },
  ({ member }) => console.log('Rôle mis à jour :', member)
);

Heartbeat obligatoire

Sans HEARTBEAT toutes les 30 secondes, la connexion est coupée après 60 secondes d'inactivité (pingTimeout). Le serveur répond avec HEARTBEAT_ACK { timestamp }.