manual matching survives ttl now
This commit is contained in:
@@ -361,15 +361,36 @@ export async function searchEpisodesInExtension(ext: Extension | null, name: str
|
|||||||
if (cached) {
|
if (cached) {
|
||||||
const isExpired = Date.now() - cached.created_at > CACHE_TTL_MS;
|
const isExpired = Date.now() - cached.created_at > CACHE_TTL_MS;
|
||||||
|
|
||||||
if (!isExpired) {
|
try {
|
||||||
console.log(`[${name}] Episodes cache hit for: ${query}`);
|
const parsed = JSON.parse(cached.result) as {
|
||||||
try {
|
mediaId?: string;
|
||||||
return JSON.parse(cached.result) as Episode[];
|
episodes: Episode[];
|
||||||
} catch (e) {
|
};
|
||||||
console.error(`[${name}] Error parsing cached episodes:`, e);
|
|
||||||
|
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);
|
const chapterList = await ext.findEpisodes(mediaId);
|
||||||
if (!Array.isArray(chapterList)) return [];
|
if (!Array.isArray(chapterList)) return [];
|
||||||
|
|
||||||
const result: Episode[] = chapterList.map(ep => ({
|
const result: Episode[] = chapterList.map(ep => ({
|
||||||
id: ep.id,
|
id: ep.id,
|
||||||
number: ep.number,
|
number: ep.number,
|
||||||
@@ -429,7 +451,8 @@ export async function searchEpisodesInExtension(ext: Extension | null, name: str
|
|||||||
title: ep.title
|
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;
|
return result;
|
||||||
} catch (e) {
|
} 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");
|
throw new Error("Extension doesn't support required methods");
|
||||||
}
|
}
|
||||||
let episodes;
|
let episodes;
|
||||||
|
let animeTitle: string | undefined;
|
||||||
|
|
||||||
if (source === "anilist" && !extensionAnimeId) {
|
if (source === "anilist" && !extensionAnimeId) {
|
||||||
const anime: any = await getAnimeById(id);
|
const anime: any = await getAnimeById(id);
|
||||||
episodes = await searchEpisodesInExtension(extension, extension.constructor.name, anime.title.romaji);
|
episodes = await searchEpisodesInExtension(extension, extension.constructor.name, anime.title.romaji);
|
||||||
} else {
|
} 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) {
|
if (!targetEp) {
|
||||||
throw new Error("Episode not found");
|
throw new Error("Episode not found");
|
||||||
|
|||||||
@@ -363,20 +363,42 @@ async function fetchBookMetadata(id: string): Promise<Book | null> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function searchChaptersInExtension(ext: Extension, name: string, lookupId: string, cacheId: string, search: boolean, origin: string, disableCache = false): Promise<ChapterWithProvider[]> {
|
async function searchChaptersInExtension(ext: Extension, name: string, lookupId: string, cacheId: string, search: boolean, origin: string, disableCache = false): Promise<ChapterWithProvider[]> {
|
||||||
const cacheKey = `chapters:${name}:${origin}:${search ? "search" : "id"}:${cacheId}`;
|
const cacheKey = `chapters:${name}:${origin}:id:${cacheId}`;
|
||||||
if (!disableCache) {
|
if (!disableCache) {
|
||||||
const cached = await getCache(cacheKey);
|
const cached = await getCache(cacheKey);
|
||||||
|
|
||||||
if (cached) {
|
if (cached) {
|
||||||
const isExpired = Date.now() - cached.created_at > CACHE_TTL_MS;
|
const isExpired = Date.now() - cached.created_at > CACHE_TTL_MS;
|
||||||
|
|
||||||
if (!isExpired) {
|
try {
|
||||||
console.log(`[${name}] Chapters cache hit for: ${lookupId}`);
|
const parsed = JSON.parse(cached.result) as {
|
||||||
try {
|
mediaId?: string;
|
||||||
return JSON.parse(cached.result) as ChapterWithProvider[];
|
chapters: ChapterWithProvider[];
|
||||||
} catch (e) {
|
};
|
||||||
console.error(`[${name}] Error parsing cached chapters:`, e);
|
|
||||||
|
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,
|
language: ch.language ?? null,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
await setCache(cacheKey, result, CACHE_TTL_MS);
|
await setCache(cacheKey, {
|
||||||
|
mediaId,
|
||||||
|
chapters: result
|
||||||
|
}, CACHE_TTL_MS);
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -361,15 +361,36 @@ export async function searchEpisodesInExtension(ext: Extension | null, name: str
|
|||||||
if (cached) {
|
if (cached) {
|
||||||
const isExpired = Date.now() - cached.created_at > CACHE_TTL_MS;
|
const isExpired = Date.now() - cached.created_at > CACHE_TTL_MS;
|
||||||
|
|
||||||
if (!isExpired) {
|
try {
|
||||||
console.log(`[${name}] Episodes cache hit for: ${query}`);
|
const parsed = JSON.parse(cached.result) as {
|
||||||
try {
|
mediaId?: string;
|
||||||
return JSON.parse(cached.result) as Episode[];
|
episodes: Episode[];
|
||||||
} catch (e) {
|
};
|
||||||
console.error(`[${name}] Error parsing cached episodes:`, e);
|
|
||||||
|
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);
|
const chapterList = await ext.findEpisodes(mediaId);
|
||||||
if (!Array.isArray(chapterList)) return [];
|
if (!Array.isArray(chapterList)) return [];
|
||||||
|
|
||||||
const result: Episode[] = chapterList.map(ep => ({
|
const result: Episode[] = chapterList.map(ep => ({
|
||||||
id: ep.id,
|
id: ep.id,
|
||||||
number: ep.number,
|
number: ep.number,
|
||||||
@@ -429,7 +451,8 @@ export async function searchEpisodesInExtension(ext: Extension | null, name: str
|
|||||||
title: ep.title
|
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;
|
return result;
|
||||||
} catch (e) {
|
} 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");
|
throw new Error("Extension doesn't support required methods");
|
||||||
}
|
}
|
||||||
let episodes;
|
let episodes;
|
||||||
|
let animeTitle: string | undefined;
|
||||||
|
|
||||||
if (source === "anilist" && !extensionAnimeId) {
|
if (source === "anilist" && !extensionAnimeId) {
|
||||||
const anime: any = await getAnimeById(id);
|
const anime: any = await getAnimeById(id);
|
||||||
episodes = await searchEpisodesInExtension(extension, extension.constructor.name, anime.title.romaji);
|
episodes = await searchEpisodesInExtension(extension, extension.constructor.name, anime.title.romaji);
|
||||||
} else {
|
} 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) {
|
if (!targetEp) {
|
||||||
throw new Error("Episode not found");
|
throw new Error("Episode not found");
|
||||||
|
|||||||
@@ -363,20 +363,42 @@ async function fetchBookMetadata(id: string): Promise<Book | null> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function searchChaptersInExtension(ext: Extension, name: string, lookupId: string, cacheId: string, search: boolean, origin: string, disableCache = false): Promise<ChapterWithProvider[]> {
|
async function searchChaptersInExtension(ext: Extension, name: string, lookupId: string, cacheId: string, search: boolean, origin: string, disableCache = false): Promise<ChapterWithProvider[]> {
|
||||||
const cacheKey = `chapters:${name}:${origin}:${search ? "search" : "id"}:${cacheId}`;
|
const cacheKey = `chapters:${name}:${origin}:id:${cacheId}`;
|
||||||
if (!disableCache) {
|
if (!disableCache) {
|
||||||
const cached = await getCache(cacheKey);
|
const cached = await getCache(cacheKey);
|
||||||
|
|
||||||
if (cached) {
|
if (cached) {
|
||||||
const isExpired = Date.now() - cached.created_at > CACHE_TTL_MS;
|
const isExpired = Date.now() - cached.created_at > CACHE_TTL_MS;
|
||||||
|
|
||||||
if (!isExpired) {
|
try {
|
||||||
console.log(`[${name}] Chapters cache hit for: ${lookupId}`);
|
const parsed = JSON.parse(cached.result) as {
|
||||||
try {
|
mediaId?: string;
|
||||||
return JSON.parse(cached.result) as ChapterWithProvider[];
|
chapters: ChapterWithProvider[];
|
||||||
} catch (e) {
|
};
|
||||||
console.error(`[${name}] Error parsing cached chapters:`, e);
|
|
||||||
|
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,
|
language: ch.language ?? null,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
await setCache(cacheKey, result, CACHE_TTL_MS);
|
await setCache(cacheKey, {
|
||||||
|
mediaId,
|
||||||
|
chapters: result
|
||||||
|
}, CACHE_TTL_MS);
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user