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/serveursGET_BULK_PRESENCE{ userIds: string[] }↩ { presences: Record<userId, PresenceState> }Récupérer la présence de plusieurs utilisateursMessages 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 messagemessage:delete{ messageId, conversationId? }Supprimer un messageTYPING_START{ conversationId }Afficher l'indicateur "en train d'écrire"TYPING_STOP{ conversationId }Masquer l'indicateur de frappeREACTION_ADD{ messageId, conversationId, emoji }Ajouter une réaction à un DMREACTION_REMOVE{ messageId, conversationId, emoji }Retirer une réaction d'un DMArchive DM (P2P)
DM_ARCHIVE_REQUEST{ conversationId, before, limit }Demander des messages archivés à l'autre pair en ligneDM_ARCHIVE_PEER_RESPONSE{ conversationId, messages[], archiveLogId }Répondre à une demande d'archive d'un pairDM_ARCHIVE_CONFIRM{ conversationId, archiveLogId }Confirmer la réception d'une archiveDM_ARCHIVE_STATUS{ conversationId }↩ { status: ArchiveStatus }Demander le statut d'archive d'une conversationAmis
FRIEND_REQUEST{ toUserId, message? }Envoyer une demande d'amiFRIEND_ACCEPT{ requestId }Accepter une demande d'amiAppels (WebRTC)
CALL_INITIATE{ type, recipientId?, conversationId?, channelId? }↩ (callId: string)"audio" | "video" | "channel" — callback avec l'ID d'appelCALL_ACCEPT{ callId }Accepter un appel entrantCALL_REJECT{ callId }Refuser un appel entrantCALL_END{ callId }Terminer un appel en coursCALL_REJOIN{ callId }Rejoindre un appel après reconnexion WebSocketWEBRTC_OFFER{ callId, offer: RTCSessionDescription }Signaling — envoyer l'offer SDPWEBRTC_ANSWER{ callId, answer: RTCSessionDescription }Signaling — répondre à une offer SDPWEBRTC_ICE_CANDIDATE{ callId, candidate: RTCIceCandidate }Signaling — partager un candidat ICECanaux vocaux (serveurs)
VOICE_JOIN{ serverId, channelId }Rejoindre un canal vocalVOICE_LEAVE{ serverId, channelId }Quitter un canal vocalVOICE_STATE_UPDATE{ channelId, muted, deafened }Mettre à jour son état micro/casqueVOICE_OFFER{ channelId, targetUserId, offer }Signaling vocal — offer vers un participantVOICE_ANSWER{ channelId, targetUserId, answer }Signaling vocal — answer vers un participantVOICE_ICE_CANDIDATE{ channelId, targetUserId, candidate }Signaling vocal — candidat ICEGET_VOICE_STATE{ serverId }↩ { voiceStates: VoiceState[] }Récupérer les états vocaux d'un serveurMessages de serveur
SERVER_MESSAGE_SEND{ serverId, channelId, content, replyToId? }Envoyer un message dans un salon de serveurSERVER_MESSAGE_EDIT{ serverId, channelId, messageId, content }Modifier un message de serveurSERVER_MESSAGE_DELETE{ serverId, channelId, messageId }Supprimer un message de serveurSERVER_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 serveurSERVER_REACTION_REMOVE{ serverId, channelId, messageId, emoji }Retirer une réaction dans un serveurSERVER_TYPING_START{ serverId, channelId }Afficher l'indicateur de frappe dans un salonSERVER_TYPING_STOP{ serverId, channelId }Masquer l'indicateur de frappeGestion des serveurs & membres
SERVER_JOIN{ serverId }Rejoindre un serveur existant (room auto-join)SERVER_LEAVE{ serverId }Quitter un serveurSERVER_INFO{ serverId }↩ { server: ServerDetails }Récupérer les infos complètes d'un serveurSERVER_GET_CHANNELS{ serverId }↩ { channels[] }Lister les canaux d'un serveurMEMBER_LIST{ serverId }↩ { members[] }Lister les membres d'un serveurMEMBER_UPDATE{ serverId, targetUserId, roleIds[], nickname? }↩ { member }Modifier le rôle ou le pseudo d'un membreMEMBER_KICK{ serverId, targetUserId, reason? }Exclure un membre (permission requis)MEMBER_BAN{ serverId, targetUserId, reason? }Bannir un membreCanaux
CHANNEL_CREATE{ serverId, name, type }Créer un canal dans un serveurCHANNEL_UPDATE{ serverId, channelId, name?, position? }Modifier un canalCHANNEL_DELETE{ serverId, channelId }Supprimer un canalRôles
ROLE_LIST{ serverId }↩ { roles[] }Lister les rôles d'un serveurROLE_CREATE{ serverId, name, color?, permissions? }Créer un rôleROLE_UPDATE{ serverId, roleId, name?, color?, permissions? }Modifier un rôleROLE_DELETE{ serverId, roleId }Supprimer un rôleInvitations
INVITE_LIST{ serverId }↩ { invites[] }Lister les invitations activesINVITE_CREATE{ serverId, maxUses?, expiresIn? }↩ { invite }Créer un lien d'invitationINVITE_DELETE{ serverId, code }Révoquer une invitationINVITE_VERIFY{ code }↩ { valid, server? }Vérifier un code d'invitationGroupes (DM multi)
GROUP_CREATE{ name, memberIds[] }↩ { group }Créer un groupeGROUP_UPDATE{ groupId, name?, avatarUrl? }Modifier un groupeGROUP_LEAVE{ groupId }Quitter un groupeGROUP_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 connexionHEARTBEAT_ACK{ timestamp }Accusé de réception du heartbeatPENDING_PINGS{ pings: Notification[] }Notifications manquées reçues lors de la reconnexionPRESENCE_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/amisMessages 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éditeurmessage: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 DMTYPING_STOP{ userId, conversationId }Fin de l'indicateur dans un DMArchive 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_RESPONSEDM_ARCHIVE_RESPONSE{ conversationId, status }Statut de réponse à une demande (from server)Amis
FRIEND_REQUEST{ requestId, from: { id, username, avatarUrl } }Demande d'ami reçueFRIEND_ACCEPT{ requestId, friend: { id, username, avatarUrl } }Votre demande d'ami a été acceptéeFRIEND_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'appelCALL_REJECT{ callId, userId }Un participant a refusé l'appelCALL_END{ callId }Appel terminéCALL_PARTICIPANT_JOINED{ callId, userId, username }Nouveau participant dans l'appelCALL_PEER_RECONNECTED{ callId, userId }Un participant a reconnecté après perte de connexionWEBRTC_OFFER{ callId, offer, from: userId }Offer SDP reçue d'un pairWEBRTC_ANSWER{ callId, answer, from: userId }Answer SDP reçue d'un pairWEBRTC_ICE_CANDIDATE{ callId, candidate, from: userId }Candidat ICE reçuCanaux vocaux
VOICE_USER_JOINED{ channelId, userId, username }Un utilisateur a rejoint le canal vocalVOICE_USER_LEFT{ channelId, userId }Un utilisateur a quitté le canal vocalVOICE_STATE_UPDATE{ channelId, userId, muted, deafened }Changement d'état micro/casque d'un participantVOICE_OFFER{ channelId, from: userId, offer }Signaling vocal — offerVOICE_ANSWER{ channelId, from: userId, answer }Signaling vocal — answerVOICE_ICE_CANDIDATE{ channelId, from: userId, candidate }Signaling vocal — candidat ICEMessages de serveur
SERVER_TYPING_START{ serverId, channelId, userId }Frappe en cours dans un canal de serveurSERVER_TYPING_STOP{ serverId, channelId, userId }Fin frappe dans un canalMembres & structure
MEMBER_JOIN{ serverId, member: { userId, username, roles[] } }Nouveau membre arrivé dans un serveurCHANNEL_CREATE{ serverId, channel: { id, name, type } }Nouveau canal créé dans un serveurCHANNEL_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 }.