From c6f259bd3dd460985be2603e23febb5ab59b9312 Mon Sep 17 00:00:00 2001 From: Pas <74743263+Pasithea0@users.noreply.github.com> Date: Sun, 10 Aug 2025 14:49:11 -0600 Subject: [PATCH] update zunime --- src/providers/all.ts | 4 ++ src/providers/embeds/zunime.ts | 85 ++++----------------------------- src/providers/sources/zunime.ts | 50 +++++++++++++++++-- 3 files changed, 57 insertions(+), 82 deletions(-) diff --git a/src/providers/all.ts b/src/providers/all.ts index f295c6c..cab6dc9 100644 --- a/src/providers/all.ts +++ b/src/providers/all.ts @@ -61,6 +61,7 @@ import { viperScraper } from './embeds/viper'; import { warezcdnembedHlsScraper } from './embeds/warezcdn/hls'; import { warezcdnembedMp4Scraper } from './embeds/warezcdn/mp4'; import { warezPlayerScraper } from './embeds/warezcdn/warezplayer'; +import { zunimeEmbeds } from './embeds/zunime'; import { EightStreamScraper } from './sources/8stream'; import { animeflvScraper } from './sources/animeflv'; import { cinemaosScraper } from './sources/cinemaos'; @@ -81,6 +82,7 @@ import { vidapiClickScraper } from './sources/vidapiclick'; import { vidifyScraper } from './sources/vidify'; import { warezcdnScraper } from './sources/warezcdn'; import { wecimaScraper } from './sources/wecima'; +import { zunimeScraper } from './sources/zunime'; export function gatherAllSources(): Array { // all sources are gathered here @@ -119,6 +121,7 @@ export function gatherAllSources(): Array { rgshowsScraper, vidifyScraper, rivestreamScraper, + zunimeScraper, ]; } @@ -174,5 +177,6 @@ export function gatherAllEmbeds(): Array { madplayNsapiVidFastEmbed, ...vidifyEmbeds, ...rivestreamEmbeds, + ...zunimeEmbeds, ]; } diff --git a/src/providers/embeds/zunime.ts b/src/providers/embeds/zunime.ts index 7524610..a0329a2 100644 --- a/src/providers/embeds/zunime.ts +++ b/src/providers/embeds/zunime.ts @@ -1,70 +1,8 @@ -/* eslint-disable no-console */ -import { flags } from '@/entrypoint/utils/targets'; import { NotFoundError } from '@/utils/errors'; -// import { createM3U8ProxyUrl } from '@/utils/proxy'; import { EmbedOutput, makeEmbed } from '../base'; -const ZUNIME_SERVERS = ['hd-2', 'miko', 'shiro', 'zaza'] as const; - -const M3U8_URL_REGEX = /https?:\/\/[^\s"'<>]+?\.m3u8[^\s"'<>]*/i; - -function extractFromString(input: string): string | null { - const match = input.match(M3U8_URL_REGEX); - return match ? match[0] : null; -} - -function findFirstM3U8Url(input: unknown): string | null { - // eslint-disable-next-line no-console - console.log(input); - const visited = new Set(); - - function dfs(node: unknown): string | null { - if (node == null) return null; - if (visited.has(node)) return null; - if (typeof node === 'object') visited.add(node); - - if (typeof node === 'string') return extractFromString(node); - - if (Array.isArray(node)) { - for (const element of node) { - const found = dfs(element); - if (found) return found; - } - return null; - } - - if (typeof node === 'object') { - for (const value of Object.values(node as Record)) { - if (typeof value === 'string') { - const foundInString = extractFromString(value); - if (foundInString) return foundInString; - } else { - const found = dfs(value); - if (found) return found; - } - } - } - return null; - } - - return dfs(input); -} - -function getFirstM3U8FromSources(sources: any): string | null { - if (Array.isArray(sources)) { - for (const source of sources) { - if (typeof source?.url === 'string' && source.url.includes('.m3u8')) { - return source.url; - } - } - return null; - } - if (typeof sources?.url === 'string' && sources.url.includes('.m3u8')) { - return sources.url; - } - return null; -} +const ZUNIME_SERVERS = ['hd-2', 'miko', 'shiro', 'zaza']; const baseUrl = 'https://backend.xaiby.sbs'; const headers = { @@ -83,9 +21,7 @@ export function makeZunimeEmbed(id: string, rank: number = 100) { const serverName = id as (typeof ZUNIME_SERVERS)[number]; const query = JSON.parse(ctx.url); - const { type, malId, episode } = query; - - if (type !== 'movie' && type !== 'show') throw new NotFoundError('Unsupported media type'); + const { malId, episode } = query; const res = await ctx.proxiedFetcher(`${'/sources'}`, { baseUrl, @@ -98,21 +34,16 @@ export function makeZunimeEmbed(id: string, rank: number = 100) { }, }); - console.log('Zunime API Response:', JSON.stringify(res, null, 2)); const resAny: any = res as any; - const playlistUrl: string | null = - getFirstM3U8FromSources(resAny?.sources) ?? - (typeof resAny?.url === 'string' && resAny.url.includes('.m3u8') ? resAny.url : null) ?? - findFirstM3U8Url(resAny); - - console.log('Extracted playlistUrl:', playlistUrl); // silly debugging heheh + if (!resAny?.success || !resAny?.sources?.url) { + throw new NotFoundError('No stream URL found in response'); + } + const streamUrl = resAny.sources.url; const upstreamHeaders: Record = resAny?.sources?.headers && Object.keys(resAny.sources.headers).length > 0 ? resAny.sources.headers : headers; - if (!playlistUrl) throw new NotFoundError('No playlist URL found'); - ctx.progress(100); return { @@ -120,9 +51,9 @@ export function makeZunimeEmbed(id: string, rank: number = 100) { { id: 'primary', type: 'hls', - playlist: `https://proxy-2.madaraverse.online/proxy?url=${encodeURIComponent(playlistUrl)}`, + playlist: `https://proxy-2.madaraverse.online/proxy?url=${encodeURIComponent(streamUrl)}`, headers: upstreamHeaders, - flags: [flags.CORS_ALLOWED], + flags: [], captions: [], }, ], diff --git a/src/providers/sources/zunime.ts b/src/providers/sources/zunime.ts index 0ade1ce..b1b3333 100644 --- a/src/providers/sources/zunime.ts +++ b/src/providers/sources/zunime.ts @@ -1,10 +1,50 @@ -import { flags } from '@/entrypoint/utils/targets'; -import { makeMalSource } from '@/providers/sources/_helpers/mal'; +import { SourcererOutput, makeSourcerer } from '@/providers/base'; +import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context'; +import { getMalIdFromMedia } from '@/utils/mal'; -export const zunimeScraper = makeMalSource({ +async function comboScraper(ctx: ShowScrapeContext | MovieScrapeContext): Promise { + const malId = await getMalIdFromMedia(ctx, ctx.media); + + const query: any = { + type: ctx.media.type, + title: ctx.media.title, + tmdbId: ctx.media.tmdbId, + imdbId: ctx.media.imdbId, + malId, + ...(ctx.media.type === 'show' && { + season: ctx.media.season.number, + episode: ctx.media.episode.number, + }), + ...(ctx.media.type === 'movie' && { episode: 1 }), + releaseYear: ctx.media.releaseYear, + }; + + return { + embeds: [ + { + embedId: 'zunime-hd-2', + url: JSON.stringify(query), + }, + { + embedId: 'zunime-miko', + url: JSON.stringify(query), + }, + { + embedId: 'zunime-shiro', + url: JSON.stringify(query), + }, + { + embedId: 'zunime-zaza', + url: JSON.stringify(query), + }, + ], + }; +} + +export const zunimeScraper = makeSourcerer({ id: 'zunime', name: 'Zunime', rank: 125, - embedIds: ['zunime-hd-2', 'zunime-miko', 'zunime-shiro', 'zunime-zaza'], - flags: [flags.CORS_ALLOWED], + flags: [], + scrapeShow: comboScraper, });