fix vidsrc

This commit is contained in:
Jorrin
2023-12-25 22:51:55 +01:00
parent 82034b91ed
commit 64050df350
8 changed files with 27 additions and 58 deletions

View File

@@ -34,7 +34,7 @@ export function makeFullFetcher(fetcher: Fetcher): UseableFetcher {
query: ops?.query ?? {}, query: ops?.query ?? {},
baseUrl: ops?.baseUrl ?? '', baseUrl: ops?.baseUrl ?? '',
body: ops?.body, body: ops?.body,
returnRaw: ops?.returnRaw, returnRaw: ops?.returnRaw ?? false,
}); });
}; };
} }

View File

@@ -15,7 +15,7 @@ export type DefaultedFetcherOptions = {
headers: Record<string, string>; headers: Record<string, string>;
query: Record<string, string>; query: Record<string, string>;
method: 'HEAD' | 'GET' | 'POST'; method: 'HEAD' | 'GET' | 'POST';
returnRaw?: boolean; returnRaw: boolean;
}; };
export type Fetcher<T = any> = { export type Fetcher<T = any> = {

View File

@@ -91,6 +91,7 @@ export const streambucketScraper = makeEmbed({
type: 'hls', type: 'hls',
playlist: regexResult[1], playlist: regexResult[1],
flags: [flags.NO_CORS], flags: [flags.NO_CORS],
captions: [],
}, },
}; };
}, },

View File

@@ -1,8 +1,6 @@
import { flags } from '@/main/targets';
import { makeEmbed } from '@/providers/base'; import { makeEmbed } from '@/providers/base';
const hlsURLRegex = /var hls_url = "(.*?)";/; const hlsURLRegex = /file:"(.*?)"/;
const setPassRegex = /var path = "(.*set_pass\.php.*)";/;
export const vidsrcembedScraper = makeEmbed({ export const vidsrcembedScraper = makeEmbed({
id: 'vidsrcembed', // VidSrc is both a source and an embed host id: 'vidsrcembed', // VidSrc is both a source and an embed host
@@ -16,34 +14,21 @@ export const vidsrcembedScraper = makeEmbed({
headers: ctx.headers, headers: ctx.headers,
}); });
let regexResult = html.match(setPassRegex); const match = html
if (!regexResult) { .match(hlsURLRegex)?.[1]
throw new Error('Unable to find VidSrc set_pass.php link'); ?.replace(/(\/\/\S+?=)/g, '')
} .replace('#2', '');
if (!match) throw new Error('Unable to find HLS playlist');
const finalUrl = atob(match);
let setPassLink = regexResult[1]; if (!finalUrl.includes('.m3u8')) throw new Error('Unable to find HLS playlist');
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,
},
});
return { return {
stream: { stream: {
type: 'hls', type: 'hls',
playlist: regexResult[1], playlist: finalUrl,
flags: [flags.NO_CORS], flags: [],
captions: [],
}, },
}; };
}, },

View File

@@ -1,13 +1,2 @@
import { MovieMedia, ShowMedia } from '@/main/media';
import { ScrapeContext } from '@/utils/context';
export const vidsrcBase = 'https://vidsrc.me'; export const vidsrcBase = 'https://vidsrc.me';
export const vidsrcRCPBase = 'https://rcp.vidsrc.me'; export const vidsrcRCPBase = 'https://rcp.vidsrc.me';
export type MovieContext = ScrapeContext & {
media: MovieMedia;
};
export type ShowContext = ScrapeContext & {
media: ShowMedia;
};

View File

@@ -1,7 +1,7 @@
import { MovieContext } from '@/providers/sources/vidsrc/common';
import { getVidSrcMovieSources } from '@/providers/sources/vidsrc/scrape'; 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 { return {
embeds: await getVidSrcMovieSources(ctx), embeds: await getVidSrcMovieSources(ctx),
}; };

View File

@@ -1,7 +1,7 @@
import { ShowContext } from '@/providers/sources/vidsrc/common';
import { getVidSrcShowSources } from '@/providers/sources/vidsrc/scrape'; 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 { return {
embeds: await getVidSrcShowSources(ctx), embeds: await getVidSrcShowSources(ctx),
}; };

View File

@@ -1,9 +1,11 @@
import { load } from 'cheerio'; import { load } from 'cheerio';
import { FetchReply } from '@/fetchers/fetch'; import { FetchReply } from '@/fetchers/fetch';
import { SourcererEmbed } from '@/providers/base';
import { streambucketScraper } from '@/providers/embeds/streambucket'; import { streambucketScraper } from '@/providers/embeds/streambucket';
import { vidsrcembedScraper } from '@/providers/embeds/vidsrc'; 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) { function decodeSrc(encoded: string, seed: string) {
const encodedBuffer = Buffer.from(encoded, 'hex'); const encodedBuffer = Buffer.from(encoded, 'hex');
@@ -16,7 +18,7 @@ function decodeSrc(encoded: string, seed: string) {
return decoded; 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. // VidSrc works by using hashes and a redirect system.
// The hashes are stored in the html, and VidSrc will // The hashes are stored in the html, and VidSrc will
// make requests to their servers with the hash. This // 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 // real embed links, we must do the same. Slow, but
// required // required
const embeds: { const embeds: SourcererEmbed[] = [];
embedId: string;
url: string;
headers?: Record<string, string>;
}[] = [];
let html = await ctx.proxiedFetcher<string>(startingURL, { let html = await ctx.proxiedFetcher<string>(startingURL, {
baseUrl: vidsrcBase, baseUrl: vidsrcBase,
@@ -37,7 +35,7 @@ async function getVidSrcEmbeds(ctx: MovieContext | ShowContext, startingURL: str
let $ = load(html); let $ = load(html);
const sourceHashes = $('.source[data-hash]') const sourceHashes = $('.server[data-hash]')
.toArray() .toArray()
.map((el) => $(el).attr('data-hash')) .map((el) => $(el).attr('data-hash'))
.filter((hash) => hash !== undefined); .filter((hash) => hash !== undefined);
@@ -76,11 +74,7 @@ async function getVidSrcEmbeds(ctx: MovieContext | ShowContext, startingURL: str
}, },
}); });
const embed: { const embed: SourcererEmbed = {
embedId: string;
url: string;
headers?: Record<string, string>;
} = {
embedId: '', embedId: '',
url: embedURL, url: embedURL,
}; };
@@ -117,11 +111,11 @@ async function getVidSrcEmbeds(ctx: MovieContext | ShowContext, startingURL: str
return embeds; return embeds;
} }
export async function getVidSrcMovieSources(ctx: MovieContext) { export async function getVidSrcMovieSources(ctx: MovieScrapeContext) {
return getVidSrcEmbeds(ctx, `/embed/${ctx.media.tmdbId}`); 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 // VidSrc will always default to season 1 episode 1
// no matter what embed URL is used. It sends back // no matter what embed URL is used. It sends back
// a list of ALL the shows episodes, in order, for // a list of ALL the shows episodes, in order, for