mirror of
https://github.com/p-stream/providers.git
synced 2026-04-19 11:22:05 +00:00
add m3u8 proxy rotation
This commit is contained in:
parent
fbe0abcd4a
commit
e3c8cab4cc
11 changed files with 106 additions and 46 deletions
|
|
@ -19,3 +19,4 @@ export { getBuiltinEmbeds, getBuiltinSources, getBuiltinExternalSources } from '
|
|||
export { makeStandardFetcher } from '@/fetchers/standardFetch';
|
||||
export { makeSimpleProxyFetcher } from '@/fetchers/simpleProxy';
|
||||
export { flags, targets } from '@/entrypoint/utils/targets';
|
||||
export { setM3U8ProxyUrl, getM3U8ProxyUrl, createM3U8ProxyUrl, updateM3U8ProxyUrl } from '@/utils/proxy';
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { flags } from '@/entrypoint/utils/targets';
|
|||
import { SourcererEmbed, SourcererOutput, makeSourcerer } from '@/providers/base';
|
||||
import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context';
|
||||
import { NotFoundError } from '@/utils/errors';
|
||||
import { createM3U8ProxyUrl, updateM3U8ProxyUrl } from '@/utils/proxy';
|
||||
|
||||
const baseUrl = 'https://rivestream.org';
|
||||
|
||||
|
|
@ -77,14 +78,10 @@ function generateSecretKey(id: number | string) {
|
|||
}
|
||||
|
||||
function createProxyUrl(originalUrl: string, referer: string): string {
|
||||
const encodedUrl = encodeURIComponent(originalUrl);
|
||||
const encodedHeaders = encodeURIComponent(
|
||||
JSON.stringify({
|
||||
referer,
|
||||
}),
|
||||
);
|
||||
|
||||
return `https://proxy.fifthwit.net/m3u8-proxy?url=${encodedUrl}&headers=${encodedHeaders}`;
|
||||
const headers = {
|
||||
referer,
|
||||
};
|
||||
return createM3U8ProxyUrl(originalUrl, headers);
|
||||
}
|
||||
|
||||
function processProxiedURL(url: string): string {
|
||||
|
|
@ -112,7 +109,7 @@ function processProxiedURL(url: string): string {
|
|||
|
||||
// Handle other proxied URLs
|
||||
if (url.includes('/m3u8-proxy?url=')) {
|
||||
return url.replace(/https:\/\/[^/]+\/m3u8-proxy/, 'https://proxy.fifthwit.net/m3u8-proxy');
|
||||
return updateM3U8ProxyUrl(url);
|
||||
}
|
||||
|
||||
return url;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import { flags } from '@/entrypoint/utils/targets';
|
||||
import { EmbedOutput, makeEmbed } from '@/providers/base';
|
||||
import { NotFoundError } from '@/utils/errors';
|
||||
import { createM3U8ProxyUrl, updateM3U8ProxyUrl } from '@/utils/proxy';
|
||||
|
||||
const baseUrl = 'https://flix.1anime.app';
|
||||
|
||||
|
|
@ -37,14 +38,12 @@ const languageMap: Record<string, string> = {
|
|||
};
|
||||
|
||||
function createProxyUrl(originalUrl: string, referer?: string): string {
|
||||
const encodedUrl = encodeURIComponent(originalUrl);
|
||||
const encodedHeaders = encodeURIComponent(
|
||||
JSON.stringify({
|
||||
referer,
|
||||
}),
|
||||
);
|
||||
const headers: Record<string, string> = {};
|
||||
if (referer) {
|
||||
headers.referer = referer;
|
||||
}
|
||||
|
||||
return `https://m3u8.moonpic.qzz.io/m3u8-proxy?url=${encodedUrl}&headers=${encodedHeaders}`;
|
||||
return createM3U8ProxyUrl(originalUrl, headers);
|
||||
}
|
||||
|
||||
function processProxiedURL(url: string): string {
|
||||
|
|
@ -76,7 +75,7 @@ function processProxiedURL(url: string): string {
|
|||
|
||||
// Handle other proxied URLs
|
||||
if (url.includes('/m3u8-proxy?url=')) {
|
||||
return url.replace(/https:\/\/[^/]+\/m3u8-proxy/, 'https://vidproxy.devoplx.com/m3u8-proxy');
|
||||
return updateM3U8ProxyUrl(url);
|
||||
}
|
||||
|
||||
return createProxyUrl(url);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import { flags } from '@/entrypoint/utils/targets';
|
||||
import { EmbedOutput, makeEmbed } from '@/providers/base';
|
||||
import { NotFoundError } from '@/utils/errors';
|
||||
import { createM3U8ProxyUrl } from '@/utils/proxy';
|
||||
|
||||
import { Caption } from '../captions';
|
||||
|
||||
|
|
@ -123,12 +124,20 @@ function embed(provider: { id: string; rank: number; name: string; server: strin
|
|||
|
||||
ctx.progress(90);
|
||||
|
||||
const headers: Record<string, string> = {};
|
||||
if (data.headers.Referer) {
|
||||
headers.referer = data.headers.Referer;
|
||||
}
|
||||
if (data.headers.Origin) {
|
||||
headers.origin = data.headers.Origin;
|
||||
}
|
||||
|
||||
return {
|
||||
stream: [
|
||||
{
|
||||
id: 'primary',
|
||||
captions,
|
||||
playlist: `https://vidproxy.devoplx.com/m3u8-proxy?url=${encodeURIComponent(streams.unknown)}&headers=${encodeURIComponent(JSON.stringify({ ...(data.headers.Referer && { referer: data.headers.Referer }), ...(data.headers.Origin && { origin: data.headers.Origin }) }))}`,
|
||||
playlist: createM3U8ProxyUrl(streams.unknown, headers),
|
||||
type: 'hls',
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
...(thumbnailTrack && {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { flags } from '@/entrypoint/utils/targets';
|
||||
import { EmbedOutput, makeEmbed } from '@/providers/base';
|
||||
import { NotFoundError } from '@/utils/errors';
|
||||
import { createM3U8ProxyUrl } from '@/utils/proxy';
|
||||
|
||||
export const hianimeHd1DubEmbed = makeEmbed({
|
||||
id: 'hianime-hd1-dub',
|
||||
|
|
@ -21,7 +22,7 @@ export const hianimeHd1DubEmbed = makeEmbed({
|
|||
{
|
||||
type: 'hls',
|
||||
id: 'primary',
|
||||
playlist: `https://vidproxy.devoplx.com/m3u8-proxy?url=${data.data.sources[0].url}&headers=${encodeURIComponent(JSON.stringify(data.data.headers))}`,
|
||||
playlist: createM3U8ProxyUrl(data.data.sources[0].url, data.data.headers),
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions: [],
|
||||
...(thumbnailTrack
|
||||
|
|
@ -57,7 +58,7 @@ export const hianimeHd2DubEmbed = makeEmbed({
|
|||
{
|
||||
type: 'hls',
|
||||
id: 'primary',
|
||||
playlist: `https://m3u8.moonpic.qzz.io/m3u8-proxy?url=${data.data.sources[0].url}&headers=${encodeURIComponent(JSON.stringify(data.data.headers))}`,
|
||||
playlist: createM3U8ProxyUrl(data.data.sources[0].url, data.data.headers),
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions: [],
|
||||
...(thumbnailTrack
|
||||
|
|
@ -93,7 +94,7 @@ export const hianimeHd1SubEmbed = makeEmbed({
|
|||
{
|
||||
type: 'hls',
|
||||
id: 'primary',
|
||||
playlist: `https://proxy-m3u8.uira.live/m3u8-proxy?url=${data.data.sources[0].url}&headers=${encodeURIComponent(JSON.stringify(data.data.headers))}`,
|
||||
playlist: createM3U8ProxyUrl(data.data.sources[0].url, data.data.headers),
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions: [],
|
||||
...(thumbnailTrack
|
||||
|
|
@ -129,7 +130,7 @@ export const hianimeHd2SubEmbed = makeEmbed({
|
|||
{
|
||||
type: 'hls',
|
||||
id: 'primary',
|
||||
playlist: `https://proxy-m3u8.uira.live/m3u8-proxy?url=${data.data.sources[0].url}&headers=${encodeURIComponent(JSON.stringify(data.data.headers))}`,
|
||||
playlist: createM3U8ProxyUrl(data.data.sources[0].url, data.data.headers),
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions: [],
|
||||
...(thumbnailTrack
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { flags } from '@/entrypoint/utils/targets';
|
||||
import { makeEmbed } from '@/providers/base';
|
||||
import { NotFoundError } from '@/utils/errors';
|
||||
import { createM3U8ProxyUrl } from '@/utils/proxy';
|
||||
|
||||
export const viperScraper = makeEmbed({
|
||||
id: 'viper',
|
||||
|
|
@ -21,15 +22,18 @@ export const viperScraper = makeEmbed({
|
|||
}
|
||||
const playlistUrl = apiResponse.body.source.replace(/^.*\/viper\//, 'https://');
|
||||
|
||||
// You need to set a proxy for flixhq CDN streams. Set up your own from this repo: https://github.com/Pasithea0/M3U8-Proxy
|
||||
const proxiedPlaylist = `https://m3u8.moonpic.qzz.io/m3u8-proxy?url=${encodeURIComponent(playlistUrl)}&headers=${encodeURIComponent(JSON.stringify({ referer: 'https://megacloud.store/', origin: 'https://megacloud.store' }))}`;
|
||||
// Headers needed for the M3U8 proxy
|
||||
const headers = {
|
||||
referer: 'https://megacloud.store/',
|
||||
origin: 'https://megacloud.store',
|
||||
};
|
||||
|
||||
return {
|
||||
stream: [
|
||||
{
|
||||
type: 'hls',
|
||||
id: 'primary',
|
||||
playlist: proxiedPlaylist,
|
||||
playlist: createM3U8ProxyUrl(playlistUrl, headers),
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions: [],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { flags } from '@/entrypoint/utils/targets';
|
|||
import { SourcererOutput, makeSourcerer } from '@/providers/base';
|
||||
import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context';
|
||||
import { NotFoundError } from '@/utils/errors';
|
||||
import { createM3U8ProxyUrl } from '@/utils/proxy';
|
||||
|
||||
const baseUrl = 'https://api.coitus.ca';
|
||||
|
||||
|
|
@ -30,14 +31,8 @@ async function comboScraper(ctx: ShowScrapeContext | MovieScrapeContext): Promis
|
|||
const originalUrl = jsonData.u;
|
||||
const referer = jsonData.r || '';
|
||||
|
||||
const encodedUrl = encodeURIComponent(originalUrl);
|
||||
const encodedHeaders = encodeURIComponent(
|
||||
JSON.stringify({
|
||||
referer,
|
||||
}),
|
||||
);
|
||||
|
||||
processedUrl = `https://proxy.fifthwit.net/m3u8-proxy?url=${encodedUrl}&headers=${encodedHeaders}`;
|
||||
const headers = { referer };
|
||||
processedUrl = createM3U8ProxyUrl(originalUrl, headers);
|
||||
} catch (jsonError) {
|
||||
console.error('Error decoding/parsing orbitproxy data:', jsonError);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { compareTitle } from '@/utils/compare';
|
|||
import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context';
|
||||
import { makeCookieHeader } from '@/utils/cookie';
|
||||
import { NotFoundError } from '@/utils/errors';
|
||||
import { createM3U8ProxyUrl } from '@/utils/proxy';
|
||||
|
||||
// thanks @TPN for this
|
||||
// See how to set this up yourself: https://gist.github.com/Pasithea0/9ba31d16580800e899c245a4379e902b
|
||||
|
|
@ -111,7 +112,12 @@ const universalScraper = async (ctx: ShowScrapeContext | MovieScrapeContext): Pr
|
|||
|
||||
if (!autoFile) throw new Error('Failed to fetch playlist');
|
||||
|
||||
const playlist = `https://vercel-sucks.up.railway.app/m3u8-proxy?url=${encodeURIComponent(`${baseUrl}${autoFile}`)}&headers=${encodeURIComponent(JSON.stringify({ referer: baseUrl, cookie: makeCookieHeader({ hd: 'on' }) }))}`;
|
||||
const headers = {
|
||||
referer: baseUrl,
|
||||
cookie: makeCookieHeader({ hd: 'on' }),
|
||||
};
|
||||
|
||||
const playlist = createM3U8ProxyUrl(`${baseUrl}${autoFile}`, headers);
|
||||
ctx.progress(90);
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { compareTitle } from '@/utils/compare';
|
|||
import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context';
|
||||
import { makeCookieHeader } from '@/utils/cookie';
|
||||
import { NotFoundError } from '@/utils/errors';
|
||||
import { createM3U8ProxyUrl } from '@/utils/proxy';
|
||||
|
||||
// thanks @TPN for this
|
||||
// See how to set this up yourself: https://gist.github.com/Pasithea0/9ba31d16580800e899c245a4379e902b
|
||||
|
|
@ -108,7 +109,12 @@ const universalScraper = async (ctx: ShowScrapeContext | MovieScrapeContext): Pr
|
|||
|
||||
if (!autoFile) throw new Error('Failed to fetch playlist');
|
||||
|
||||
const playlist = `https://vercel-sucks.up.railway.app/m3u8-proxy?url=${encodeURIComponent(`${baseUrl}${autoFile}`)}&headers=${encodeURIComponent(JSON.stringify({ referer: baseUrl, cookie: makeCookieHeader({ hd: 'on' }) }))}`;
|
||||
const headers = {
|
||||
referer: baseUrl,
|
||||
cookie: makeCookieHeader({ hd: 'on' }),
|
||||
};
|
||||
|
||||
const playlist = createM3U8ProxyUrl(`${baseUrl}${autoFile}`, headers);
|
||||
ctx.progress(90);
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -2,17 +2,14 @@ import { flags } from '@/entrypoint/utils/targets';
|
|||
import { SourcererEmbed, SourcererOutput, makeSourcerer } from '@/providers/base';
|
||||
import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context';
|
||||
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 {
|
||||
const encodedUrl = encodeURIComponent(originalUrl);
|
||||
const encodedHeaders = encodeURIComponent(
|
||||
JSON.stringify({
|
||||
referer,
|
||||
}),
|
||||
);
|
||||
|
||||
return `https://proxy.fifthwit.net/m3u8-proxy?url=${encodedUrl}&headers=${encodedHeaders}`;
|
||||
const headers = {
|
||||
referer,
|
||||
};
|
||||
return createM3U8ProxyUrl(originalUrl, headers);
|
||||
}
|
||||
|
||||
function processProxiedURL(url: string): string {
|
||||
|
|
@ -40,7 +37,7 @@ function processProxiedURL(url: string): string {
|
|||
|
||||
// Handle other proxied URLs
|
||||
if (url.includes('/m3u8-proxy?url=')) {
|
||||
return url.replace(/https:\/\/[^/]+\/m3u8-proxy/, 'https://proxy.fifthwit.net/m3u8-proxy');
|
||||
return updateM3U8ProxyUrl(url);
|
||||
}
|
||||
|
||||
return url;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,27 @@
|
|||
import { flags } from '@/entrypoint/utils/targets';
|
||||
import { Stream } from '@/providers/streams';
|
||||
|
||||
// Default proxy URL for general purpose proxying
|
||||
const DEFAULT_PROXY_URL = 'https://proxy.nsbx.ru/proxy';
|
||||
// Default M3U8 proxy URL for HLS stream proxying
|
||||
let CONFIGURED_M3U8_PROXY_URL = 'https://proxy.fifthwit.net';
|
||||
|
||||
/**
|
||||
* Set a custom M3U8 proxy URL to use for all M3U8 proxy requests
|
||||
* @param proxyUrl - The base URL of the M3U8 proxy
|
||||
*/
|
||||
export function setM3U8ProxyUrl(proxyUrl: string): void {
|
||||
CONFIGURED_M3U8_PROXY_URL = proxyUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the currently configured M3U8 proxy URL
|
||||
* @returns The configured M3U8 proxy URL
|
||||
*/
|
||||
export function getM3U8ProxyUrl(): string {
|
||||
return CONFIGURED_M3U8_PROXY_URL;
|
||||
}
|
||||
|
||||
export function requiresProxy(stream: Stream): boolean {
|
||||
if (!stream.flags.includes(flags.CORS_ALLOWED) || !!(stream.headers && Object.keys(stream.headers).length > 0))
|
||||
return true;
|
||||
|
|
@ -27,14 +48,14 @@ export function setupProxy(stream: Stream): Stream {
|
|||
if (stream.type === 'hls') {
|
||||
payload.type = 'hls';
|
||||
payload.url = stream.playlist;
|
||||
stream.playlist = `https://proxy.nsbx.ru/proxy?${new URLSearchParams({ payload: Buffer.from(JSON.stringify(payload)).toString('base64url') })}`;
|
||||
stream.playlist = `${DEFAULT_PROXY_URL}?${new URLSearchParams({ payload: Buffer.from(JSON.stringify(payload)).toString('base64url') })}`;
|
||||
}
|
||||
|
||||
if (stream.type === 'file') {
|
||||
payload.type = 'mp4';
|
||||
Object.entries(stream.qualities).forEach((entry) => {
|
||||
payload.url = entry[1].url;
|
||||
entry[1].url = `https://proxy.nsbx.ru/proxy?${new URLSearchParams({ payload: Buffer.from(JSON.stringify(payload)).toString('base64url') })}`;
|
||||
entry[1].url = `${DEFAULT_PROXY_URL}?${new URLSearchParams({ payload: Buffer.from(JSON.stringify(payload)).toString('base64url') })}`;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -42,3 +63,27 @@ export function setupProxy(stream: Stream): Stream {
|
|||
stream.flags = [flags.CORS_ALLOWED];
|
||||
return stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a proxied M3U8 URL using the configured M3U8 proxy
|
||||
* @param url - The original M3U8 URL to proxy
|
||||
* @param headers - Headers to include with the request
|
||||
* @returns The proxied M3U8 URL
|
||||
*/
|
||||
export function createM3U8ProxyUrl(url: string, headers: Record<string, string> = {}): string {
|
||||
const encodedUrl = encodeURIComponent(url);
|
||||
const encodedHeaders = encodeURIComponent(JSON.stringify(headers));
|
||||
return `${CONFIGURED_M3U8_PROXY_URL}/m3u8-proxy?url=${encodedUrl}${headers ? `&headers=${encodedHeaders}` : ''}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing M3U8 proxy URL to use the currently configured proxy
|
||||
* @param url - The M3U8 proxy URL to update
|
||||
* @returns The updated M3U8 proxy URL
|
||||
*/
|
||||
export function updateM3U8ProxyUrl(url: string): string {
|
||||
if (url.includes('/m3u8-proxy?url=')) {
|
||||
return url.replace(/https:\/\/[^/]+\/m3u8-proxy/, `${CONFIGURED_M3U8_PROXY_URL}/m3u8-proxy`);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue