diff --git a/src/providers/all.ts b/src/providers/all.ts index 0d76f17..d1cf886 100644 --- a/src/providers/all.ts +++ b/src/providers/all.ts @@ -220,5 +220,6 @@ export function gatherAllEmbeds(): Array { streamwishEnglishScraper, streamtapeLatinoScraper, ...cinemaosEmbeds, + // ...cinemaosHexaEmbeds, ]; } diff --git a/src/providers/embeds/cinemaos.ts b/src/providers/embeds/cinemaos.ts index 7c53cb8..628b5c0 100644 --- a/src/providers/embeds/cinemaos.ts +++ b/src/providers/embeds/cinemaos.ts @@ -1,13 +1,14 @@ import { flags } from '@/entrypoint/utils/targets'; import { EmbedOutput, makeEmbed } from '@/providers/base'; import { NotFoundError } from '@/utils/errors'; +import { createM3U8ProxyUrl } from '@/utils/proxy'; -const CINEMAOS_API = 'https://cinemaos-v3.vercel.app/api/neo/backendfetch'; +const CINEMAOS_API = atob('aHR0cHM6Ly9jaW5lbWFvcy12My52ZXJjZWwuYXBwL2FwaS9uZW8vYmFja2VuZGZldGNo'); export function makeCinemaOSEmbed(server: string, rank: number) { return makeEmbed({ id: `cinemaos-${server}`, - name: `CinemaOS: ${server.charAt(0).toUpperCase() + server.slice(1)}`, + name: `${server.charAt(0).toUpperCase() + server.slice(1)}`, rank, async scrape(ctx): Promise { const query = JSON.parse(ctx.url); @@ -22,6 +23,9 @@ export function makeCinemaOSEmbed(server: string, rank: number) { if (!sources || !Array.isArray(sources) || sources.length === 0) { throw new NotFoundError('No sources found'); } + + ctx.progress(80); + // If only one source, return as a single HLS stream if (sources.length === 1) { return { @@ -37,11 +41,17 @@ export function makeCinemaOSEmbed(server: string, rank: number) { }; } // If multiple sources, treat as file with qualities - const qualityMap: Record = {}; + const qualityMap: Record = {}; for (const src of sources) { - // Use quality or source as the key, fallback to 'unknown' - const key = (src.quality || src.source || 'unknown').toString(); - qualityMap[key] = { + const quality = (src.quality || src.source || 'unknown').toString(); + let qualityKey: number; + if (quality === '4K') { + qualityKey = 2160; + } else { + qualityKey = parseInt(quality.replace('P', ''), 10); + } + if (Number.isNaN(qualityKey) || qualityMap[qualityKey]) continue; + qualityMap[qualityKey] = { type: 'mp4', url: src.url, }; @@ -63,28 +73,66 @@ export function makeCinemaOSEmbed(server: string, rank: number) { // List of supported servers and their ranks (descending order) const CINEMAOS_SERVERS = [ - 'flowcast', + // 'flowcast', 'shadow', 'asiacloud', - 'hindicast', - 'anime', - 'animez', - 'guard', - 'hq', - 'ninja', - 'alpha', - 'kaze', - 'zenith', - 'cast', - 'ghost', - 'halo', - 'kinoecho', - 'ee3', - 'volt', - 'putafilme', + // 'hindicast', + // 'anime', + // 'animez', + // 'guard', + // 'hq', + // 'ninja', + // 'alpha', + // 'kaze', + // 'zenith', + // 'cast', + // 'ghost', + // 'halo', + // 'kinoecho', + // 'ee3', + // 'volt', + // 'putafilme', 'ophim', - 'kage', + // 'kage', ]; -// Export all embeds export const cinemaosEmbeds = CINEMAOS_SERVERS.map((server, i) => makeCinemaOSEmbed(server, 300 - i)); + +export function makeCinemaOSHexaEmbed(id: string, rank: number = 100) { + return makeEmbed({ + id: `cinemaos-hexa-${id}`, + name: `Hexa ${id.charAt(0).toUpperCase() + id.slice(1)}`, + disabled: true, + rank, + async scrape(ctx): Promise { + const query = JSON.parse(ctx.url); + const directUrl = query.directUrl; + if (!directUrl) { + throw new NotFoundError('No directUrl provided for Hexa embed'); + } + + // Headers needed for the M3U8 proxy + const headers = { + referer: 'https://megacloud.store/', + origin: 'https://megacloud.store', + }; + + return { + stream: [ + { + id: 'primary', + type: 'hls', + playlist: createM3U8ProxyUrl(directUrl, headers), + flags: [flags.CORS_ALLOWED], + captions: [], + }, + ], + }; + }, + }); +} + +// List of all Hexa servers and their rank (descending order) +export const HEXA_SERVERS = ['alpha', 'bravo', 'charlie', 'delta', 'echo', 'foxtrot', 'golf', 'hotel', 'india']; + +export const cinemaosHexaEmbeds = HEXA_SERVERS.map((server, i) => makeCinemaOSHexaEmbed(server, 315 - i)); diff --git a/src/providers/sources/cinemaos.ts b/src/providers/sources/cinemaos.ts index c357e6e..894b870 100644 --- a/src/providers/sources/cinemaos.ts +++ b/src/providers/sources/cinemaos.ts @@ -2,6 +2,8 @@ import { flags } from '@/entrypoint/utils/targets'; import { SourcererOutput, makeSourcerer } from '@/providers/base'; import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context'; +// const baseUrl = atob('aHR0cHM6Ly9jaW5lbWFvcy12My52ZXJjZWwuYXBwLw=='); + const CINEMAOS_SERVERS = [ // 'flowcast', 'shadow', @@ -15,30 +17,19 @@ const CINEMAOS_SERVERS = [ // 'alpha', // 'kaze', // 'zenith', - 'cast', + // 'cast', // 'ghost', - 'halo', - 'kinoecho', + // 'halo', + // 'kinoecho', // 'ee3', - 'volt', + // 'volt', // 'putafilme', 'ophim', // 'kage', ]; async function comboScraper(ctx: ShowScrapeContext | MovieScrapeContext): Promise { - const res = await ctx.proxiedFetcher( - 'https://cinemaos-v3.vercel.app/api/neo/backendfetch?requestID=VideoProviderServices', - ); - let availableServers = []; - try { - const data = typeof res === 'string' ? JSON.parse(res) : res; - availableServers = Array.isArray(data?.data) ? data.data : []; - } catch (e) { - availableServers = []; - } - - const filteredServers = availableServers.filter((server: string) => CINEMAOS_SERVERS.includes(server)); + const embeds = []; const query: any = { type: ctx.media.type, @@ -50,14 +41,39 @@ async function comboScraper(ctx: ShowScrapeContext | MovieScrapeContext): Promis query.episode = ctx.media.episode.number; } - const embeds = filteredServers.map((server: string) => ({ - embedId: `cinemaos-${server}`, - url: JSON.stringify({ ...query, service: server }), - })); + // // V2 Embeds / Hexa + // try { + // const hexaUrl = `api/hexa?type=${query.type}&tmdbId=${query.tmdbId}`; + // const hexaRes = await ctx.proxiedFetcher(hexaUrl, { baseUrl }); + // const hexaData = typeof hexaRes === 'string' ? JSON.parse(hexaRes) : hexaRes; + // if (hexaData && hexaData.sources && typeof hexaData.sources === 'object') { + // for (const [key, value] of Object.entries(hexaData.sources)) { + // if (value && value.url) { + // embeds.push({ + // embedId: `cinemaos-hexa-${key}`, + // url: JSON.stringify({ ...query, service: `hexa-${key}`, directUrl: value.url }), + // }); + // } + // } + // } + // } catch (e: any) { + // // eslint-disable-next-line no-console + // console.error('Failed to fetch hexa sources'); + // } + + // V3 Embeds + for (const server of CINEMAOS_SERVERS) { + embeds.push({ + embedId: `cinemaos-${server}`, + url: JSON.stringify({ ...query, service: server }), + }); + } // eslint-disable-next-line no-console console.log(embeds); + ctx.progress(50); + return { embeds }; } diff --git a/src/utils/valid.ts b/src/utils/valid.ts index b6f2da2..6d9466d 100644 --- a/src/utils/valid.ts +++ b/src/utils/valid.ts @@ -11,6 +11,7 @@ import { oneServerPrimeboxEmbed, oneServerVidsrcsuEmbed, } from '@/providers/embeds/1server'; +import { cinemaosHexaEmbeds } from '@/providers/embeds/cinemaos'; import { ConsumetStreamSBScraper, ConsumetStreamTapeScraper, @@ -87,6 +88,7 @@ const SKIP_VALIDATION_CHECK_IDS = [ oneServerAnimepaheEmbed.id, oneServerAnizoneEmbed.id, wecimaScraper.id, + ...cinemaosHexaEmbeds.map((e) => e.id), ]; export function isValidStream(stream: Stream | undefined): boolean {