add nflix

This commit is contained in:
Pas 2025-03-21 12:13:19 -06:00
parent 680d0d88d5
commit c809258026
3 changed files with 139 additions and 1 deletions

View file

@ -52,6 +52,7 @@ import { FedAPIScraper } from './sources/fedapi';
import { hdRezkaScraper } from './sources/hdrezka';
import { iosmirrorScraper } from './sources/iosmirror';
import { iosmirrorPVScraper } from './sources/iosmirrorpv';
import { nunflixScraper } from './sources/nunflix';
import { ridooMoviesScraper } from './sources/ridomovies';
import { slidemoviesScraper } from './sources/slidemovies';
import { soaperTvScraper } from './sources/soapertv';
@ -86,6 +87,7 @@ export function gatherAllSources(): Array<Sourcerer> {
vidapiClickScraper,
coitusScraper,
streamboxScraper,
nunflixScraper,
];
}

View file

@ -64,7 +64,7 @@ async function comboScraper(ctx: ShowScrapeContext | MovieScrapeContext): Promis
export const embedsuScraper = makeSourcerer({
id: 'embedsu',
name: 'embed.su',
rank: 240,
rank: 230,
disabled: false,
flags: [flags.CORS_ALLOWED],
scrapeMovie: comboScraper,

View file

@ -0,0 +1,136 @@
import { flags } from '@/entrypoint/utils/targets';
import { SourcererOutput, makeSourcerer } from '@/providers/base';
import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context';
import { NotFoundError } from '@/utils/errors';
const mamaApiBase = 'https://mama.up.railway.app/api/showbox';
interface StreamItem {
filename: string;
quality: string;
type: string;
size: string;
player_streams: Array<{
file: string;
quality: string;
type: string;
}>;
direct_download: string;
}
interface StreamData {
success: boolean;
tmdb_id: string;
type: 'movie' | 'tv';
title: string;
year: number;
showbox_id: string;
febbox_url?: string;
season?: number;
episode?: number;
streams: StreamItem | StreamItem[];
seasons?: Record<string, any>;
source: string;
}
async function comboScraper(ctx: ShowScrapeContext | MovieScrapeContext): Promise<SourcererOutput> {
const apiUrl =
ctx.media.type === 'movie'
? `${mamaApiBase}/movie/${ctx.media.tmdbId}`
: `${mamaApiBase}/tv/${ctx.media.tmdbId}?season=${ctx.media.season.number}&episode=${ctx.media.episode.number}`;
const apiRes = await ctx.proxiedFetcher(apiUrl);
if (!apiRes) {
throw new NotFoundError('No response from API');
}
const data = (await apiRes) as StreamData;
if (!data.success) {
throw new NotFoundError('No streams found');
}
const streamItems = Array.isArray(data.streams) ? data.streams : [data.streams];
if (streamItems.length === 0 || !streamItems[0].player_streams) {
throw new NotFoundError('No valid streams found');
}
let bestStreamItem = streamItems[0];
for (const item of streamItems) {
if (item.quality.includes('4K') || item.quality.includes('2160p')) {
bestStreamItem = item;
break;
}
}
const streams = bestStreamItem.player_streams.reduce((acc: Record<string, string>, stream) => {
let qualityKey: number | string;
if (stream.quality === '4K' || stream.quality.includes('4K')) {
qualityKey = 2160;
} else if (stream.quality === 'ORG' || stream.quality.includes('ORG')) {
return acc; // Skip original quality
} else {
qualityKey = parseInt(stream.quality.replace('P', ''), 10);
}
if (Number.isNaN(qualityKey) || acc[qualityKey]) return acc;
acc[qualityKey] = stream.file;
return acc;
}, {});
return {
embeds: [],
stream: [
{
id: 'primary',
captions: [],
qualities: {
...(streams[2160] && {
'4k': {
type: 'mp4',
url: streams[2160],
},
}),
...(streams[1080] && {
1080: {
type: 'mp4',
url: streams[1080],
},
}),
...(streams[720] && {
720: {
type: 'mp4',
url: streams[720],
},
}),
...(streams[480] && {
480: {
type: 'mp4',
url: streams[480],
},
}),
...(streams[360] && {
360: {
type: 'mp4',
url: streams[360],
},
}),
},
type: 'file',
flags: [flags.CORS_ALLOWED],
},
],
};
}
export const nunflixScraper = makeSourcerer({
id: 'nunflix',
name: 'NFlix',
rank: 240,
disabled: false,
flags: [flags.CORS_ALLOWED],
scrapeMovie: comboScraper,
scrapeShow: comboScraper,
});