Live Stream history — mobil ve web
Geçmiş yayınlar client entegrasyonu
Live Stream History - Mobile/Web Integration
Migration rehberi
Yapılandırma sırası için Migration şablonu. Yeni düzenlemelerde Amaç → Önkoşullar → Endpoint → Request/Response → Hata kodları → Client adımları → İlgili sayfalar bölümlerini tercih edin.
Endpointler
GET /api/v1/live-stream/my-broadcasted-streamsGET /api/v1/live-stream/my-watched-streams- Auth:
Authorization: Bearer <JWT>zorunlu
Kapsam
my-broadcasted-streams:
- Kullanıcının
hostveyaguestolarak katıldığı geçmiş yayınları döner. - Response item
rolealanı matched participant rolüne görehostveyaguestolur.
my-watched-streams:
- Kullanıcının
audienceolarak izlediği geçmiş yayınları döner. - Response item
rolealanıaudienceolur.
Ortak davranış:
- Sadece
status = endedyayınlar döner. - Soft-deleted yayınlar dönmez.
- Aynı yayına tekrar giriş yapılmışsa tek item döner.
recordingUrl,recordingveya profil replay görünürlüğü filtresi uygulanmaz.- Harcama/kazanç bilgisi bu endpointlerde dönmez.
History Kaydi Nasil Olusur?
History listeleri backend tarafındaki Participant kayıtlarından beslenir.
Bir yayın izleme geçmişine düşmesi için kullanıcı yayına authenticated olarak katılmalıdır:
- REST:
POST /api/v1/live-stream/join - Socket:
/live-streamnamespacejoinStream - Socket:
/stream-chatnamespacejoinStream
Socket bağlantılarında JWT gönderilmezse kullanıcı odaya katılsa bile kişisel watched history için participant kaydı yazılmaz.
Query
page?: number // default: 1, min: 1
limit?: number // default: 10, min: 1, max: 100Örnek:
GET /api/v1/live-stream/my-broadcasted-streams?page=1&limit=10
GET /api/v1/live-stream/my-watched-streams?page=2&limit=20Response
Backend standart BaseResponseDto<T> wrapper döner. Asıl payload data içindedir.
Response shape GET /api/v1/live-stream/whats-live-now ile aynıdır: data.list içinde LiveStreamResponseDto[], data.pagination içinde pagination metadata döner.
{
"isSuccess": true,
"statusCode": 200,
"data": {
"list": [
{
"id": "65f000000000000000000001",
"title": "Yayin basligi",
"liveStreamType": "solo",
"channelName": "channel-name",
"broadcasters": [],
"guests": [],
"creator": {
"_id": "65f000000000000000000010",
"username": "creator",
"name": "Creator",
"surname": "User",
"profilePhoto": null
},
"thumbnailUrl": null,
"recording": false,
"recordingUrl": null,
"status": "ended",
"accessType": "free",
"price": 0,
"interest": "music",
"durationGoal": null,
"motivation": null,
"isActiveReplayOnCreatorProfile": null,
"replayCreditPrice": null,
"startedAt": "2026-05-01T12:00:00.000Z",
"plannedStartDate": null,
"endedAt": "2026-05-01T12:30:00.000Z",
"plannedEndDate": null,
"createdAt": "2026-05-01T11:50:00.000Z",
"updatedAt": "2026-05-01T12:30:00.000Z",
"fundingGoal": null,
"collectedFunding": null,
"fundingPercentage": null,
"role": "host",
"miniCrowdFundings": []
}
],
"pagination": {
"currentPage": 1,
"totalPages": 1,
"totalItems": 1,
"itemsPerPage": 10,
"hasNextPage": false,
"hasPrevPage": false
}
},
"errors": [],
"timestamp": "2026-05-11T07:00:00.000Z"
}TypeScript Tipleri
type LiveStreamRole = 'host' | 'guest' | 'audience' | null;
type Pagination = {
currentPage: number;
totalPages: number;
totalItems: number;
itemsPerPage: number;
hasNextPage: boolean;
hasPrevPage: boolean;
};
type PaginatedResponse<T> = {
list: T[];
pagination: Pagination;
};
type BaseResponseDto<T> = {
isSuccess: boolean;
statusCode: number;
data: T;
errors?: string[];
timestamp: string;
};
type LiveStreamHistoryItem = {
id: string;
title: string;
liveStreamType: 'solo' | 'duoself' | 'duocrowd';
channelName: string;
status: 'ended';
accessType: 'free' | 'paid';
role: LiveStreamRole;
creator: unknown | null;
guests: unknown[];
broadcasters: unknown[];
thumbnailUrl?: string | null;
recording: boolean;
recordingUrl?: string | null;
startedAt?: string | null;
endedAt?: string | null;
createdAt: string;
updatedAt: string;
};
type LiveStreamHistoryResponse = PaginatedResponse<LiveStreamHistoryItem>;Not: LiveStreamHistoryItem aslında mevcut LiveStreamResponseDto ile aynıdır. Uygulamada zaten ortak live stream type varsa onu kullanın.
RTK Query Ornegi
Base API baseUrl değeri /api ise endpoint URL'leri /v1/... olarak kullanılır.
import { baseApi } from './baseApi';
type BaseResponseDto<T> = { data: T };
type Pagination = {
currentPage: number;
totalPages: number;
totalItems: number;
itemsPerPage: number;
hasNextPage: boolean;
hasPrevPage: boolean;
};
type PaginatedResponse<T> = {
list: T[];
pagination: Pagination;
};
type LiveStreamHistoryItem = {
id: string;
title: string;
status: 'ended';
role: 'host' | 'guest' | 'audience' | null;
thumbnailUrl?: string | null;
startedAt?: string | null;
endedAt?: string | null;
};
type HistoryQuery = {
page?: number;
limit?: number;
};
const unwrap = <T>(response: BaseResponseDto<T> | T): T =>
response && typeof response === 'object' && 'data' in response
? (response as BaseResponseDto<T>).data
: (response as T);
export const liveStreamHistoryApi = baseApi.injectEndpoints({
endpoints: (builder) => ({
getMyBroadcastedStreams: builder.query<
PaginatedResponse<LiveStreamHistoryItem>,
HistoryQuery | void
>({
query: (params) => ({
url: '/v1/live-stream/my-broadcasted-streams',
method: 'GET',
params: {
page: params?.page ?? 1,
limit: params?.limit ?? 10,
},
}),
transformResponse: (
response: BaseResponseDto<PaginatedResponse<LiveStreamHistoryItem>>,
) => unwrap(response),
}),
getMyWatchedStreams: builder.query<
PaginatedResponse<LiveStreamHistoryItem>,
HistoryQuery | void
>({
query: (params) => ({
url: '/v1/live-stream/my-watched-streams',
method: 'GET',
params: {
page: params?.page ?? 1,
limit: params?.limit ?? 10,
},
}),
transformResponse: (
response: BaseResponseDto<PaginatedResponse<LiveStreamHistoryItem>>,
) => unwrap(response),
}),
}),
});
export const {
useGetMyBroadcastedStreamsQuery,
useGetMyWatchedStreamsQuery,
} = liveStreamHistoryApi;Web Fetch Ornegi
async function getMyWatchedStreams(token: string, page = 1, limit = 10) {
const params = new URLSearchParams({
page: String(page),
limit: String(limit),
});
const response = await fetch(`/api/v1/live-stream/my-watched-streams?${params}`, {
headers: {
Authorization: `Bearer ${token}`,
},
});
if (!response.ok) {
throw new Error(`History request failed: ${response.status}`);
}
const body = await response.json();
return body.data as PaginatedResponse<LiveStreamHistoryItem>;
}UI Notlari
- Broadcasted tab:
my-broadcasted-streams - Watched tab:
my-watched-streams - Empty state:
- Broadcasted: kullanıcının host/guest olarak bitmiş yayını yoktur.
- Watched: kullanıcının audience olarak bitmiş yayını yoktur.
- Infinite scroll için
pagination.hasNextPagekullanılmalı. - Pull-to-refresh için
page=1tekrar çekilmeli. - Harcama/kazanç gösterimi bu endpointlerden beklenmemeli.