diff --git a/desktop/src/api/anime/anime.service.ts b/desktop/src/api/anime/anime.service.ts index b51432d..7e44e1c 100644 --- a/desktop/src/api/anime/anime.service.ts +++ b/desktop/src/api/anime/anime.service.ts @@ -361,15 +361,36 @@ export async function searchEpisodesInExtension(ext: Extension | null, name: str if (cached) { const isExpired = Date.now() - cached.created_at > CACHE_TTL_MS; - if (!isExpired) { - console.log(`[${name}] Episodes cache hit for: ${query}`); - try { - return JSON.parse(cached.result) as Episode[]; - } catch (e) { - console.error(`[${name}] Error parsing cached episodes:`, e); + try { + const parsed = JSON.parse(cached.result) as { + mediaId?: string; + episodes: Episode[]; + }; + + if (!isExpired) { + console.log(`[${name}] Episodes cache hit for: ${query}`); + return parsed.episodes; } - } else { - console.log(`[${name}] Episodes cache expired for: ${query}`); + + // Si el caché expiró pero tenemos mediaId, refrescamos directamente + if (parsed.mediaId && ext.type === "anime-board" && ext.search && typeof ext.findEpisodes === "function") { + console.log(`[${name}] Episodes cache expired but mediaId found, refreshing...`); + const chapterList = await ext.findEpisodes(parsed.mediaId); + + if (!Array.isArray(chapterList)) return []; + + const result: Episode[] = chapterList.map(ep => ({ + id: ep.id, + number: ep.number, + url: ep.url, + title: ep.title + })); + + await setCache(cacheKey, { mediaId: parsed.mediaId, episodes: result }, CACHE_TTL_MS); + return result; + } + } catch (e) { + console.error(`[${name}] Error parsing cached episodes:`, e); } } @@ -422,6 +443,7 @@ export async function searchEpisodesInExtension(ext: Extension | null, name: str const chapterList = await ext.findEpisodes(mediaId); if (!Array.isArray(chapterList)) return []; + const result: Episode[] = chapterList.map(ep => ({ id: ep.id, number: ep.number, @@ -429,7 +451,8 @@ export async function searchEpisodesInExtension(ext: Extension | null, name: str title: ep.title })); - await setCache(cacheKey, result, CACHE_TTL_MS); + // Cachear tanto el mediaId como los episodios + await setCache(cacheKey, { mediaId, episodes: result }, CACHE_TTL_MS); return result; } catch (e) { @@ -465,15 +488,36 @@ export async function getStreamData(extension: Extension, episode: string, id: s throw new Error("Extension doesn't support required methods"); } let episodes; + let animeTitle: string | undefined; if (source === "anilist" && !extensionAnimeId) { const anime: any = await getAnimeById(id); episodes = await searchEpisodesInExtension(extension, extension.constructor.name, anime.title.romaji); } else { - episodes = await extension.findEpisodes(extensionAnimeId ?? id); + const targetId = extensionAnimeId ?? id; + episodes = await extension.findEpisodes(targetId); + + if (extensionAnimeId) { + + const anime: any = await getAnimeById(id); + animeTitle = anime.title.romaji; + + const episodesCacheKey = `anime:episodes:${providerName}:${animeTitle}`; + const episodesResult: Episode[] = episodes.map((ep: any) => ({ + id: ep.id, + number: ep.number, + url: ep.url, + title: ep.title + })); + + await setCache(episodesCacheKey, { + mediaId: extensionAnimeId, + episodes: episodesResult + }, CACHE_TTL_MS); + } } - const targetEp = episodes.find(e => e.number === parseInt(episode)); + const targetEp = episodes.find((e: any) => e.number === parseInt(episode)); if (!targetEp) { throw new Error("Episode not found"); diff --git a/desktop/src/api/books/books.service.ts b/desktop/src/api/books/books.service.ts index 0a87060..2620039 100644 --- a/desktop/src/api/books/books.service.ts +++ b/desktop/src/api/books/books.service.ts @@ -363,20 +363,42 @@ async function fetchBookMetadata(id: string): Promise { } async function searchChaptersInExtension(ext: Extension, name: string, lookupId: string, cacheId: string, search: boolean, origin: string, disableCache = false): Promise { - const cacheKey = `chapters:${name}:${origin}:${search ? "search" : "id"}:${cacheId}`; + const cacheKey = `chapters:${name}:${origin}:id:${cacheId}`; if (!disableCache) { const cached = await getCache(cacheKey); if (cached) { const isExpired = Date.now() - cached.created_at > CACHE_TTL_MS; - if (!isExpired) { - console.log(`[${name}] Chapters cache hit for: ${lookupId}`); - try { - return JSON.parse(cached.result) as ChapterWithProvider[]; - } catch (e) { - console.error(`[${name}] Error parsing cached chapters:`, e); + try { + const parsed = JSON.parse(cached.result) as { + mediaId?: string; + chapters: ChapterWithProvider[]; + }; + + if (!isExpired) { + console.log(`[${name}] Chapters cache hit for: ${lookupId}`); + return parsed.chapters; } + + if (parsed.mediaId) { + const chaps = await ext.findChapters!(parsed.mediaId); + + const result = chaps.map(ch => ({ + id: ch.id, + number: parseFloat(ch.number.toString()), + title: ch.title, + date: ch.releaseDate, + provider: name, + index: ch.index, + language: ch.language ?? null, + })); + + await setCache(cacheKey, { mediaId: parsed.mediaId, chapters: result }, CACHE_TTL_MS); + return result; + } + } catch (e) { + console.error(`[${name}] Error parsing cached chapters:`, e); } } } @@ -436,7 +458,10 @@ async function searchChaptersInExtension(ext: Extension, name: string, lookupId: language: ch.language ?? null, })); - await setCache(cacheKey, result, CACHE_TTL_MS); + await setCache(cacheKey, { + mediaId, + chapters: result + }, CACHE_TTL_MS); return result; } catch (e) { diff --git a/docker/src/api/anime/anime.service.ts b/docker/src/api/anime/anime.service.ts index b51432d..7e44e1c 100644 --- a/docker/src/api/anime/anime.service.ts +++ b/docker/src/api/anime/anime.service.ts @@ -361,15 +361,36 @@ export async function searchEpisodesInExtension(ext: Extension | null, name: str if (cached) { const isExpired = Date.now() - cached.created_at > CACHE_TTL_MS; - if (!isExpired) { - console.log(`[${name}] Episodes cache hit for: ${query}`); - try { - return JSON.parse(cached.result) as Episode[]; - } catch (e) { - console.error(`[${name}] Error parsing cached episodes:`, e); + try { + const parsed = JSON.parse(cached.result) as { + mediaId?: string; + episodes: Episode[]; + }; + + if (!isExpired) { + console.log(`[${name}] Episodes cache hit for: ${query}`); + return parsed.episodes; } - } else { - console.log(`[${name}] Episodes cache expired for: ${query}`); + + // Si el caché expiró pero tenemos mediaId, refrescamos directamente + if (parsed.mediaId && ext.type === "anime-board" && ext.search && typeof ext.findEpisodes === "function") { + console.log(`[${name}] Episodes cache expired but mediaId found, refreshing...`); + const chapterList = await ext.findEpisodes(parsed.mediaId); + + if (!Array.isArray(chapterList)) return []; + + const result: Episode[] = chapterList.map(ep => ({ + id: ep.id, + number: ep.number, + url: ep.url, + title: ep.title + })); + + await setCache(cacheKey, { mediaId: parsed.mediaId, episodes: result }, CACHE_TTL_MS); + return result; + } + } catch (e) { + console.error(`[${name}] Error parsing cached episodes:`, e); } } @@ -422,6 +443,7 @@ export async function searchEpisodesInExtension(ext: Extension | null, name: str const chapterList = await ext.findEpisodes(mediaId); if (!Array.isArray(chapterList)) return []; + const result: Episode[] = chapterList.map(ep => ({ id: ep.id, number: ep.number, @@ -429,7 +451,8 @@ export async function searchEpisodesInExtension(ext: Extension | null, name: str title: ep.title })); - await setCache(cacheKey, result, CACHE_TTL_MS); + // Cachear tanto el mediaId como los episodios + await setCache(cacheKey, { mediaId, episodes: result }, CACHE_TTL_MS); return result; } catch (e) { @@ -465,15 +488,36 @@ export async function getStreamData(extension: Extension, episode: string, id: s throw new Error("Extension doesn't support required methods"); } let episodes; + let animeTitle: string | undefined; if (source === "anilist" && !extensionAnimeId) { const anime: any = await getAnimeById(id); episodes = await searchEpisodesInExtension(extension, extension.constructor.name, anime.title.romaji); } else { - episodes = await extension.findEpisodes(extensionAnimeId ?? id); + const targetId = extensionAnimeId ?? id; + episodes = await extension.findEpisodes(targetId); + + if (extensionAnimeId) { + + const anime: any = await getAnimeById(id); + animeTitle = anime.title.romaji; + + const episodesCacheKey = `anime:episodes:${providerName}:${animeTitle}`; + const episodesResult: Episode[] = episodes.map((ep: any) => ({ + id: ep.id, + number: ep.number, + url: ep.url, + title: ep.title + })); + + await setCache(episodesCacheKey, { + mediaId: extensionAnimeId, + episodes: episodesResult + }, CACHE_TTL_MS); + } } - const targetEp = episodes.find(e => e.number === parseInt(episode)); + const targetEp = episodes.find((e: any) => e.number === parseInt(episode)); if (!targetEp) { throw new Error("Episode not found"); diff --git a/docker/src/api/books/books.service.ts b/docker/src/api/books/books.service.ts index 0a87060..2620039 100644 --- a/docker/src/api/books/books.service.ts +++ b/docker/src/api/books/books.service.ts @@ -363,20 +363,42 @@ async function fetchBookMetadata(id: string): Promise { } async function searchChaptersInExtension(ext: Extension, name: string, lookupId: string, cacheId: string, search: boolean, origin: string, disableCache = false): Promise { - const cacheKey = `chapters:${name}:${origin}:${search ? "search" : "id"}:${cacheId}`; + const cacheKey = `chapters:${name}:${origin}:id:${cacheId}`; if (!disableCache) { const cached = await getCache(cacheKey); if (cached) { const isExpired = Date.now() - cached.created_at > CACHE_TTL_MS; - if (!isExpired) { - console.log(`[${name}] Chapters cache hit for: ${lookupId}`); - try { - return JSON.parse(cached.result) as ChapterWithProvider[]; - } catch (e) { - console.error(`[${name}] Error parsing cached chapters:`, e); + try { + const parsed = JSON.parse(cached.result) as { + mediaId?: string; + chapters: ChapterWithProvider[]; + }; + + if (!isExpired) { + console.log(`[${name}] Chapters cache hit for: ${lookupId}`); + return parsed.chapters; } + + if (parsed.mediaId) { + const chaps = await ext.findChapters!(parsed.mediaId); + + const result = chaps.map(ch => ({ + id: ch.id, + number: parseFloat(ch.number.toString()), + title: ch.title, + date: ch.releaseDate, + provider: name, + index: ch.index, + language: ch.language ?? null, + })); + + await setCache(cacheKey, { mediaId: parsed.mediaId, chapters: result }, CACHE_TTL_MS); + return result; + } + } catch (e) { + console.error(`[${name}] Error parsing cached chapters:`, e); } } } @@ -436,7 +458,10 @@ async function searchChaptersInExtension(ext: Extension, name: string, lookupId: language: ch.language ?? null, })); - await setCache(cacheKey, result, CACHE_TTL_MS); + await setCache(cacheKey, { + mediaId, + chapters: result + }, CACHE_TTL_MS); return result; } catch (e) {