diff --git a/src/controllers/episodes/getEpisodeUrl/index.ts b/src/controllers/episodes/getEpisodeUrl/index.ts index d330af3..310c334 100644 --- a/src/controllers/episodes/getEpisodeUrl/index.ts +++ b/src/controllers/episodes/getEpisodeUrl/index.ts @@ -2,17 +2,21 @@ import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi"; import { readEnvVariable } from "~/libs/readEnvVariable"; import type { Env } from "~/types/env"; -import { - FetchUrlResponse, - FetchUrlResponseSchema, -} from "~/types/episode/fetch-url-response"; +import type { Episode } from "~/types/episode"; +import { FetchUrlResponse } from "~/types/episode/fetch-url-response"; import { AniListIdQuerySchema, + EpisodeNumberSchema, ErrorResponse, ErrorResponseSchema, } from "~/types/schema"; -const FetchUrlRequest = z.object({ id: z.string(), provider: z.string() }); +import { fetchEpisodesFromAllProviders } from "../getByAniListId"; + +const FetchUrlRequest = z.union([ + z.object({ id: z.string(), provider: z.string() }), + z.object({ episodeNumber: EpisodeNumberSchema }), +]); const route = createRoute({ tags: ["aniplay", "episodes"], @@ -68,12 +72,54 @@ const route = createRoute({ const app = new OpenAPIHono(); +export async function fetchEpisodeUrlFromAllProviders( + aniListId: number, + episodeNumber: number, + isAnifyEnabled: boolean, +) { + const results = await fetchEpisodesFromAllProviders( + aniListId, + isAnifyEnabled, + ); + if (results.length === 0) { + return { episodes: null, fetchUrlResult: null }; + } + + let episodes: Episode[] | null = null; + let fetchUrlResult: FetchUrlResponse | null = null; + + for (const { episodes: episodesResult, providerId } of results) { + const episode = episodesResult.find( + (episode) => episode.number === episodeNumber, + ); + if (!episode) { + continue; + } + episodes = episodesResult; + + const urlResult = await fetchEpisodeUrl( + providerId, + episode.id, + aniListId, + isAnifyEnabled, + ); + if (!urlResult) { + continue; + } + + fetchUrlResult = urlResult; + break; + } + + return { episodes, fetchUrlResult }; +} + export async function fetchEpisodeUrl( provider: string, id: string, aniListId: number, isAnifyEnabled: boolean, -) { +): Promise { if (provider === "consumet" || !isAnifyEnabled) { try { const result = await import("./consumet").then( @@ -126,16 +172,29 @@ export async function fetchEpisodeUrl( app.openapi(route, async (c) => { const aniListId = Number(c.req.param("aniListId")); - const { provider, id } = await c.req.json(); + const { provider, id, episodeNumber } = + await c.req.json(); + if (!provider && episodeNumber == undefined) { + return c.json(ErrorResponse, { status: 400 }); + } try { const isAnifyEnabled = readEnvVariable(c.env, "ENABLE_ANIFY"); - const result = await fetchEpisodeUrl( - provider, - id, - aniListId, - isAnifyEnabled, - ); + let result: FetchUrlResponse | null; + if (provider) { + result = await fetchEpisodeUrl(provider, id, aniListId, isAnifyEnabled); + } else { + const { fetchUrlResult } = await fetchEpisodeUrlFromAllProviders( + aniListId, + episodeNumber!, + isAnifyEnabled, + ); + if (!fetchUrlResult) { + return c.json(ErrorResponse, { status: 404 }); + } + + result = fetchUrlResult; + } if (result) { return c.json({ success: true, result });