Allmine API
Live Stream

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

  1. Genel Bakış

  2. Namespace'ler

  3. Guest Namespace (/guest) Uygulamanın genelinde dinlenilen bir socket. Birisi davet atmışmı diye

  4. Guest Stream Namespace (/guest-stream)

  5. Live Stream Namespace (/live-stream)

  6. Live Stream Status Namespace (/live-stream-status)

  7. Stream Chat Namespace (/stream-chat)

  8. Ortak Tipler


Genel Bakış

Yayın sistemi 5 farklı WebSocket namespace'i kullanır:

NamespaceAmaçAuthentication
/guestDavet yönetimi (yayına katılmadan önce)userId query param
/guest-streamYayın odası (yayıncı, misafir, izleyici)JWT token
/live-streamViewer count ve yayın durumuYok
/live-stream-statusUygulama geneli canlı yayın durum değişimleriGlobal event'ler auth'suz, kullanıcıya özel event'ler JWT subscribe
/stream-chatChat 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ı joinStream ile 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}
  • joinStream event'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 ID
  • AUTH_REQUIRED: Token gerekli
  • TOKEN_INVALID: Geçersiz veya süresi dolmuş token
  • USER_INVALID: Token geçerli bir kullanıcı içermiyor
  • STREAM_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 ID
  • NOT_IN_ROOM: Önce yayına katılmalısınız
  • EMPTY_CONTENT: Mesaj içeriği gerekli
  • SEND_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 ID
  • NOT_IN_ROOM: Önce yayına katılmalısınız
  • INVALID_REACTION_TYPE: Geçersiz reaksiyon tipi
  • SEND_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: guestRemovedDueToTimeout event'i gönderilir ve misafir yayından çıkarılır
    • Yayıncı için: hostOfflineTimeout event'i gönderilir ve yayın sonlandırılır

Davet Timeout

  • Davetler 30 saniye içinde kabul edilmezse otomatik olarak reddedilir
  • guestInviteExpired event'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ı

  1. Davet Süreci:

    • guestInviteacceptGuestInvite / rejectGuestInviteguestAccepted / guestRejected
  2. Yayın Katılımı:

    • joinStreamjoinedStreamguestAccepted (eğer misafir ise)
  3. Yayından Ayrılma:

    • leaveGuestStreamguestLeftuserOffline

Ö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ı

  1. JWT Token: /guest-stream ve /stream-chat namespace'leri JWT token gerektirir
  2. User ID Doğrulama: Tüm event'lerde user ID doğrulaması yapılır
  3. Stream ID Validation: Tüm stream ID'leri MongoDB ObjectId formatında olmalıdır
  4. 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]

On this page

Yayın Socket Event'leri DokümantasyonuİçindekilerGenel BakışNamespace'lerBase URL'lerLive Stream Status Namespace (/live-stream-status)BağlantıClient → Server Event'leri1. subscribe2. unsubscribeServer → Client Event'leri1. liveStreamScheduled2. liveStreamPreparing3. liveStreamStarted4. liveStreamEnded5. liveStreamExpired6. liveStreamCancelled7. liveStreamFundingProgress8. liveStreamFundingGoalReached9. liveStreamReadyToStartGuest Namespace (/guest)BağlantıClient → Server Event'leri1. acceptGuestInvite2. rejectGuestInviteServer → Client Event'leri1. guestInvite2. guestInviteAccepted3. guestInviteRejected4. guestInviteExpired5. inviteCanceled6. guestLeftNotification7. guestKicked8. errorGuest Stream Namespace (/guest-stream)BağlantıClient → Server Event'leri1. inviteGuest2. cancelInvite3. leaveGuestStream4. kickGuestServer → Client Event'leri1. joinedStream2. userReconnected3. userOffline4. guestInvitationBroadcast5. inviteCancelBroadcast6. guestAccepted7. onGuestJoined8. guestRejected9. guestInviteCanceled10. guestLeft11. guestKicked12. guestRemovedDueToTimeout13. hostOfflineTimeout14. errorLive Stream Namespace (/live-stream)BağlantıClient → Server Event'leri1. joinStream2. leaveStream3. joinOverview4. leaveOverviewServer → Client Event'leri1. joinedStream2. leftStream3. joinedOverview4. leftOverview5. viewerCountUpdatedgiftCountUpdated6. streamStarted7. streamEnded8. streamTimeExtensionAdded9. userBanned10. userBanRevoked11. userKickedFromStream12. joinStreamError13. leaveStreamError14. joinOverviewError15. leaveOverviewErrorStream Chat Namespace (/stream-chat)BağlantıClient → Server Event'leri1. joinStream2. leaveStream3. sendMessage4. sendReactionServer → Client Event'leri1. joinStreamSuccess2. leaveStreamSuccess3. newMessage4. sendMessageSuccess5. newReaction6. sendReactionSuccess7. joinStreamError6. sendMessageError8. sendReactionErrorOrtak TiplerUserSummaryDtoLiveStreamTimeExtensionResponseDtoEvent Payload TipleriJoin/Leave Stream ResponseStream Status EventsBan EventsUser Kicked EventError EventsÖnemli NotlarOffline Timeout MekanizmasıDavet TimeoutRoom YönetimiEvent SıralamasıÖrnek Kullanım SenaryolarıSenaryo 1: Misafir Davet SüreciSenaryo 2: Chat MesajlaşmasıSenaryo 3: Viewer Count TakibiHata YönetimiGüvenlik NotlarıVersiyonlamaDestek