Live Stream socket events
WebSocket event sözlüğü ve subscribe kuralları
Yayın Socket Event'leri Dokümantasyonu
Bu dokümantasyon, yayın ile ilgili tüm WebSocket namespace'lerini, event'lerini, payload'larını ve dönüş tiplerini içermektedir.
İçindekiler
-
Guest Namespace (
/guest) Uygulamanın genelinde dinlenilen bir socket. Birisi davet atmışmı diye
Genel Bakış
Yayın sistemi 5 farklı WebSocket namespace'i kullanır:
| Namespace | Amaç | Authentication |
|---|---|---|
/guest | Davet yönetimi (yayına katılmadan önce) | userId query param |
/guest-stream | Yayın odası (yayıncı, misafir, izleyici) | JWT token |
/live-stream | Viewer count ve yayın durumu | Yok |
/live-stream-status | Uygulama geneli canlı yayın durum değişimleri | Global event'ler auth'suz, kullanıcıya özel event'ler JWT subscribe |
/stream-chat | Chat mesajlaşması | JWT token |
Namespace'ler
Base URL'ler
- Local:
ws://localhost:3000 - Development:
wss://dev.allmine.win - Staging:
wss://staging.allmine.win - Production:
wss://api.allmine.win
Live Stream Status Namespace (/live-stream-status)
Endpoint: {BASE_URL}/live-stream-status
Amaç: Uygulama genelinde canlı yayın durum değişimlerini ve token ile abone olan host/guest kullanıcılar için hazır başlama bilgisini gerçek zamanlı dinlemek.
Bağlantı
const socket = io(`${BASE_URL}/live-stream-status`, {
transports: ['websocket', 'polling'],
});Client → Server Event'leri
Global durum event'leri için client'tan server'a zorunlu bir abonelik eventi yoktur. Kullanıcıya özel liveStreamReadyToStart event'i için abone olunmalıdır.
1. subscribe
Kullanıcıya özel status event'leri için socket'i user:{userId} odasına alır.
socket.emit('subscribe', {
token: accessToken, // Bearer prefix'i opsiyonel
});Başarılı yanıt:
socket.on('subscribeSuccess', (payload: { userId: string; room: string }) => {});Hata yanıtı:
socket.on('subscribeError', (payload: { code: string; message: string }) => {});2. unsubscribe
socket.emit('unsubscribe');
socket.on('unsubscribeSuccess', () => {});Server → Client Event'leri
1. liveStreamScheduled
2. liveStreamPreparing
3. liveStreamStarted
4. liveStreamEnded
5. liveStreamExpired
6. liveStreamCancelled
7. liveStreamFundingProgress
8. liveStreamFundingGoalReached
9. liveStreamReadyToStart
Tüm event'lerde aşağıdaki base payload bulunur:
{
eventId: string;
streamId: string;
occurredAt: string; // ISO 8601
previousStatus: 'scheduled' | 'preparing' | 'active' | 'ended' | 'expired' | 'cancelled_by_host' | 'cancelled_by_guest' | null;
status: 'scheduled' | 'preparing' | 'active' | 'ended' | 'expired' | 'cancelled_by_host' | 'cancelled_by_guest';
summary: {
title: string | null;
liveStreamType: 'solo' | 'duocrowd' | 'duoself' | null;
accessType: 'free' | 'paid' | null;
plannedStartDate: string | null; // ISO 8601
startedAt: string | null; // ISO 8601
endedAt: string | null; // ISO 8601
fundingGoal: number | null;
collectedFunding: number | null;
fundingPercentage: number | null;
};
}Event'e özel ek alanlar:
// liveStreamCancelled
{
cancelledByRole: 'host' | 'guest';
}
// liveStreamFundingProgress
{
amountDelta: number;
remainingFunding: number | null;
isGoalReached: boolean;
}
// liveStreamReadyToStart
{
previousStatus: 'scheduled';
status: 'preparing';
recipientRole: 'host' | 'guest';
readyToStart: true;
}liveStreamReadyToStart yalnızca hedefe ulaşmış ve zamanı gelmiş DuoCrowd yayınlar ile zamanı gelmiş DuoSelf yayınlar preparing durumuna geçtiğinde host/guest kullanıcı odalarına gönderilir. Auth'suz global bağlantılar bu event'i almaz.
Guest Namespace (/guest)
Endpoint: {BASE_URL}/guest
Amaç: Kullanıcılar yayına katılmadan önce davet yönetimi için kullanılır.
Bağlantı
const socket = io(`${BASE_URL}/guest`, {
query: {
userId: 'user-id-here'
},
transports: ['websocket']
});Query Parametreleri:
userId(required): Kullanıcı ID'si
Client → Server Event'leri
1. acceptGuestInvite
Daveti kabul eder.
Payload:
{
streamId: string; // MongoDB ObjectId
userId: string; // Kullanıcı ID'si
uid: string; // Agora UID
}Örnek:
socket.emit('acceptGuestInvite', {
streamId: '507f1f77bcf86cd799439011',
userId: '507f1f77bcf86cd799439012',
uid: '12345'
});Yanıt: guestInviteAccepted event'i gelir.
2. rejectGuestInvite
Daveti reddeder.
Payload:
{
streamId: string;
userId: string;
}Örnek:
socket.emit('rejectGuestInvite', {
streamId: '507f1f77bcf86cd799439011',
userId: '507f1f77bcf86cd799439012'
});Yanıt: guestInviteRejected event'i gelir.
Server → Client Event'leri
1. guestInvite
Kullanıcıya davet gönderildiğinde gelir.
Payload:
{
userId: string;
userSummary: UserSummaryDto | null;
streamId: string;
invitedBy: string;
invitedAt: string; // ISO 8601 format
}Örnek:
socket.on('guestInvite', (data) => {
console.log('Davet geldi:', data);
});2. guestInviteAccepted
Davet kabul edildiğinde kullanıcıya bildirim gelir.
Payload:
{
streamId: string;
uid: string;
}Örnek:
socket.on('guestInviteAccepted', (data) => {
console.log('Davet kabul edildi:', data);
});3. guestInviteRejected
Davet reddedildiğinde kullanıcıya bildirim gelir.
Payload:
{
userId: string;
userSummary: UserSummaryDto | null;
streamId: string;
type: 'manual' | 'manual_prejoin';
}Örnek:
socket.on('guestInviteRejected', (data) => {
console.log('Davet reddedildi:', data);
});4. guestInviteExpired
Davet süresi dolduğunda (30 saniye) gelir.
Payload:
{
userId: string;
userSummary: UserSummaryDto | null;
streamId: string;
type: 'auto';
reason: 'timeout';
}Örnek:
socket.on('guestInviteExpired', (data) => {
console.log('Davet süresi doldu:', data);
});5. inviteCanceled
Yayıncı daveti iptal ettiğinde gelir.
Payload:
{
invitedUser: string;
invitedUserSummary: UserSummaryDto | null;
streamId: string;
canceledBy: string;
canceledBySummary: UserSummaryDto | null;
}Örnek:
socket.on('inviteCanceled', (data) => {
console.log('Davet iptal edildi:', data);
});6. guestLeftNotification
Misafir yayından ayrıldığında yayıncıya bildirim gelir.
Payload:
{
userId: string;
streamId: string;
reason: string;
initiatedBy: 'guest';
hostId: string;
hostSummary: UserSummaryDto | null;
}Örnek:
socket.on('guestLeftNotification', (data) => {
console.log('Misafir ayrıldı:', data);
});7. guestKicked
Kullanıcı yayından atıldığında gelir.
Payload:
{
userId: string;
userSummary: UserSummaryDto | null;
streamId: string;
kickedBy: string;
kickedBySummary: UserSummaryDto | null;
}Örnek:
socket.on('guestKicked', (data) => {
console.log('Yayından atıldınız:', data);
});8. error
Hata durumunda gelir.
Payload:
{
message: string;
}Örnek:
socket.on('error', (data) => {
console.error('Hata:', data.message);
});Guest Stream Namespace (/guest-stream)
Endpoint: {BASE_URL}/guest-stream
Amaç: Yayın odası - yayıncı, misafir ve izleyiciler için gerçek zamanlı event'ler.
Bağlantı
const socket = io(`${BASE_URL}/guest-stream`, {
auth: {
streamId: 'stream-id-here',
token: 'jwt-token-here'
},
// veya query ile:
query: {
streamId: 'stream-id-here'
},
headers: {
Authorization: 'Bearer jwt-token-here'
},
transports: ['websocket']
});Authentication:
streamId(required): Yayın ID'si (auth veya query'de)token(required): JWT access token (auth veya Authorization header'da)
Room Yapısı:
- Room adı:
guest-stream:{streamId} - Bağlantı kurulduğunda otomatik olarak room'a katılır
Client → Server Event'leri
1. inviteGuest
Yayıncı misafir davet eder.
Payload:
{
userId: string; // Davet edilecek kullanıcı ID'si
streamId: string; // Yayın ID'si
}Örnek:
socket.emit('inviteGuest', {
userId: '507f1f77bcf86cd799439012',
streamId: '507f1f77bcf86cd799439011'
});Yanıt: guestInvitationBroadcast event'i room'a broadcast edilir.
2. cancelInvite
Yayıncı daveti iptal eder.
Payload:
{
userId: string; // Davet iptal edilecek kullanıcı ID'si
streamId: string; // Yayın ID'si
}Örnek:
socket.emit('cancelInvite', {
userId: '507f1f77bcf86cd799439012',
streamId: '507f1f77bcf86cd799439011'
});Yanıt: inviteCancelBroadcast event'i room'a broadcast edilir.
3. leaveGuestStream
Misafir yayından ayrılır.
Payload:
{
streamId: string;
reason?: string; // Opsiyonel ayrılma nedeni
hostId?: string; // Yayıncı ID'si
}Örnek:
socket.emit('leaveGuestStream', {
streamId: '507f1f77bcf86cd799439011',
reason: 'user_request',
hostId: '507f1f77bcf86cd799439010'
});Yanıt: guestLeft event'i room'a broadcast edilir.
4. kickGuest
Yayıncı misafiri yayından atar.
Payload:
{
userId: string; // Atılacak kullanıcı ID'si
streamId: string; // Yayın ID'si
}Örnek:
socket.emit('kickGuest', {
userId: '507f1f77bcf86cd799439012',
streamId: '507f1f77bcf86cd799439011'
});Yanıt: guestKicked event'i room'a broadcast edilir.
Server → Client Event'leri
1. joinedStream
Bağlantı kurulduğunda ve room'a katıldığında gelir.
Payload:
{
streamId: string;
}Örnek:
socket.on('joinedStream', (data) => {
console.log('Yayın odasına katıldınız:', data.streamId);
});2. userReconnected
Yayıncı veya misafir yeniden bağlandığında gelir (offline timer iptal edildiğinde).
Payload:
{
streamId: string;
userId: string;
offlineSince: string | null; // ISO 8601 format veya null
}Örnek:
socket.on('userReconnected', (data) => {
console.log('Kullanıcı yeniden bağlandı:', data);
});3. userOffline
Kullanıcı bağlantısı kesildiğinde gelir (tüm kullanıcılar için).
Payload:
{
streamId: string;
userId: string;
timestamp: string; // ISO 8601 format
}Örnek:
socket.on('userOffline', (data) => {
console.log('Kullanıcı offline:', data);
});4. guestInvitationBroadcast
Davet gönderildiğinde room'daki herkese broadcast edilir.
Payload:
{
invitedUser: string;
invitedUserSummary: UserSummaryDto | null;
invitedAt: string; // ISO 8601 format
invitedBy: string;
invitedBySummary: UserSummaryDto | null;
}Örnek:
socket.on('guestInvitationBroadcast', (data) => {
console.log('Davet gönderildi:', data);
});5. inviteCancelBroadcast
Davet iptal edildiğinde room'daki herkese broadcast edilir.
Payload:
{
invitedUser: string;
invitedUserSummary: UserSummaryDto | null;
canceledBy: string;
canceledBySummary: UserSummaryDto | null;
}Örnek:
socket.on('inviteCancelBroadcast', (data) => {
console.log('Davet iptal edildi:', data);
});6. guestAccepted
Misafir daveti kabul ettiğinde room'daki herkese broadcast edilir.
Payload:
{
userId: string;
userSummary: UserSummaryDto | null;
streamId: string;
uid: string;
}Örnek:
socket.on('guestAccepted', (data) => {
console.log('Misafir daveti kabul etti:', data);
});7. onGuestJoined
Guest kullanıcı live stream'e join olduğunda (join endpoint'i çağrıldığında) room'daki herkese broadcast edilir. Bu event, guest kullanıcının uid bilgisini içerir ve Agora'da yayın esnasında kullanılabilir.
Payload:
{
streamId: string;
userId: string;
uid: number; // Agora UID
userSummary: UserSummaryDto | null;
timestamp: string; // ISO 8601 format
}Örnek:
socket.on('onGuestJoined', (data) => {
console.log('Guest yayına katıldı:', data);
console.log('Guest UID:', data.uid);
});8. guestRejected
Misafir daveti reddettiğinde veya süresi dolduğunda room'daki herkese broadcast edilir.
Payload:
{
userId: string;
userSummary: UserSummaryDto | null;
streamId: string;
type: 'manual' | 'manual_prejoin' | 'auto';
reason?: string; // 'timeout' gibi
}Örnek:
socket.on('guestRejected', (data) => {
console.log('Misafir daveti reddetti:', data);
});9. guestInviteCanceled
Davet iptal edildiğinde room'daki herkese broadcast edilir.
Payload:
{
invitedUser: string;
invitedUserSummary: UserSummaryDto | null;
streamId: string;
canceledBy: string;
canceledBySummary: UserSummaryDto | null;
}Örnek:
socket.on('guestInviteCanceled', (data) => {
console.log('Davet iptal edildi:', data);
});10. guestLeft
Misafir yayından ayrıldığında room'daki herkese broadcast edilir.
Payload:
{
userId: string;
streamId: string;
reason: string; // 'guest_left' gibi
initiatedBy: 'guest';
}Örnek:
socket.on('guestLeft', (data) => {
console.log('Misafir ayrıldı:', data);
});11. guestKicked
Misafir yayından atıldığında room'daki herkese broadcast edilir.
Payload:
{
userId: string;
userSummary: UserSummaryDto | null;
streamId: string;
kickedBy: string;
kickedBySummary: UserSummaryDto | null;
}Örnek:
socket.on('guestKicked', (data) => {
console.log('Misafir atıldı:', data);
});12. guestRemovedDueToTimeout
Misafir offline timeout (30 saniye) nedeniyle yayından çıkarıldığında gelir.
Payload:
{
userId: string;
userSummary: UserSummaryDto | null;
streamId: string;
reason: 'offline_timeout';
initiatedBy: 'system';
}Örnek:
socket.on('guestRemovedDueToTimeout', (data) => {
console.log('Misafir timeout nedeniyle çıkarıldı:', data);
});13. hostOfflineTimeout
Yayıncı offline timeout (30 saniye) nedeniyle yayın sonlandırıldığında gelir.
Payload:
{
streamId: string;
hostId: string;
reason: 'offline_timeout';
}Örnek:
socket.on('hostOfflineTimeout', (data) => {
console.log('Yayın timeout nedeniyle sonlandırıldı:', data);
});14. error
Hata durumunda gelir.
Payload:
{
message: string;
}Hata Mesajları:
"streamId is required""Access token is required""Invalid token"
Örnek:
socket.on('error', (data) => {
console.error('Hata:', data.message);
});Live Stream Namespace (/live-stream)
Endpoint: {BASE_URL}/live-stream
Amaç: Viewer count takibi ve yayın durumu güncellemeleri.
streamStarted event'inin uçtan uca entegrasyonu için: docs/live-stream-started-integration.md
Bağlantı
const socket = io(`${BASE_URL}/live-stream`, {
transports: ['websocket']
});Not: Bu namespace için authentication gerekmez.
Room Yapısı:
- Stream room:
stream:{streamId}- Belirli bir yayın için - Overview room:
streams:overview- Tüm yayınlar için
Client → Server Event'leri
1. joinStream
Belirli bir yayına katılır.
Payload:
{
streamId: string; // MongoDB ObjectId
}Örnek:
socket.emit('joinStream', {
streamId: '507f1f77bcf86cd799439011'
});Yanıt: joinedStream event'i gelir.
2. leaveStream
Belirli bir yayından ayrılır.
Payload:
{
streamId: string; // MongoDB ObjectId
}Örnek:
socket.emit('leaveStream', {
streamId: '507f1f77bcf86cd799439011'
});Yanıt: leftStream event'i gelir.
3. joinOverview
Global overview room'una katılır (homepage için).
Payload: Yok
Örnek:
socket.emit('joinOverview');Yanıt: joinedOverview event'i gelir.
4. leaveOverview
Global overview room'undan ayrılır.
Payload: Yok
Örnek:
socket.emit('leaveOverview');Yanıt: leftOverview event'i gelir.
Server → Client Event'leri
1. joinedStream
Yayına başarıyla katıldığında gelir.
Payload:
{
streamId: string;
viewerCount: number;
success: boolean;
}Örnek:
socket.on('joinedStream', (data) => {
console.log(`Yayına katıldınız: ${data.streamId}, İzleyici: ${data.viewerCount}`);
});2. leftStream
Yayından başarıyla ayrıldığında gelir.
Payload:
{
streamId: string;
viewerCount: number;
success: boolean;
}Örnek:
socket.on('leftStream', (data) => {
console.log(`Yayından ayrıldınız: ${data.streamId}, İzleyici: ${data.viewerCount}`);
});3. joinedOverview
Overview room'una başarıyla katıldığında gelir.
Payload:
{
activeStreams: Array<{
streamId: string;
viewerCount: number;
}>;
success: boolean;
}Örnek:
socket.on('joinedOverview', (data) => {
console.log('Aktif yayınlar:', data.activeStreams);
});4. leftOverview
Overview room'undan başarıyla ayrıldığında gelir.
Payload:
{
success: boolean;
}Örnek:
socket.on('leftOverview', (data) => {
console.log('Overview room\'undan ayrıldınız');
});5. viewerCountUpdated
Viewer count güncellendiğinde gelir.
Payload:
{
streamId: string;
viewerCount: number;
}Örnek:
socket.on('viewerCountUpdated', (data) => {
console.log(`Yayın ${data.streamId} izleyici sayısı: ${data.viewerCount}`);
});giftCountUpdated
Yayındaki toplam hediye adedi güncellendiğinde gelir.
Bu event iki durumda tetiklenir:
- Kullanıcı
joinStreamile yayına katıldıktan sonra sadece ilgili socket'e snapshot olarak - Yayına yeni gift gönderildiğinde stream room'undaki herkese broadcast olarak
Payload:
{
streamId: string;
totalGiftCount: number;
timestamp: string; // ISO 8601 format
}Örnek:
socket.on('giftCountUpdated', (data) => {
console.log(`Yayın ${data.streamId} toplam gift adedi: ${data.totalGiftCount}`);
});6. streamStarted
Yayın gerçekten başladığında (startedAt set edildiğinde) ilgili stream room'undaki herkese gelir.
Payload:
{
streamId: string;
startedAt: string; // ISO 8601 format
plannedEndDate: string | null; // ISO 8601 format veya null
timestamp: string; // ISO 8601 format
}Örnek:
socket.on('streamStarted', (data) => {
console.log('Yeni yayın başladı:', data.streamId, data.startedAt, data.plannedEndDate);
});7. streamEnded
Yayın bittiğinde overview room'undaki herkese gelir.
Payload:
{
streamId: string;
}Örnek:
socket.on('streamEnded', (data) => {
console.log('Yayın bitti:', data.streamId);
});8. streamTimeExtensionAdded
Yayın süresi uzatıldığında stream room'undaki herkese gelir.
Payload:
{
id: string;
streamId: string;
senderId: string;
durationSeconds: number;
senderSnapshot: {
_id: string;
username?: string;
name?: string | null;
surname?: string | null;
profilePhoto?: any | null;
};
createdAt: string; // ISO 8601 format
}Örnek:
socket.on('streamTimeExtensionAdded', (data) => {
console.log('Yayın süresi uzatıldı:', data);
});9. userBanned
Kullanıcı banlandığında stream room'undaki herkese gelir.
Payload:
{
targetUserId: string;
targetUser: UserSummaryDto;
actionType: string;
reason?: string;
scope: string;
timestamp: string; // ISO 8601 format
}Örnek:
socket.on('userBanned', (data) => {
console.log('Kullanıcı banlandı:', data);
});10. userBanRevoked
Kullanıcının banı kaldırıldığında stream room'undaki herkese gelir.
Payload:
{
targetUserId: string;
timestamp: string; // ISO 8601 format
}Örnek:
socket.on('userBanRevoked', (data) => {
console.log('Ban kaldırıldı:', data);
});11. userKickedFromStream
Kullanıcı yetersiz bakiye veya başka bir nedenle yayından atıldığında stream room'undaki herkese gelir.
Payload:
{
streamId: string;
userId: string;
reason: string; // Örn: 'Insufficient credit balance'
timestamp: string; // ISO 8601 format
}Örnek:
socket.on('userKickedFromStream', (data) => {
if (data.userId === currentUserId) {
console.log('Yayından atıldınız:', data.reason);
// Yayından çık ve hata mesajı göster
} else {
console.log('Kullanıcı yayından atıldı:', data.userId);
}
});12. joinStreamError
Yayına katılma hatası.
Payload:
{
streamId: string;
error: string;
}Örnek:
socket.on('joinStreamError', (data) => {
console.error('Yayına katılma hatası:', data.error);
});13. leaveStreamError
Yayından ayrılma hatası.
Payload:
{
streamId: string;
error: string;
}Örnek:
socket.on('leaveStreamError', (data) => {
console.error('Yayından ayrılma hatası:', data.error);
});14. joinOverviewError
Overview room'una katılma hatası.
Payload:
{
error: string;
}Örnek:
socket.on('joinOverviewError', (data) => {
console.error('Overview room'una katılma hatası:', data.error);
});15. leaveOverviewError
Overview room'undan ayrılma hatası.
Payload:
{
error: string;
}Örnek:
socket.on('leaveOverviewError', (data) => {
console.error('Overview room'undan ayrılma hatası:', data.error);
});Stream Chat Namespace (/stream-chat)
Endpoint: {BASE_URL}/stream-chat
Amaç: Yayın chat mesajlaşması.
Bağlantı
const socket = io(`${BASE_URL}/stream-chat`, {
transports: ['websocket', 'polling']
});Authentication: JWT token joinStream event'inde gönderilir.
Room Yapısı:
- Room adı:
stream:{streamId} joinStreamevent'i ile room'a katılınır
Client → Server Event'leri
1. joinStream
Yayın chat'ine katılır.
Payload:
{
streamId: string; // MongoDB ObjectId
token: string; // JWT access token
}Örnek:
socket.emit('joinStream', {
streamId: '507f1f77bcf86cd799439011',
token: '<access_token>'
});Yanıt: joinStreamSuccess event'i gelir.
Hata: joinStreamError event'i gelir.
2. leaveStream
Yayın chat'inden ayrılır.
Payload:
{
streamId: string; // MongoDB ObjectId
}Örnek:
socket.emit('leaveStream', {
streamId: '507f1f77bcf86cd799439011'
});Yanıt: leaveStreamSuccess event'i gelir.
3. sendMessage
Chat mesajı gönderir.
Payload:
{
streamId: string;
content: string; // Mesaj içeriği
}Örnek:
socket.emit('sendMessage', {
streamId: '507f1f77bcf86cd799439011',
content: 'Herkese selam!'
});Yanıt: sendMessageSuccess event'i gelir.
Hata: sendMessageError event'i gelir.
4. sendReaction
Like veya kalp reaksiyonu gönderir.
Payload:
{
streamId: string; // MongoDB ObjectId
type: 'like' | 'heart';
}Örnek:
socket.emit('sendReaction', {
streamId: '507f1f77bcf86cd799439011',
type: 'like'
});Yanıt: sendReactionSuccess event'i gelir.
Hata: sendReactionError event'i gelir.
Server → Client Event'leri
1. joinStreamSuccess
Chat'e başarıyla katıldığında gelir.
Payload:
{
room: string; // `stream:{streamId}` formatında
userId: string;
}Örnek:
socket.on('joinStreamSuccess', (data) => {
console.log('Chat\'e katıldınız:', data);
});2. leaveStreamSuccess
Chat'ten başarıyla ayrıldığında gelir.
Payload:
{
room: string; // `stream:{streamId}` formatında
}Örnek:
socket.on('leaveStreamSuccess', (data) => {
console.log('Chat\'ten ayrıldınız:', data);
});3. newMessage
Yeni mesaj geldiğinde room'daki herkese broadcast edilir.
Payload:
{
_id: string; // Mesaj ID'si
streamId: string; // Yayın ID'si
content: string; // Mesaj içeriği
sender: UserSummaryDto; // Gönderen kullanıcı bilgisi
createdAt: Date; // Oluşturulma tarihi
updatedAt: Date; // Güncellenme tarihi
}Örnek:
socket.on('newMessage', (data) => {
console.log('Yeni mesaj:', data.content, 'Gönderen:', data.sender.username);
});4. sendMessageSuccess
Mesaj başarıyla gönderildiğinde gelir.
Payload:
{
_id: string;
streamId: string;
content: string;
sender: UserSummaryDto;
createdAt: Date;
updatedAt: Date;
}Örnek:
socket.on('sendMessageSuccess', (data) => {
console.log('Mesaj gönderildi:', data);
});5. newReaction
Yeni reaksiyon geldiğinde room'daki herkese broadcast edilir.
Payload:
{
streamId: string; // Yayın ID'si
type: 'like' | 'heart'; // Reaksiyon tipi
userId: string; // Gönderen kullanıcı ID'si
timestamp: Date; // Reaksiyon zamanı
}Örnek:
socket.on('newReaction', (data) => {
console.log('Yeni reaksiyon:', data.type, 'Gönderen:', data.userId);
});6. sendReactionSuccess
Reaksiyon başarıyla gönderildiğinde gelir.
Payload:
{
streamId: string;
type: 'like' | 'heart';
timestamp: Date;
}Örnek:
socket.on('sendReactionSuccess', (data) => {
console.log('Reaksiyon gönderildi:', data);
});7. joinStreamError
Chat'e katılma hatası.
Payload:
{
code: string;
message: string;
}Hata Kodları:
INVALID_STREAM_ID: Geçersiz stream IDAUTH_REQUIRED: Token gerekliTOKEN_INVALID: Geçersiz veya süresi dolmuş tokenUSER_INVALID: Token geçerli bir kullanıcı içermiyorSTREAM_INACTIVE: Yayın aktif değil
Örnek:
socket.on('joinStreamError', (data) => {
console.error('Chat\'e katılma hatası:', data.code, data.message);
});6. sendMessageError
Mesaj gönderme hatası.
Payload:
{
code: string;
message: string;
}Hata Kodları:
INVALID_STREAM_ID: Geçersiz stream IDNOT_IN_ROOM: Önce yayına katılmalısınızEMPTY_CONTENT: Mesaj içeriği gerekliSEND_FAILED: Mesaj gönderme başarısız
Örnek:
socket.on('sendMessageError', (data) => {
console.error('Mesaj gönderme hatası:', data.code, data.message);
});8. sendReactionError
Reaksiyon gönderme hatası.
Payload:
{
code: string;
message: string;
}Hata Kodları:
INVALID_STREAM_ID: Geçersiz stream IDNOT_IN_ROOM: Önce yayına katılmalısınızINVALID_REACTION_TYPE: Geçersiz reaksiyon tipiSEND_FAILED: Reaksiyon gönderme başarısız
Örnek:
socket.on('sendReactionError', (data) => {
console.error('Reaksiyon gönderme hatası:', data.code, data.message);
});Ortak Tipler
UserSummaryDto
interface UserSummaryDto {
_id: string;
username?: string;
name?: string | null;
surname?: string | null;
profilePhoto?: {
_id: string;
url: string;
variants?: Array<{
size: number;
url: string;
}>;
// ... diğer media alanları
} | null;
}LiveStreamTimeExtensionResponseDto
interface LiveStreamTimeExtensionResponseDto {
id: string; // Time extension kaydının ID'si
streamId: string;
senderId: string;
durationSeconds: number; // Eklenen süre (saniye cinsinden)
senderSnapshot: {
_id: string;
username?: string | null;
name?: string | null;
surname?: string | null;
profilePhoto?: {
_id: string;
url: string;
variants?: Array<{
size: number;
url: string;
}>;
} | null;
};
createdAt: string; // ISO 8601 formatında
}Event Payload Tipleri
Join/Leave Stream Response
interface JoinedStreamResponse {
streamId: string;
viewerCount: number;
success: boolean;
}
interface LeftStreamResponse {
streamId: string;
viewerCount: number;
success: boolean;
}Stream Status Events
interface StreamStartedPayload {
streamId: string;
startedAt: string; // ISO 8601 formatında
plannedEndDate: string | null; // ISO 8601 formatında veya null
timestamp: string; // ISO 8601 formatında
}
interface StreamEndedPayload {
streamId: string;
}Ban Events
interface UserBannedPayload {
targetUserId: string;
targetUser: UserSummaryDto;
actionType: string; // 'BLOCK' veya diğer action tipleri
reason?: string; // Ban nedeni (opsiyonel)
scope: string; // 'STREAM' veya 'BROADCASTER'
timestamp: string; // ISO 8601 formatında
}
interface UserBanRevokedPayload {
targetUserId: string;
timestamp: string; // ISO 8601 formatında
}User Kicked Event
interface UserKickedFromStreamPayload {
streamId: string;
userId: string;
reason: string; // Örn: 'Insufficient credit balance'
timestamp: string; // ISO 8601 formatında
}Error Events
interface JoinStreamErrorPayload {
streamId: string;
error: string;
}
interface LeaveStreamErrorPayload {
streamId: string;
error: string;
}
interface OverviewErrorPayload {
error: string;
}Önemli Notlar
Offline Timeout Mekanizması
- Yayıncı veya misafir 30 saniye offline kalırsa:
- Misafir için:
guestRemovedDueToTimeoutevent'i gönderilir ve misafir yayından çıkarılır - Yayıncı için:
hostOfflineTimeoutevent'i gönderilir ve yayın sonlandırılır
- Misafir için:
Davet Timeout
- Davetler 30 saniye içinde kabul edilmezse otomatik olarak reddedilir
guestInviteExpiredevent'i gönderilir
Room Yönetimi
- Her namespace farklı room yapısı kullanır
- Room'lara otomatik katılım veya manuel katılım mekanizmaları vardır
- Disconnect olduğunda otomatik olarak room'lardan çıkarılır
Event Sıralaması
-
Davet Süreci:
guestInvite→acceptGuestInvite/rejectGuestInvite→guestAccepted/guestRejected
-
Yayın Katılımı:
joinStream→joinedStream→guestAccepted(eğer misafir ise)
-
Yayından Ayrılma:
leaveGuestStream→guestLeft→userOffline
Örnek Kullanım Senaryoları
Senaryo 1: Misafir Davet Süreci
// 1. Yayıncı misafir davet eder
guestStreamSocket.emit('inviteGuest', {
userId: 'guest-user-id',
streamId: 'stream-id'
});
// 2. Misafir daveti alır (guest namespace'te)
guestSocket.on('guestInvite', (data) => {
// Daveti göster
});
// 3. Misafir daveti kabul eder
guestSocket.emit('acceptGuestInvite', {
streamId: 'stream-id',
userId: 'guest-user-id',
uid: 'agora-uid'
});
// 4. Yayın odasında herkese bildirim gelir
guestStreamSocket.on('guestAccepted', (data) => {
// Misafir katıldı bilgisini göster
});Senaryo 2: Chat Mesajlaşması
// 1. Chat'e katıl
streamChatSocket.emit('joinStream', {
streamId: 'stream-id',
token: 'jwt-token'
});
// 2. Mesaj gönder
streamChatSocket.emit('sendMessage', {
streamId: 'stream-id',
content: 'Merhaba!'
});
// 3. Yeni mesajları dinle
streamChatSocket.on('newMessage', (data) => {
// Mesajı göster
});Senaryo 3: Viewer Count Takibi
// 1. Yayına katıl
liveStreamSocket.emit('joinStream', {
streamId: 'stream-id'
});
// 2. Viewer count güncellemelerini dinle
liveStreamSocket.on('viewerCountUpdated', (data) => {
// Viewer count'u güncelle
});
// 3. Toplam gift adedi güncellemelerini dinle
liveStreamSocket.on('giftCountUpdated', (data) => {
// Gift sayacını güncelle
});Hata Yönetimi
Tüm namespace'lerde hata durumlarında error event'i gönderilir. Client tarafında mutlaka dinlenmelidir:
socket.on('error', (data) => {
console.error('Socket hatası:', data.message);
// Hata mesajını kullanıcıya göster
});Güvenlik Notları
- JWT Token:
/guest-streamve/stream-chatnamespace'leri JWT token gerektirir - User ID Doğrulama: Tüm event'lerde user ID doğrulaması yapılır
- Stream ID Validation: Tüm stream ID'leri MongoDB ObjectId formatında olmalıdır
- Room İzolasyonu: Her stream kendi room'unda izole edilmiştir
Versiyonlama
Bu dokümantasyon API versiyonu ile birlikte güncellenir. Mevcut versiyon: v1
Destek
Sorularınız için: [email protected]