pstreams-providers/src/providers/embeds/xprime.ts
2025-05-07 14:57:22 -06:00

305 lines
8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* eslint-disable no-console */
import { flags } from '@/entrypoint/utils/targets';
import { EmbedOutput, makeEmbed } from '@/providers/base';
import { NotFoundError } from '@/utils/errors';
const foxBaseUrl = 'https://xprime.tv/foxtemp';
const apolloBaseUrl = 'https://kendrickl-3amar.site';
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 languageMap: Record<string, string> = {
'chinese - hong kong': 'zh',
'chinese - traditional': 'zh',
czech: 'cs',
danish: 'da',
dutch: 'nl',
english: 'en',
'english - sdh': 'en',
finnish: 'fi',
french: 'fr',
german: 'de',
greek: 'el',
hungarian: 'hu',
italian: 'it',
korean: 'ko',
norwegian: 'no',
polish: 'pl',
portuguese: 'pt',
'portuguese - brazilian': 'pt',
romanian: 'ro',
'spanish - european': 'es',
'spanish - latin american': 'es',
swedish: 'sv',
turkish: 'tr',
اَلْعَرَبِيَّةُ: 'ar',
: 'bn',
filipino: 'tl',
indonesia: 'id',
اردو: 'ur',
};
export const xprimeFoxEmbed = makeEmbed({
id: 'xprime-fox',
name: 'Fox',
rank: 241,
async scrape(ctx): Promise<EmbedOutput> {
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,
async scrape(ctx): Promise<EmbedOutput> {
const query = JSON.parse(ctx.url);
let url = `${apolloBaseUrl}/${query.tmdbId}`;
if (query.type === 'show') {
url += `/${query.season}/${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');
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,
...(data.thumbnails?.file
? {
thumbnailTrack: {
type: 'vtt',
url: data.thumbnails.file,
},
}
: {}),
},
],
};
},
});
export const xprimeStreamboxEmbed = makeEmbed({
id: 'xprime-streambox',
name: 'Streambox',
rank: 243,
async scrape(ctx): Promise<EmbedOutput> {
const query = JSON.parse(ctx.url);
let url = `${showboxBaseUrl}?name=${query.title}&year=${query.releaseYear}&fallback_year=${query.releaseYear}`;
if (query.type === 'show') {
url += `&season=${query.season}&episode=${query.episode}`;
}
// Old handling in case
// if (query.type === 'show') {
// url += `?id=${query.tmdbId}&season=${query.season}&episode=${query.episode}`;
// } else {
// url += `?id=${query.tmdbId}`;
// }
const data = await ctx.fetcher(url);
if (!data) throw new NotFoundError('No response received');
if (data.error) throw new NotFoundError(data.error);
if (!data.streams) throw new NotFoundError('No streams found in response');
const captions =
data.subtitles?.map((sub: { file: string; label: string }) => ({
id: sub.label,
url: sub.file,
language: languageMap[sub.label.toLowerCase()] || 'unknown',
type: 'srt',
})) || [];
const qualityMap: Record<string, { type: string; url: string }> = {};
Object.entries(data.streams).forEach(([key, value]) => {
const normalizedKey = key.toLowerCase().replace('p', '');
qualityMap[normalizedKey] = {
type: 'mp4',
url: value as string,
};
});
return {
stream: [
{
id: 'primary',
captions,
qualities: qualityMap,
type: 'file',
flags: [flags.CORS_ALLOWED],
},
],
};
},
});
export const xprimeMarantEmbed = makeEmbed({
id: 'xprime-marant',
name: 'Marant (French + English)',
rank: 240,
async scrape(ctx): Promise<EmbedOutput> {
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,
async scrape(ctx): Promise<EmbedOutput> {
const query = JSON.parse(ctx.url);
let url = `${primenetBaseUrl}?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,
async scrape(ctx): Promise<EmbedOutput> {
const query = JSON.parse(ctx.url);
let url = `${volkswagenBaseUrl}?name=${query.title}`;
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.streams) throw new NotFoundError('No streams found in response');
const qualityMap: Record<string, { type: string; url: string }> = {};
Object.entries(data.streams).forEach(([key, value]) => {
const normalizedKey = key.toLowerCase().replace('p', '');
qualityMap[normalizedKey] = {
type: 'mp4',
url: value as string,
};
});
ctx.progress(90);
return {
stream: [
{
id: 'primary',
type: 'file',
flags: [flags.CORS_ALLOWED],
qualities: qualityMap,
captions: [],
},
],
};
},
});