vidrip/frontend/src/services/api.ts

139 lines
3.6 KiB
TypeScript

import { Channel, Playlist, Video, Config, SchedulerStatus } from '../types';
const API_BASE = '/api';
async function fetchJSON<T>(url: string, options?: RequestInit): Promise<T> {
const response = await fetch(url, {
...options,
headers: {
'Content-Type': 'application/json',
...options?.headers,
},
});
if (!response.ok) {
const error = await response.json().catch(() => ({ error: 'Request failed' }));
throw new Error(error.error || `HTTP ${response.status}`);
}
if (response.status === 204) {
return {} as T;
}
return response.json();
}
// Channels API
export const channelsAPI = {
getAll: () => fetchJSON<Channel[]>(`${API_BASE}/channels`),
getById: (id: number) => fetchJSON<Channel>(`${API_BASE}/channels/${id}`),
getVideos: (id: number) => fetchJSON<Video[]>(`${API_BASE}/channels/${id}/videos`),
create: (url: string) =>
fetchJSON<Channel>(`${API_BASE}/channels`, {
method: 'POST',
body: JSON.stringify({ url }),
}),
update: (id: number, active: boolean) =>
fetchJSON<Channel>(`${API_BASE}/channels/${id}`, {
method: 'PATCH',
body: JSON.stringify({ active }),
}),
delete: (id: number) =>
fetchJSON<void>(`${API_BASE}/channels/${id}`, {
method: 'DELETE',
}),
refresh: (id: number) =>
fetchJSON<{ message: string }>(`${API_BASE}/channels/${id}/refresh`, {
method: 'POST',
}),
};
// Playlists API
export const playlistsAPI = {
getAll: () => fetchJSON<Playlist[]>(`${API_BASE}/playlists`),
getById: (id: number) => fetchJSON<Playlist>(`${API_BASE}/playlists/${id}`),
getVideos: (id: number) => fetchJSON<Video[]>(`${API_BASE}/playlists/${id}/videos`),
create: (url: string) =>
fetchJSON<Playlist>(`${API_BASE}/playlists`, {
method: 'POST',
body: JSON.stringify({ url }),
}),
update: (id: number, active: boolean) =>
fetchJSON<Playlist>(`${API_BASE}/playlists/${id}`, {
method: 'PATCH',
body: JSON.stringify({ active }),
}),
delete: (id: number) =>
fetchJSON<void>(`${API_BASE}/playlists/${id}`, {
method: 'DELETE',
}),
refresh: (id: number) =>
fetchJSON<{ message: string }>(`${API_BASE}/playlists/${id}/refresh`, {
method: 'POST',
}),
};
// Videos API
export const videosAPI = {
getAll: (status?: string, search?: string) => {
const params = new URLSearchParams();
if (status) params.append('status', status);
if (search) params.append('search', search);
const queryString = params.toString();
const url = queryString
? `${API_BASE}/videos?${queryString}`
: `${API_BASE}/videos`;
return fetchJSON<Video[]>(url);
},
getById: (id: number) => fetchJSON<Video>(`${API_BASE}/videos/${id}`),
create: (url: string) =>
fetchJSON<Video>(`${API_BASE}/videos`, {
method: 'POST',
body: JSON.stringify({ url }),
}),
delete: (id: number) =>
fetchJSON<void>(`${API_BASE}/videos/${id}`, {
method: 'DELETE',
}),
retry: (id: number) =>
fetchJSON<Video>(`${API_BASE}/videos/${id}/retry`, {
method: 'POST',
}),
downloadNow: (id: number) =>
fetchJSON<{ message: string; videoId: string }>(`${API_BASE}/videos/${id}/download`, {
method: 'POST',
}),
};
// Config API
export const configAPI = {
get: () => fetchJSON<Config>(`${API_BASE}/config`),
update: (config: Partial<Config>) =>
fetchJSON<Config>(`${API_BASE}/config`, {
method: 'PATCH',
body: JSON.stringify(config),
}),
getSchedulerStatus: () =>
fetchJSON<SchedulerStatus>(`${API_BASE}/config/scheduler/status`),
};