diff --git a/src/fetchers/common.ts b/src/fetchers/common.ts index dff6978..a2b77aa 100644 --- a/src/fetchers/common.ts +++ b/src/fetchers/common.ts @@ -34,7 +34,7 @@ export function makeFullFetcher(fetcher: Fetcher): UseableFetcher { query: ops?.query ?? {}, baseUrl: ops?.baseUrl ?? '', body: ops?.body, - returnRaw: ops?.returnRaw, + returnRaw: ops?.returnRaw ?? false, }); }; } diff --git a/src/fetchers/types.ts b/src/fetchers/types.ts index 1ad3092..8e581a6 100644 --- a/src/fetchers/types.ts +++ b/src/fetchers/types.ts @@ -15,7 +15,7 @@ export type DefaultedFetcherOptions = { headers: Record; query: Record; method: 'HEAD' | 'GET' | 'POST'; - returnRaw?: boolean; + returnRaw: boolean; }; export type Fetcher = { diff --git a/src/providers/embeds/streambucket.ts b/src/providers/embeds/streambucket.ts index a3d2689..f137ceb 100644 --- a/src/providers/embeds/streambucket.ts +++ b/src/providers/embeds/streambucket.ts @@ -91,6 +91,7 @@ export const streambucketScraper = makeEmbed({ type: 'hls', playlist: regexResult[1], flags: [flags.NO_CORS], + captions: [], }, }; }, diff --git a/src/providers/embeds/vidsrc.ts b/src/providers/embeds/vidsrc.ts index 3e025b6..da3f2aa 100644 --- a/src/providers/embeds/vidsrc.ts +++ b/src/providers/embeds/vidsrc.ts @@ -1,8 +1,6 @@ -import { flags } from '@/main/targets'; import { makeEmbed } from '@/providers/base'; -const hlsURLRegex = /var hls_url = "(.*?)";/; -const setPassRegex = /var path = "(.*set_pass\.php.*)";/; +const hlsURLRegex = /file:"(.*?)"/; export const vidsrcembedScraper = makeEmbed({ id: 'vidsrcembed', // VidSrc is both a source and an embed host @@ -16,34 +14,21 @@ export const vidsrcembedScraper = makeEmbed({ headers: ctx.headers, }); - let regexResult = html.match(setPassRegex); - if (!regexResult) { - throw new Error('Unable to find VidSrc set_pass.php link'); - } + const match = html + .match(hlsURLRegex)?.[1] + ?.replace(/(\/\/\S+?=)/g, '') + .replace('#2', ''); + if (!match) throw new Error('Unable to find HLS playlist'); + const finalUrl = atob(match); - let setPassLink = regexResult[1]; - - if (setPassLink.startsWith('//')) { - setPassLink = `https:${setPassLink}`; - } - - regexResult = html.match(hlsURLRegex); - if (!regexResult) { - throw new Error('Unable to find VidSrc HLS stream'); - } - - // Must call set_pass.php BEFORE using the stream - await fetch(setPassLink, { - headers: { - referer: ctx.url, - }, - }); + if (!finalUrl.includes('.m3u8')) throw new Error('Unable to find HLS playlist'); return { stream: { type: 'hls', - playlist: regexResult[1], - flags: [flags.NO_CORS], + playlist: finalUrl, + flags: [], + captions: [], }, }; }, diff --git a/src/providers/sources/vidsrc/common.ts b/src/providers/sources/vidsrc/common.ts index 6f8d773..4ccc93c 100644 --- a/src/providers/sources/vidsrc/common.ts +++ b/src/providers/sources/vidsrc/common.ts @@ -1,13 +1,2 @@ -import { MovieMedia, ShowMedia } from '@/main/media'; -import { ScrapeContext } from '@/utils/context'; - export const vidsrcBase = 'https://vidsrc.me'; export const vidsrcRCPBase = 'https://rcp.vidsrc.me'; - -export type MovieContext = ScrapeContext & { - media: MovieMedia; -}; - -export type ShowContext = ScrapeContext & { - media: ShowMedia; -}; diff --git a/src/providers/sources/vidsrc/scrape-movie.ts b/src/providers/sources/vidsrc/scrape-movie.ts index 7e0a796..585eb31 100644 --- a/src/providers/sources/vidsrc/scrape-movie.ts +++ b/src/providers/sources/vidsrc/scrape-movie.ts @@ -1,7 +1,7 @@ -import { MovieContext } from '@/providers/sources/vidsrc/common'; import { getVidSrcMovieSources } from '@/providers/sources/vidsrc/scrape'; +import { MovieScrapeContext } from '@/utils/context'; -export async function scrapeMovie(ctx: MovieContext) { +export async function scrapeMovie(ctx: MovieScrapeContext) { return { embeds: await getVidSrcMovieSources(ctx), }; diff --git a/src/providers/sources/vidsrc/scrape-show.ts b/src/providers/sources/vidsrc/scrape-show.ts index 7214332..ff5d2a4 100644 --- a/src/providers/sources/vidsrc/scrape-show.ts +++ b/src/providers/sources/vidsrc/scrape-show.ts @@ -1,7 +1,7 @@ -import { ShowContext } from '@/providers/sources/vidsrc/common'; import { getVidSrcShowSources } from '@/providers/sources/vidsrc/scrape'; +import { ShowScrapeContext } from '@/utils/context'; -export async function scrapeShow(ctx: ShowContext) { +export async function scrapeShow(ctx: ShowScrapeContext) { return { embeds: await getVidSrcShowSources(ctx), }; diff --git a/src/providers/sources/vidsrc/scrape.ts b/src/providers/sources/vidsrc/scrape.ts index a8aa4fc..6ea5256 100644 --- a/src/providers/sources/vidsrc/scrape.ts +++ b/src/providers/sources/vidsrc/scrape.ts @@ -1,9 +1,11 @@ import { load } from 'cheerio'; import { FetchReply } from '@/fetchers/fetch'; +import { SourcererEmbed } from '@/providers/base'; import { streambucketScraper } from '@/providers/embeds/streambucket'; import { vidsrcembedScraper } from '@/providers/embeds/vidsrc'; -import { MovieContext, ShowContext, vidsrcBase, vidsrcRCPBase } from '@/providers/sources/vidsrc/common'; +import { vidsrcBase, vidsrcRCPBase } from '@/providers/sources/vidsrc/common'; +import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context'; function decodeSrc(encoded: string, seed: string) { const encodedBuffer = Buffer.from(encoded, 'hex'); @@ -16,7 +18,7 @@ function decodeSrc(encoded: string, seed: string) { return decoded; } -async function getVidSrcEmbeds(ctx: MovieContext | ShowContext, startingURL: string) { +async function getVidSrcEmbeds(ctx: MovieScrapeContext | ShowScrapeContext, startingURL: string) { // VidSrc works by using hashes and a redirect system. // The hashes are stored in the html, and VidSrc will // make requests to their servers with the hash. This @@ -25,11 +27,7 @@ async function getVidSrcEmbeds(ctx: MovieContext | ShowContext, startingURL: str // real embed links, we must do the same. Slow, but // required - const embeds: { - embedId: string; - url: string; - headers?: Record; - }[] = []; + const embeds: SourcererEmbed[] = []; let html = await ctx.proxiedFetcher(startingURL, { baseUrl: vidsrcBase, @@ -37,7 +35,7 @@ async function getVidSrcEmbeds(ctx: MovieContext | ShowContext, startingURL: str let $ = load(html); - const sourceHashes = $('.source[data-hash]') + const sourceHashes = $('.server[data-hash]') .toArray() .map((el) => $(el).attr('data-hash')) .filter((hash) => hash !== undefined); @@ -76,11 +74,7 @@ async function getVidSrcEmbeds(ctx: MovieContext | ShowContext, startingURL: str }, }); - const embed: { - embedId: string; - url: string; - headers?: Record; - } = { + const embed: SourcererEmbed = { embedId: '', url: embedURL, }; @@ -117,11 +111,11 @@ async function getVidSrcEmbeds(ctx: MovieContext | ShowContext, startingURL: str return embeds; } -export async function getVidSrcMovieSources(ctx: MovieContext) { +export async function getVidSrcMovieSources(ctx: MovieScrapeContext) { return getVidSrcEmbeds(ctx, `/embed/${ctx.media.tmdbId}`); } -export async function getVidSrcShowSources(ctx: ShowContext) { +export async function getVidSrcShowSources(ctx: ShowScrapeContext) { // VidSrc will always default to season 1 episode 1 // no matter what embed URL is used. It sends back // a list of ALL the shows episodes, in order, for