From d1306f06bafe631d877045234e5725aa4a33925b Mon Sep 17 00:00:00 2001 From: Rushil Perera Date: Thu, 6 Mar 2025 09:35:10 -0500 Subject: [PATCH] Improves episode source retrieval from Aniwatch Refactors episode source fetching to handle multiple servers. It now attempts to retrieve the episode URL from multiple servers if the initial request fails, improving the chances of finding a valid source. --- .../episodes/getEpisodeUrl/aniwatch.ts | 71 ++++++++++++++++++- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/src/controllers/episodes/getEpisodeUrl/aniwatch.ts b/src/controllers/episodes/getEpisodeUrl/aniwatch.ts index 1c8ddb7..92305a8 100644 --- a/src/controllers/episodes/getEpisodeUrl/aniwatch.ts +++ b/src/controllers/episodes/getEpisodeUrl/aniwatch.ts @@ -5,9 +5,33 @@ export async function getSourcesFromAniwatch( watchId: string, ): Promise { console.log(`Fetching sources from aniwatch for ${watchId}`); - const { source, intro, outro, subtitles } = await fetch( - `https://aniwatch.up.railway.app/api/v2/hianime/episode/sources?animeEpisodeId=${encodeURIComponent(watchId)}`, - ) + const url = await getEpisodeUrl(watchId); + if (url) { + return url; + } + + const servers = await getEpisodeServers(watchId); + if (servers.length === 0) { + return null; + } + + for (const server of servers) { + const url = await getEpisodeUrl(watchId, server.serverName); + if (url) { + return url; + } + } + + return null; +} + +async function getEpisodeUrl(watchId: string, server?: string) { + let url = `https://aniwatch.up.railway.app/api/v2/hianime/episode/sources?animeEpisodeId=${encodeURIComponent(watchId)}`; + if (server) { + url += `&server=${encodeURIComponent(server)}`; + } + + const { source, intro, outro, subtitles } = await fetch(url) .then( (res) => res.json() as Promise<{ @@ -44,6 +68,24 @@ export async function getSourcesFromAniwatch( }; } +async function getEpisodeServers(watchId: string) { + const { data } = await fetch( + `https://aniwatch.up.railway.app/api/v2/hianime/episode/servers?animeEpisodeId=${encodeURIComponent( + watchId, + )}`, + ) + .then((res) => res.json() as Promise) + .then((res) => { + if (!res.success) { + throw new Error(res.message); + } + + return res; + }); + + return data.sub; +} + interface AniwatchEpisodeUrlResponse { tracks: Track[]; intro: SkipTime; @@ -64,3 +106,26 @@ interface Track { kind: string; default?: boolean; } + +type AniwatchEpisodeServersResponse = + | { + success: true; + data: AniwatchEpisodeServers; + } + | { + success: false; + message: string; + }; + +interface AniwatchEpisodeServers { + sub: AniwatchEpisodeServer[]; + dub: AniwatchEpisodeServer[]; + raw: AniwatchEpisodeServer[]; + episodeID: string; + episodeNo: number; +} + +interface AniwatchEpisodeServer { + serverName: string; + serverID: number; +}