import { load } from 'cheerio'; import { flags } from '@/entrypoint/utils/targets'; import { SourcererOutput, makeSourcerer } from '@/providers/base'; import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context'; import { NotFoundError } from '@/utils/errors'; const baseUrl = 'https://pupp.slidemovies-dev.workers.dev'; async function comboScraper(ctx: ShowScrapeContext | MovieScrapeContext): Promise { const watchPageUrl = ctx.media.type === 'movie' ? `${baseUrl}/movie/${ctx.media.tmdbId}` : `${baseUrl}/tv/${ctx.media.tmdbId}/${ctx.media.season.number}/-${ctx.media.episode.number}`; ctx.progress(60); const watchPage = await ctx.proxiedFetcher(watchPageUrl); const $ = load(watchPage); const proxiedStreamUrl = $('media-player').attr('src'); if (!proxiedStreamUrl) { throw new NotFoundError('Stream URL not found'); } const isoLanguageMap: Record = { ng: 'en', re: 'fr', pa: 'es', }; const captions = $('media-provider track') .map((_, el) => { const url = $(el).attr('src') || ''; const rawLang = $(el).attr('lang') || 'unknown'; const languageCode = isoLanguageMap[rawLang] || rawLang; const isVtt = url.endsWith('.vtt') ? 'vtt' : 'srt'; return { type: isVtt as 'vtt' | 'srt', id: url, url, language: languageCode, hasCorsRestrictions: false, }; }) .get(); ctx.progress(90); return { embeds: [], stream: [ { id: 'primary', type: 'hls', flags: [], playlist: proxiedStreamUrl, captions, }, ], }; } export const slidemoviesScraper = makeSourcerer({ id: 'slidemovies', name: 'SlideMovies', rank: 181, disabled: false, flags: [flags.CORS_ALLOWED], scrapeMovie: comboScraper, scrapeShow: comboScraper, });