mirror of
https://github.com/p-stream/providers.git
synced 2026-03-11 17:55:36 +00:00
use ext to proxy m3u8 streams with createM3U8ProxyUrl func
This commit is contained in:
parent
e0b924e6f5
commit
1f98cd3636
18 changed files with 59 additions and 25 deletions
|
|
@ -5,14 +5,14 @@ import { NotFoundError } from '@/utils/errors';
|
|||
import { createM3U8ProxyUrl, updateM3U8ProxyUrl } from '@/utils/proxy';
|
||||
|
||||
// REQUIRES A PROXY FOR MOST SERVERS set it up here https://github.com/Pasithea0/M3U8-Proxy
|
||||
function createProxyUrl(originalUrl: string, referer: string): string {
|
||||
function createProxyUrl(originalUrl: string, referer: string, features?: any): string {
|
||||
const headers = {
|
||||
referer,
|
||||
};
|
||||
return createM3U8ProxyUrl(originalUrl, headers);
|
||||
return createM3U8ProxyUrl(originalUrl, features, headers);
|
||||
}
|
||||
|
||||
function processProxiedURL(url: string): string {
|
||||
function processProxiedURL(url: string, ctx: MovieScrapeContext | ShowScrapeContext): string {
|
||||
// Handle orbitproxy URLs
|
||||
if (url.includes('orbitproxy')) {
|
||||
try {
|
||||
|
|
@ -25,7 +25,7 @@ function processProxiedURL(url: string): string {
|
|||
const originalUrl = jsonData.u;
|
||||
const referer = jsonData.r || '';
|
||||
|
||||
return createProxyUrl(originalUrl, referer);
|
||||
return createProxyUrl(originalUrl, referer, ctx.features);
|
||||
} catch (jsonError) {
|
||||
console.error('Error decoding/parsing orbitproxy data:', jsonError);
|
||||
}
|
||||
|
|
@ -85,7 +85,7 @@ async function comboScraper(ctx: ShowScrapeContext | MovieScrapeContext): Promis
|
|||
|
||||
const processedServers = servers.map((server) => ({
|
||||
...server,
|
||||
url: processProxiedURL(server.url),
|
||||
url: processProxiedURL(server.url, ctx),
|
||||
}));
|
||||
|
||||
const embeds: SourcererEmbed[] = processedServers.map((server) => ({
|
||||
|
|
|
|||
|
|
@ -123,7 +123,8 @@ export function makeCinemaOSHexaEmbed(id: string, rank: number = 100) {
|
|||
{
|
||||
id: 'primary',
|
||||
type: 'hls',
|
||||
playlist: createM3U8ProxyUrl(directUrl, headers),
|
||||
playlist: createM3U8ProxyUrl(directUrl, ctx.features, headers),
|
||||
headers,
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions: [],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -48,7 +48,8 @@ export const madplayBaseEmbed = makeEmbed({
|
|||
{
|
||||
id: 'primary',
|
||||
type: 'hls',
|
||||
playlist: createM3U8ProxyUrl(stream.file, headers),
|
||||
playlist: createM3U8ProxyUrl(stream.file, ctx.features, headers),
|
||||
headers,
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions: [],
|
||||
},
|
||||
|
|
@ -92,7 +93,8 @@ export const madplayNsapiEmbed = makeEmbed({
|
|||
{
|
||||
id: 'primary',
|
||||
type: 'hls',
|
||||
playlist: createM3U8ProxyUrl(stream.url, stream.headers || headers),
|
||||
playlist: createM3U8ProxyUrl(stream.url, ctx.features, stream.headers || headers),
|
||||
headers: stream.headers || headers,
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions: [],
|
||||
},
|
||||
|
|
@ -136,7 +138,8 @@ export const madplayRoperEmbed = makeEmbed({
|
|||
{
|
||||
id: 'primary',
|
||||
type: 'hls',
|
||||
playlist: createM3U8ProxyUrl(stream.url, stream.headers || headers),
|
||||
playlist: createM3U8ProxyUrl(stream.url, ctx.features, stream.headers || headers),
|
||||
headers: stream.headers || headers,
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions: [],
|
||||
},
|
||||
|
|
@ -180,7 +183,8 @@ export const madplayNsapiVidFastEmbed = makeEmbed({
|
|||
{
|
||||
id: 'primary',
|
||||
type: 'hls',
|
||||
playlist: createM3U8ProxyUrl(stream.url, stream.headers || headers),
|
||||
playlist: createM3U8ProxyUrl(stream.url, ctx.features, stream.headers || headers),
|
||||
headers: stream.headers || headers,
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions: [],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -33,9 +33,12 @@ export const myanimedubScraper = makeEmbed({
|
|||
{
|
||||
id: 'dub',
|
||||
type: 'hls',
|
||||
playlist: createM3U8ProxyUrl(streamData.results.streamingLink.link.file, {
|
||||
playlist: createM3U8ProxyUrl(streamData.results.streamingLink.link.file, ctx.features, {
|
||||
Referer: 'https://rapid-cloud.co/',
|
||||
}),
|
||||
headers: {
|
||||
Referer: 'https://rapid-cloud.co/',
|
||||
},
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions:
|
||||
(streamData.results.streamingLink.tracks
|
||||
|
|
|
|||
|
|
@ -33,9 +33,12 @@ export const myanimesubScraper = makeEmbed({
|
|||
{
|
||||
id: 'sub',
|
||||
type: 'hls',
|
||||
playlist: createM3U8ProxyUrl(streamData.results.streamingLink.link.file, {
|
||||
playlist: createM3U8ProxyUrl(streamData.results.streamingLink.link.file, ctx.features, {
|
||||
Referer: 'https://rapid-cloud.co/',
|
||||
}),
|
||||
headers: {
|
||||
Referer: 'https://rapid-cloud.co/',
|
||||
},
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions:
|
||||
(streamData.results.streamingLink.tracks
|
||||
|
|
|
|||
|
|
@ -224,7 +224,8 @@ function embed(provider: { id: string; name: string; rank: number }) {
|
|||
{
|
||||
id: 'primary',
|
||||
type: 'hls',
|
||||
playlist: createM3U8ProxyUrl(videoUrl, videoHeaders),
|
||||
playlist: createM3U8ProxyUrl(videoUrl, ctx.features, videoHeaders),
|
||||
headers: videoHeaders,
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions: [],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -94,7 +94,8 @@ export const turbovidScraper = makeEmbed({
|
|||
{
|
||||
type: 'hls',
|
||||
id: 'primary',
|
||||
playlist: createM3U8ProxyUrl(playlist, streamHeaders),
|
||||
playlist: createM3U8ProxyUrl(playlist, ctx.features, streamHeaders),
|
||||
headers: streamHeaders,
|
||||
flags: [],
|
||||
captions: [],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ export function makeVidifyEmbed(id: string, rank: number = 100) {
|
|||
playlist = decodeURIComponent(playlistUrl);
|
||||
} else {
|
||||
console.log(`Found normal stream: `, playlistUrl);
|
||||
playlist = createM3U8ProxyUrl(decodeURIComponent(playlistUrl), streamHeaders);
|
||||
playlist = createM3U8ProxyUrl(decodeURIComponent(playlistUrl), ctx.features, streamHeaders);
|
||||
}
|
||||
|
||||
ctx.progress(100);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ export const vidnestHollymoviehdEmbed = makeEmbed({
|
|||
streams.push({
|
||||
id: `hollymoviehd-${source.label}`,
|
||||
type: 'hls',
|
||||
playlist: createM3U8ProxyUrl(source.file),
|
||||
playlist: createM3U8ProxyUrl(source.file, ctx.features),
|
||||
headers: {},
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions: [],
|
||||
} as HlsBasedStream);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,8 @@ function makeVidSrcEmbed(provider: { id: string; name: string; rank: number }) {
|
|||
{
|
||||
id: 'primary',
|
||||
type: 'hls',
|
||||
playlist: createM3U8ProxyUrl(ctx.url, headers),
|
||||
playlist: createM3U8ProxyUrl(ctx.url, ctx.features, headers),
|
||||
headers,
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions: [],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ export const viperScraper = makeEmbed({
|
|||
{
|
||||
type: 'hls',
|
||||
id: 'primary',
|
||||
playlist: createM3U8ProxyUrl(playlistUrl, headers),
|
||||
playlist: createM3U8ProxyUrl(playlistUrl, ctx.features, headers),
|
||||
headers,
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions: [],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ async function comboScraper(ctx: ShowScrapeContext | MovieScrapeContext): Promis
|
|||
if (!apiRes.videoSource) throw new NotFoundError('No watchable item found');
|
||||
|
||||
let processedUrl = apiRes.videoSource;
|
||||
let streamHeaders: Record<string, string> = {};
|
||||
|
||||
if (processedUrl.includes('orbitproxy')) {
|
||||
try {
|
||||
const urlParts = processedUrl.split(/orbitproxy\.[^/]+\//);
|
||||
|
|
@ -31,8 +33,8 @@ async function comboScraper(ctx: ShowScrapeContext | MovieScrapeContext): Promis
|
|||
const originalUrl = jsonData.u;
|
||||
const referer = jsonData.r || '';
|
||||
|
||||
const headers = { referer };
|
||||
processedUrl = createM3U8ProxyUrl(originalUrl, headers);
|
||||
streamHeaders = { referer };
|
||||
processedUrl = createM3U8ProxyUrl(originalUrl, ctx.features, streamHeaders);
|
||||
} catch (jsonError) {
|
||||
console.error('Error decoding/parsing orbitproxy data:', jsonError);
|
||||
}
|
||||
|
|
@ -54,6 +56,7 @@ async function comboScraper(ctx: ShowScrapeContext | MovieScrapeContext): Promis
|
|||
captions: [],
|
||||
playlist: processedUrl,
|
||||
type: 'hls',
|
||||
headers: streamHeaders,
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ const universalScraper = async (ctx: ShowScrapeContext | MovieScrapeContext): Pr
|
|||
cookie: makeCookieHeader({ hd: 'on' }),
|
||||
};
|
||||
|
||||
const playlist = createM3U8ProxyUrl(`${baseUrl}${autoFile}`, headers);
|
||||
const playlist = createM3U8ProxyUrl(`${baseUrl}${autoFile}`, ctx.features, headers);
|
||||
ctx.progress(90);
|
||||
|
||||
return {
|
||||
|
|
@ -127,6 +127,7 @@ const universalScraper = async (ctx: ShowScrapeContext | MovieScrapeContext): Pr
|
|||
id: 'primary',
|
||||
playlist,
|
||||
type: 'hls',
|
||||
headers,
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions: [],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ const universalScraper = async (ctx: ShowScrapeContext | MovieScrapeContext): Pr
|
|||
cookie: makeCookieHeader({ hd: 'on' }),
|
||||
};
|
||||
|
||||
const playlist = createM3U8ProxyUrl(`${baseUrl}${autoFile}`, headers);
|
||||
const playlist = createM3U8ProxyUrl(`${baseUrl}${autoFile}`, ctx.features, headers);
|
||||
ctx.progress(90);
|
||||
|
||||
return {
|
||||
|
|
@ -124,6 +124,7 @@ const universalScraper = async (ctx: ShowScrapeContext | MovieScrapeContext): Pr
|
|||
id: 'primary',
|
||||
playlist,
|
||||
type: 'hls',
|
||||
headers,
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions: [],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ export async function scrapeInvidualSource(
|
|||
const contextBase: ScrapeContext = {
|
||||
fetcher: ops.fetcher,
|
||||
proxiedFetcher: ops.proxiedFetcher,
|
||||
features: ops.features,
|
||||
progress(val) {
|
||||
ops.events?.update?.({
|
||||
id: sourceScraper.id,
|
||||
|
|
@ -107,6 +108,7 @@ export async function scrapeIndividualEmbed(
|
|||
const output = await embedScraper.scrape({
|
||||
fetcher: ops.fetcher,
|
||||
proxiedFetcher: ops.proxiedFetcher,
|
||||
features: ops.features,
|
||||
url,
|
||||
progress(val) {
|
||||
ops.events?.update?.({
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ export async function runAllProviders(list: ProviderList, ops: ProviderRunnerOpt
|
|||
const contextBase: ScrapeContext = {
|
||||
fetcher: ops.fetcher,
|
||||
proxiedFetcher: ops.proxiedFetcher,
|
||||
features: ops.features,
|
||||
progress(val) {
|
||||
ops.events?.update?.({
|
||||
id: lastId,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
import { MovieMedia, ShowMedia } from '@/entrypoint/utils/media';
|
||||
import { FeatureMap } from '@/entrypoint/utils/targets';
|
||||
import { UseableFetcher } from '@/fetchers/types';
|
||||
|
||||
export type ScrapeContext = {
|
||||
proxiedFetcher: UseableFetcher;
|
||||
fetcher: UseableFetcher;
|
||||
progress(val: number): void;
|
||||
features: FeatureMap;
|
||||
};
|
||||
|
||||
export type EmbedInput = {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { flags } from '@/entrypoint/utils/targets';
|
||||
import { FeatureMap, flags } from '@/entrypoint/utils/targets';
|
||||
import { Stream } from '@/providers/streams';
|
||||
|
||||
// Default proxy URL for general purpose proxying
|
||||
|
|
@ -67,10 +67,18 @@ export function setupProxy(stream: Stream): Stream {
|
|||
/**
|
||||
* Creates a proxied M3U8 URL using the configured M3U8 proxy
|
||||
* @param url - The original M3U8 URL to proxy
|
||||
* @param features - Feature map to determine if local proxy (extension/native) is available
|
||||
* @param headers - Headers to include with the request
|
||||
* @returns The proxied M3U8 URL
|
||||
* @returns The proxied M3U8 URL or original URL if local proxy is available
|
||||
*/
|
||||
export function createM3U8ProxyUrl(url: string, headers: Record<string, string> = {}): string {
|
||||
export function createM3U8ProxyUrl(url: string, features?: FeatureMap, headers: Record<string, string> = {}): string {
|
||||
// If we have features and local proxy is available (no CORS restrictions), return original URL
|
||||
// The stream headers will handle the proxying through the extension/native environment
|
||||
if (features && !features.requires.includes(flags.CORS_ALLOWED)) {
|
||||
return url;
|
||||
}
|
||||
|
||||
// Otherwise, use the external M3U8 proxy
|
||||
const encodedUrl = encodeURIComponent(url);
|
||||
const encodedHeaders = encodeURIComponent(JSON.stringify(headers));
|
||||
return `${CONFIGURED_M3U8_PROXY_URL}/m3u8-proxy?url=${encodedUrl}${headers ? `&headers=${encodedHeaders}` : ''}`;
|
||||
|
|
|
|||
Loading…
Reference in a new issue