diff --git a/src/providers/all.ts b/src/providers/all.ts index 9ae41ef..bce55cb 100644 --- a/src/providers/all.ts +++ b/src/providers/all.ts @@ -39,6 +39,18 @@ import { streamwishSpanishScraper, } from './embeds/streamwish'; import { vidCloudScraper } from './embeds/vidcloud'; +import { + vidifyAlfaEmbed, + vidifyBravoEmbed, + vidifyCharlieEmbed, + vidifyDeltaEmbed, + vidifyEchoEmbed, + vidifyFoxtrotEmbed, + vidifyGolfEmbed, + vidifyHotelEmbed, + vidifyIndiaEmbed, + vidifyJuliettEmbed, +} from './embeds/vidify'; import { VidsrcsuServer10Scraper, VidsrcsuServer11Scraper, @@ -75,6 +87,7 @@ import { slidemoviesScraper } from './sources/slidemovies'; import { soaperTvScraper } from './sources/soapertv'; import { streamboxScraper } from './sources/streambox'; import { vidapiClickScraper } from './sources/vidapiclick'; +import { vidifyScraper } from './sources/vidify'; import { warezcdnScraper } from './sources/warezcdn'; import { wecimaScraper } from './sources/wecima'; @@ -113,6 +126,7 @@ export function gatherAllSources(): Array { vidsrcvipScraper, madplayScraper, rgshowsScraper, + vidifyScraper, ]; } @@ -166,5 +180,15 @@ export function gatherAllEmbeds(): Array { madplayNsapiEmbed, madplayRoperEmbed, madplayNsapiVidFastEmbed, + vidifyAlfaEmbed, + vidifyBravoEmbed, + vidifyCharlieEmbed, + vidifyDeltaEmbed, + vidifyEchoEmbed, + vidifyFoxtrotEmbed, + vidifyGolfEmbed, + vidifyHotelEmbed, + vidifyIndiaEmbed, + vidifyJuliettEmbed, ]; } diff --git a/src/providers/embeds/vidify.ts b/src/providers/embeds/vidify.ts new file mode 100644 index 0000000..483e19d --- /dev/null +++ b/src/providers/embeds/vidify.ts @@ -0,0 +1,464 @@ +import { flags } from '@/entrypoint/utils/targets'; +import { NotFoundError } from '@/utils/errors'; +import { createM3U8ProxyUrl } from '@/utils/proxy'; + +import { EmbedOutput, makeEmbed } from '../base'; + +const baseUrl = 'madplay.site'; +const headers = { + referer: 'https://api.vidify.top/', + origin: 'https://player.vidify.top', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', +}; + +export const vidifyAlfaEmbed = makeEmbed({ + id: 'vidify-alfa', + name: 'Vidify Alfa', + rank: 230, + async scrape(ctx): Promise { + const query = JSON.parse(ctx.url); + const { type, tmdbId, season, episode } = query; + + let url = `https://${baseUrl}/`; + + if (type === 'movie') { + url += `/movie/${tmdbId}?sr=1`; + } else if (type === 'show') { + url += `/tv/${tmdbId}/season/${season}/episode/${episode}?sr=1`; + } else { + throw new NotFoundError('Unsupported media type'); + } + + const res = await ctx.proxiedFetcher(url, { headers }); + console.log(res); + + if (!Array.isArray(res) || res.length === 0) { + throw new NotFoundError('No streams found'); + } + const stream = res[0]; + + if (!stream.file) { + throw new NotFoundError('No file URL found in stream'); + } + + ctx.progress(100); + + return { + stream: [ + { + id: 'primary', + type: 'hls', + playlist: createM3U8ProxyUrl(stream.file, headers), + flags: [flags.CORS_ALLOWED], + captions: [], + }, + ], + }; + }, +}); + +export const vidifyBravoEmbed = makeEmbed({ + id: 'vidify-bravo', + name: 'Vidify Bravo', + rank: 229, + async scrape(ctx): Promise { + const query = JSON.parse(ctx.url); + const { type, tmdbId, season, episode } = query; + + let url = `https://${baseUrl}/`; + + if (type === 'movie') { + url += `/movie/${tmdbId}?sr=2`; + } else if (type === 'show') { + url += `/tv/${tmdbId}/season/${season}/episode/${episode}?sr=2`; + } else { + throw new NotFoundError('Unsupported media type'); + } + + const res = await ctx.proxiedFetcher(url, { headers }); + + if (!Array.isArray(res) || res.length === 0) { + throw new NotFoundError('No streams found'); + } + const stream = res[0]; + + if (!stream.file) { + throw new NotFoundError('No file URL found in stream'); + } + + ctx.progress(100); + + return { + stream: [ + { + id: 'primary', + type: 'hls', + playlist: createM3U8ProxyUrl(stream.file, headers), + flags: [flags.CORS_ALLOWED], + captions: [], + }, + ], + }; + }, +}); + +export const vidifyCharlieEmbed = makeEmbed({ + id: 'vidify-charlie', + name: 'Vidify Charlie', + rank: 228, + async scrape(ctx): Promise { + const query = JSON.parse(ctx.url); + const { type, tmdbId, season, episode } = query; + + let url = `https://${baseUrl}/`; + + if (type === 'movie') { + url += `/movie/${tmdbId}?sr=3`; + } else if (type === 'show') { + url += `/tv/${tmdbId}/season/${season}/episode/${episode}?sr=3`; + } else { + throw new NotFoundError('Unsupported media type'); + } + + const res = await ctx.proxiedFetcher(url, { headers }); + + if (!Array.isArray(res) || res.length === 0) { + throw new NotFoundError('No streams found'); + } + const stream = res[0]; + + if (!stream.file) { + throw new NotFoundError('No file URL found in stream'); + } + + ctx.progress(100); + + return { + stream: [ + { + id: 'primary', + type: 'hls', + playlist: createM3U8ProxyUrl(stream.file, headers), + flags: [flags.CORS_ALLOWED], + captions: [], + }, + ], + }; + }, +}); + +export const vidifyDeltaEmbed = makeEmbed({ + id: 'vidify-delta', + name: 'Vidify Delta', + rank: 227, + async scrape(ctx): Promise { + const query = JSON.parse(ctx.url); + const { type, tmdbId, season, episode } = query; + + let url = `https://${baseUrl}/`; + + if (type === 'movie') { + url += `/movie/${tmdbId}?sr=4`; + } else if (type === 'show') { + url += `/tv/${tmdbId}/season/${season}/episode/${episode}?sr=4`; + } else { + throw new NotFoundError('Unsupported media type'); + } + + const res = await ctx.proxiedFetcher(url, { headers }); + + if (!Array.isArray(res) || res.length === 0) { + throw new NotFoundError('No streams found'); + } + const stream = res[0]; + + if (!stream.file) { + throw new NotFoundError('No file URL found in stream'); + } + + ctx.progress(100); + + return { + stream: [ + { + id: 'primary', + type: 'hls', + playlist: createM3U8ProxyUrl(stream.file, headers), + flags: [flags.CORS_ALLOWED], + captions: [], + }, + ], + }; + }, +}); + +export const vidifyEchoEmbed = makeEmbed({ + id: 'vidify-echo', + name: 'Vidify Echo', + rank: 226, + async scrape(ctx): Promise { + const query = JSON.parse(ctx.url); + const { type, tmdbId, season, episode } = query; + + let url = `https://${baseUrl}/`; + + if (type === 'movie') { + url += `/movie/${tmdbId}?sr=5`; + } else if (type === 'show') { + url += `/tv/${tmdbId}/season/${season}/episode/${episode}?sr=5`; + } else { + throw new NotFoundError('Unsupported media type'); + } + + const res = await ctx.proxiedFetcher(url, { headers }); + + if (!Array.isArray(res) || res.length === 0) { + throw new NotFoundError('No streams found'); + } + const stream = res[0]; + + if (!stream.file) { + throw new NotFoundError('No file URL found in stream'); + } + + ctx.progress(100); + + return { + stream: [ + { + id: 'primary', + type: 'hls', + playlist: createM3U8ProxyUrl(stream.file, headers), + flags: [flags.CORS_ALLOWED], + captions: [], + }, + ], + }; + }, +}); + +export const vidifyFoxtrotEmbed = makeEmbed({ + id: 'vidify-foxtrot', + name: 'Vidify Foxtrot', + rank: 225, + async scrape(ctx): Promise { + const query = JSON.parse(ctx.url); + const { type, tmdbId, season, episode } = query; + + let url = `https://${baseUrl}/`; + + if (type === 'movie') { + url += `/movie/${tmdbId}?sr=6`; + } else if (type === 'show') { + url += `/tv/${tmdbId}/season/${season}/episode/${episode}?sr=6`; + } else { + throw new NotFoundError('Unsupported media type'); + } + + const res = await ctx.proxiedFetcher(url, { headers }); + + if (!Array.isArray(res) || res.length === 0) { + throw new NotFoundError('No streams found'); + } + const stream = res[0]; + + if (!stream.file) { + throw new NotFoundError('No file URL found in stream'); + } + + ctx.progress(100); + + return { + stream: [ + { + id: 'primary', + type: 'hls', + playlist: createM3U8ProxyUrl(stream.file, headers), + flags: [flags.CORS_ALLOWED], + captions: [], + }, + ], + }; + }, +}); + +export const vidifyGolfEmbed = makeEmbed({ + id: 'vidify-golf', + name: 'Vidify Golf', + rank: 224, + async scrape(ctx): Promise { + const query = JSON.parse(ctx.url); + const { type, tmdbId, season, episode } = query; + + let url = `https://${baseUrl}/`; + + if (type === 'movie') { + url += `/movie/${tmdbId}?sr=7`; + } else if (type === 'show') { + url += `/tv/${tmdbId}/season/${season}/episode/${episode}?sr=7`; + } else { + throw new NotFoundError('Unsupported media type'); + } + + const res = await ctx.proxiedFetcher(url, { headers }); + + if (!Array.isArray(res) || res.length === 0) { + throw new NotFoundError('No streams found'); + } + const stream = res[0]; + + if (!stream.file) { + throw new NotFoundError('No file URL found in stream'); + } + + ctx.progress(100); + + return { + stream: [ + { + id: 'primary', + type: 'hls', + playlist: createM3U8ProxyUrl(stream.file, headers), + flags: [flags.CORS_ALLOWED], + captions: [], + }, + ], + }; + }, +}); + +export const vidifyHotelEmbed = makeEmbed({ + id: 'vidify-hotel', + name: 'Vidify Hotel', + rank: 223, + async scrape(ctx): Promise { + const query = JSON.parse(ctx.url); + const { type, tmdbId, season, episode } = query; + + let url = `https://${baseUrl}/`; + + if (type === 'movie') { + url += `/movie/${tmdbId}?sr=8`; + } else if (type === 'show') { + url += `/tv/${tmdbId}/season/${season}/episode/${episode}?sr=8`; + } else { + throw new NotFoundError('Unsupported media type'); + } + + const res = await ctx.proxiedFetcher(url, { headers }); + + if (!Array.isArray(res) || res.length === 0) { + throw new NotFoundError('No streams found'); + } + const stream = res[0]; + + if (!stream.file) { + throw new NotFoundError('No file URL found in stream'); + } + + ctx.progress(100); + + return { + stream: [ + { + id: 'primary', + type: 'hls', + playlist: createM3U8ProxyUrl(stream.file, headers), + flags: [flags.CORS_ALLOWED], + captions: [], + }, + ], + }; + }, +}); + +export const vidifyIndiaEmbed = makeEmbed({ + id: 'vidify-india', + name: 'Vidify India', + rank: 222, + async scrape(ctx): Promise { + const query = JSON.parse(ctx.url); + const { type, tmdbId, season, episode } = query; + + let url = `https://${baseUrl}/`; + + if (type === 'movie') { + url += `/movie/${tmdbId}?sr=9`; + } else if (type === 'show') { + url += `/tv/${tmdbId}/season/${season}/episode/${episode}?sr=9`; + } else { + throw new NotFoundError('Unsupported media type'); + } + + const res = await ctx.proxiedFetcher(url, { headers }); + + if (!Array.isArray(res) || res.length === 0) { + throw new NotFoundError('No streams found'); + } + const stream = res[0]; + + if (!stream.file) { + throw new NotFoundError('No file URL found in stream'); + } + + ctx.progress(100); + + return { + stream: [ + { + id: 'primary', + type: 'hls', + playlist: createM3U8ProxyUrl(stream.file, headers), + flags: [flags.CORS_ALLOWED], + captions: [], + }, + ], + }; + }, +}); + +export const vidifyJuliettEmbed = makeEmbed({ + id: 'vidify-juliett', + name: 'Vidify Juliett', + rank: 221, + async scrape(ctx): Promise { + const query = JSON.parse(ctx.url); + const { type, tmdbId, season, episode } = query; + + let url = `https://${baseUrl}/`; + + if (type === 'movie') { + url += `/movie/${tmdbId}?sr=10`; + } else if (type === 'show') { + url += `/tv/${tmdbId}/season/${season}/episode/${episode}?sr=10`; + } else { + throw new NotFoundError('Unsupported media type'); + } + + const res = await ctx.proxiedFetcher(url, { headers }); + + if (!Array.isArray(res) || res.length === 0) { + throw new NotFoundError('No streams found'); + } + const stream = res[0]; + + if (!stream.file) { + throw new NotFoundError('No file URL found in stream'); + } + + ctx.progress(100); + + return { + stream: [ + { + id: 'primary', + type: 'hls', + playlist: createM3U8ProxyUrl(stream.file, headers), + flags: [flags.CORS_ALLOWED], + captions: [], + }, + ], + }; + }, +}); diff --git a/src/providers/sources/vidify.ts b/src/providers/sources/vidify.ts new file mode 100644 index 0000000..ae9bab0 --- /dev/null +++ b/src/providers/sources/vidify.ts @@ -0,0 +1,72 @@ +import { flags } from '@/entrypoint/utils/targets'; +import { SourcererOutput, makeSourcerer } from '@/providers/base'; +import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context'; + +async function comboScraper(ctx: ShowScrapeContext | MovieScrapeContext): Promise { + const query = { + type: ctx.media.type, + title: ctx.media.title, + tmdbId: ctx.media.tmdbId, + imdbId: ctx.media.imdbId, + ...(ctx.media.type === 'show' && { + season: ctx.media.season.number, + episode: ctx.media.episode.number, + }), + releaseYear: ctx.media.releaseYear, + }; + + return { + embeds: [ + { + embedId: 'vidify-alfa', + url: JSON.stringify(query), + }, + { + embedId: 'vidify-bravo', + url: JSON.stringify(query), + }, + { + embedId: 'vidify-charlie', + url: JSON.stringify(query), + }, + { + embedId: 'vidify-delta', + url: JSON.stringify(query), + }, + { + embedId: 'vidify-echo', + url: JSON.stringify(query), + }, + { + embedId: 'vidify-foxtrot', + url: JSON.stringify(query), + }, + { + embedId: 'vidify-golf', + url: JSON.stringify(query), + }, + { + embedId: 'vidify-hotel', + url: JSON.stringify(query), + }, + { + embedId: 'vidify-india', + url: JSON.stringify(query), + }, + { + embedId: 'vidify-juliett', + url: JSON.stringify(query), + }, + ], + }; +} + +export const vidifyScraper = makeSourcerer({ + id: 'vidify', + name: 'Vidify', + rank: 184, + disabled: true, + flags: [flags.CORS_ALLOWED], + scrapeMovie: comboScraper, + scrapeShow: comboScraper, +});