(function () { 'use strict'; async function request(path, params) { const url = new URL(SR.config.getBase() + path); if (params) { for (const [key, value] of Object.entries(params)) { if (value === undefined || value === null || value === '') continue; url.searchParams.set(key, String(value)); } } let res; try { res = await fetch(url.toString()); } catch (e) { throw new Error(`cannot reach the API at ${SR.config.getBase()} — check the base URL in Settings`); } let data = null; try { data = await res.json(); } catch (e) { /* non-JSON body */ } if (!res.ok) { throw new Error((data && data.error) || `API error: HTTP ${res.status}`); } return data; } // route a media/subtitle URL through the API proxy (CORS, headers, m3u8 rewrite) function proxyUrl(target, headers) { const q = new URLSearchParams(); q.set('url', target); q.set('h', JSON.stringify(headers || {})); return SR.config.getBase() + '/proxy/media?' + q.toString(); } window.SR = window.SR || {}; SR.api = { request, proxyUrl, search: (q) => request('/search', { q }), trending: (type, timeWindow) => request('/trending', { type, window: timeWindow }), details: (type, id) => request(`/${type}/${id}`), seasons: (id) => request(`/tv/${id}/seasons`), episodes: (id, season) => request(`/tv/${id}/seasons/${season}`), streams: ({ tmdb, type, season, episode }) => request('/streams', { tmdb, type, season, episode }), }; })();