mirror of
https://github.com/movie-web/providers.git
synced 2025-09-13 12:43:25 +00:00
fix vidsrc
This commit is contained in:
@@ -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,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -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> = {
|
||||||
|
@@ -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: [],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@@ -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: [],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@@ -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;
|
|
||||||
};
|
|
||||||
|
@@ -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),
|
||||||
};
|
};
|
||||||
|
@@ -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),
|
||||||
};
|
};
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user