diff --git a/src/providers/all.ts b/src/providers/all.ts index 162acc3..1908d5a 100644 --- a/src/providers/all.ts +++ b/src/providers/all.ts @@ -74,6 +74,7 @@ import { webtor1080Scraper, webtor480Scraper, webtor4kScraper, webtor720Scraper import { xprimeApolloEmbed, xprimeFoxEmbed, + xprimeHarbourEmbed, xprimeMarantEmbed, xprimePrimenetEmbed, xprimeStreamboxEmbed, @@ -185,6 +186,7 @@ export function gatherAllEmbeds(): Array { xprimeMarantEmbed, xprimePrimenetEmbed, xprimeVolkswagenEmbed, + xprimeHarbourEmbed, ConsumetVidCloudScraper, ConsumetStreamSBScraper, ConsumetVidStreamingScraper, diff --git a/src/providers/embeds/xprime.ts b/src/providers/embeds/xprime.ts index 93cf2f7..b8f85df 100644 --- a/src/providers/embeds/xprime.ts +++ b/src/providers/embeds/xprime.ts @@ -9,6 +9,7 @@ const showboxBaseUrl = 'https://xprime.tv/primebox'; const marantBaseUrl = 'https://backend.xprime.tv/marant'; const primenetBaseUrl = 'https://backend.xprime.tv/primenet'; const volkswagenBaseUrl = 'https://backend.xprime.tv/volkswagen'; +const harbourBaseUrl = 'https://backend.xprime.tv/harbour'; const languageMap: Record = { 'chinese - hong kong': 'zh', @@ -41,54 +42,10 @@ const languageMap: Record = { اردو: 'ur', }; -export const xprimeFoxEmbed = makeEmbed({ - id: 'xprime-fox', - name: 'Fox', - rank: 241, - async scrape(ctx): Promise { - const query = JSON.parse(ctx.url); - const params = new URLSearchParams({ - name: query.title, - pstream: 'true', - }); - - if (query.type === 'show') { - params.append('season', query.season.toString()); - params.append('episode', query.episode.toString()); - } - - const apiRes = await ctx.fetcher(`${foxBaseUrl}?${params.toString()}`); - if (!apiRes) throw new NotFoundError('No response received'); - const data = await JSON.parse(apiRes); - if (!data.url) throw new NotFoundError('No stream URL found in response'); - - const captions = - data.subtitles?.map((sub: { file: string; label: string }) => ({ - type: 'vtt', - url: sub.file, - language: languageMap[sub.label.toLowerCase()] || 'unknown', - })) || []; - - ctx.progress(90); - - return { - stream: [ - { - type: 'hls', - id: 'primary', - playlist: `https://oca.kendrickl-3amar.site/?v=${encodeURIComponent(data.url)}&headers=${encodeURIComponent(JSON.stringify({ referer: 'https://megacloud.store/', origin: 'https://megacloud.store' }))}`, - flags: [flags.CORS_ALLOWED], - captions, - }, - ], - }; - }, -}); - export const xprimeApolloEmbed = makeEmbed({ id: 'xprime-apollo', name: 'Appolo', - rank: 244, + rank: 237, async scrape(ctx): Promise { const query = JSON.parse(ctx.url); let url = `${apolloBaseUrl}/${query.tmdbId}`; @@ -137,7 +94,7 @@ export const xprimeApolloEmbed = makeEmbed({ export const xprimeStreamboxEmbed = makeEmbed({ id: 'xprime-streambox', name: 'Streambox', - rank: 243, + rank: 236, async scrape(ctx): Promise { const query = JSON.parse(ctx.url); @@ -192,44 +149,10 @@ export const xprimeStreamboxEmbed = makeEmbed({ }, }); -export const xprimeMarantEmbed = makeEmbed({ - id: 'xprime-marant', - name: 'Marant (French + English)', - rank: 240, - async scrape(ctx): Promise { - const query = JSON.parse(ctx.url); - let url = `${marantBaseUrl}?id=${query.tmdbId}`; - - if (query.type === 'show') { - url += `&season=${query.season}&episode=${query.episode}`; - } - - const data = await ctx.fetcher(url); - - if (!data) throw new NotFoundError('No response received'); - if (data.error) throw new NotFoundError(data.error); - if (!data.url) throw new NotFoundError('No stream URL found in response'); - - ctx.progress(90); - - return { - stream: [ - { - type: 'hls', - id: 'primary', - playlist: data.url, - flags: [flags.CORS_ALLOWED], - captions: [], - }, - ], - }; - }, -}); - export const xprimePrimenetEmbed = makeEmbed({ id: 'xprime-primenet', name: 'Primenet', - rank: 242, + rank: 235, async scrape(ctx): Promise { const query = JSON.parse(ctx.url); let url = `${primenetBaseUrl}?id=${query.tmdbId}`; @@ -260,10 +183,132 @@ export const xprimePrimenetEmbed = makeEmbed({ }, }); +export const xprimeFoxEmbed = makeEmbed({ + id: 'xprime-fox', + name: 'Fox', + rank: 233, + async scrape(ctx): Promise { + const query = JSON.parse(ctx.url); + const params = new URLSearchParams({ + name: query.title, + pstream: 'true', + }); + + if (query.type === 'show') { + params.append('season', query.season.toString()); + params.append('episode', query.episode.toString()); + } + + const apiRes = await ctx.fetcher(`${foxBaseUrl}?${params.toString()}`); + if (!apiRes) throw new NotFoundError('No response received'); + const data = await JSON.parse(apiRes); + if (!data.url) throw new NotFoundError('No stream URL found in response'); + + const captions = + data.subtitles?.map((sub: { file: string; label: string }) => ({ + type: 'vtt', + url: sub.file, + language: languageMap[sub.label.toLowerCase()] || 'unknown', + })) || []; + + ctx.progress(90); + + return { + stream: [ + { + type: 'hls', + id: 'primary', + playlist: `https://oca.kendrickl-3amar.site/?v=${encodeURIComponent(data.url)}&headers=${encodeURIComponent(JSON.stringify({ referer: 'https://megacloud.store/', origin: 'https://megacloud.store' }))}`, + flags: [flags.CORS_ALLOWED], + captions, + }, + ], + }; + }, +}); + +export const xprimeHarbourEmbed = makeEmbed({ + id: 'xprime-harbour', + name: 'Harbour', + rank: 232, + async scrape(ctx): Promise { + const query = JSON.parse(ctx.url); + const params = new URLSearchParams({ + name: query.title, + year: query.releaseYear.toString(), + }); + + if (query.type === 'show') { + params.append('season', query.season.toString()); + params.append('episode', query.episode.toString()); + } + + const apiRes = await ctx.fetcher(`${harbourBaseUrl}?${params.toString()}`); + if (!apiRes) throw new NotFoundError('No response received'); + const data = await JSON.parse(apiRes); + if (!data.url) throw new NotFoundError('No stream URL found in response'); + + const captions = + data.subtitles?.map((sub: { file: string; label: string }) => ({ + type: 'vtt', + url: sub.file, + language: languageMap[sub.label.toLowerCase()] || 'unknown', + })) || []; + + ctx.progress(90); + + return { + stream: [ + { + type: 'hls', + id: 'primary', + playlist: data.url, + flags: [flags.CORS_ALLOWED], + captions, + }, + ], + }; + }, +}); + +export const xprimeMarantEmbed = makeEmbed({ + id: 'xprime-marant', + name: 'Marant (French + English)', + rank: 231, + async scrape(ctx): Promise { + const query = JSON.parse(ctx.url); + let url = `${marantBaseUrl}?id=${query.tmdbId}`; + + if (query.type === 'show') { + url += `&season=${query.season}&episode=${query.episode}`; + } + + const data = await ctx.fetcher(url); + + if (!data) throw new NotFoundError('No response received'); + if (data.error) throw new NotFoundError(data.error); + if (!data.url) throw new NotFoundError('No stream URL found in response'); + + ctx.progress(90); + + return { + stream: [ + { + type: 'hls', + id: 'primary', + playlist: data.url, + flags: [flags.CORS_ALLOWED], + captions: [], + }, + ], + }; + }, +}); + export const xprimeVolkswagenEmbed = makeEmbed({ id: 'xprime-volkswagen', name: 'Volkswagen (German)', - rank: 239, + rank: 230, async scrape(ctx): Promise { const query = JSON.parse(ctx.url); let url = `${volkswagenBaseUrl}?name=${query.title}`; diff --git a/src/providers/sources/xprime.ts b/src/providers/sources/xprime.ts index 4c84946..c5dd244 100644 --- a/src/providers/sources/xprime.ts +++ b/src/providers/sources/xprime.ts @@ -15,10 +15,6 @@ async function comboScraper(ctx: ShowScrapeContext | MovieScrapeContext): Promis }; const embeds = [ - { - embedId: 'xprime-fox', - url: JSON.stringify(query), - }, { embedId: 'xprime-apollo', url: JSON.stringify(query), @@ -28,11 +24,15 @@ async function comboScraper(ctx: ShowScrapeContext | MovieScrapeContext): Promis url: JSON.stringify(query), }, { - embedId: 'xprime-marant', + embedId: 'xprime-primenet', url: JSON.stringify(query), }, { - embedId: 'xprime-primenet', + embedId: 'xprime-fox', + url: JSON.stringify(query), + }, + { + embedId: 'xprime-marant', url: JSON.stringify(query), }, { diff --git a/src/utils/valid.ts b/src/utils/valid.ts index 232c533..b6f2da2 100644 --- a/src/utils/valid.ts +++ b/src/utils/valid.ts @@ -34,6 +34,7 @@ import { warezcdnembedMp4Scraper } from '@/providers/embeds/warezcdn/mp4'; import { xprimeApolloEmbed, xprimeFoxEmbed, + xprimeHarbourEmbed, xprimeMarantEmbed, xprimePrimenetEmbed, xprimeStreamboxEmbed, @@ -67,6 +68,7 @@ const SKIP_VALIDATION_CHECK_IDS = [ xprimeMarantEmbed.id, xprimePrimenetEmbed.id, xprimeVolkswagenEmbed.id, + xprimeHarbourEmbed.id, ConsumetVidCloudScraper.id, ConsumetStreamSBScraper.id, ConsumetVidStreamingScraper.id,