multi language support for books and book page redesigned
This commit is contained in:
@@ -101,12 +101,14 @@ export async function getChapterContent(req: any, reply: FastifyReply) {
|
||||
try {
|
||||
const { bookId, chapter, provider } = req.params;
|
||||
const source = req.query.source || 'anilist';
|
||||
const lang = req.query.lang || 'none';
|
||||
|
||||
const content = await booksService.getChapterContent(
|
||||
bookId,
|
||||
chapter,
|
||||
provider,
|
||||
source
|
||||
source,
|
||||
lang
|
||||
);
|
||||
|
||||
return reply.send(content);
|
||||
|
||||
@@ -67,7 +67,19 @@ export async function getBookById(id: string | number): Promise<Book | { error:
|
||||
);
|
||||
|
||||
if (row) {
|
||||
return JSON.parse(row.full_data);
|
||||
const parsed = JSON.parse(row.full_data);
|
||||
|
||||
const hasRelationImages =
|
||||
parsed?.relations?.edges?.[0]?.node?.coverImage?.large;
|
||||
|
||||
const hasCharacterImages =
|
||||
parsed?.characters?.nodes?.[0]?.image?.large;
|
||||
|
||||
if (hasRelationImages && hasCharacterImages) {
|
||||
return parsed;
|
||||
}
|
||||
|
||||
console.log(`[Book] Cache outdated for ID ${id}, refetching...`);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -82,8 +94,8 @@ export async function getBookById(id: string | number): Promise<Book | { error:
|
||||
trailer { id site thumbnail } updatedAt coverImage { extraLarge large medium color }
|
||||
bannerImage genres synonyms averageScore meanScore popularity isLocked trending favourites
|
||||
tags { id name description category rank isGeneralSpoiler isMediaSpoiler isAdult userId }
|
||||
relations { edges { relationType node { id title { romaji } } } }
|
||||
characters(page: 1, perPage: 10) { nodes { id name { full } } }
|
||||
relations { edges { relationType node { id title { romaji } coverImage { large medium } } } }
|
||||
characters(page: 1, perPage: 10) { nodes { id name { full } image { large medium } } }
|
||||
studios { nodes { id name isAnimationStudio } }
|
||||
isAdult nextAiringEpisode { airingAt timeUntilAiring episode }
|
||||
externalLinks { url site }
|
||||
@@ -406,7 +418,8 @@ async function searchChaptersInExtension(ext: Extension, name: string, searchTit
|
||||
title: ch.title,
|
||||
date: ch.releaseDate,
|
||||
provider: name,
|
||||
index: ch.index
|
||||
index: ch.index,
|
||||
language: ch.language ?? null,
|
||||
}));
|
||||
|
||||
await setCache(cacheKey, result, CACHE_TTL_MS);
|
||||
@@ -463,7 +476,7 @@ export async function getChaptersForBook(id: string, ext: Boolean, onlyProvider?
|
||||
};
|
||||
}
|
||||
|
||||
export async function getChapterContent(bookId: string, chapterIndex: string, providerName: string, source: string): Promise<ChapterContent> {
|
||||
export async function getChapterContent(bookId: string, chapterId: string, providerName: string, source: string, lang: string): Promise<ChapterContent> {
|
||||
const extensions = getAllExtensions();
|
||||
const ext = extensions.get(providerName);
|
||||
|
||||
@@ -471,14 +484,14 @@ export async function getChapterContent(bookId: string, chapterIndex: string, pr
|
||||
throw new Error("Provider not found");
|
||||
}
|
||||
|
||||
const contentCacheKey = `content:${providerName}:${source}:${bookId}:${chapterIndex}`;
|
||||
const contentCacheKey = `content:${providerName}:${source}:${lang}:${bookId}:${chapterId}`;
|
||||
const cachedContent = await getCache(contentCacheKey);
|
||||
|
||||
if (cachedContent) {
|
||||
const isExpired = Date.now() - cachedContent.created_at > CACHE_TTL_MS;
|
||||
|
||||
if (!isExpired) {
|
||||
console.log(`[${providerName}] Content cache hit for Book ID ${bookId}, Index ${chapterIndex}`);
|
||||
console.log(`[${providerName}] Content cache hit for Book ID ${bookId}, Index ${chapterId}`);
|
||||
try {
|
||||
return JSON.parse(cachedContent.result) as ChapterContent;
|
||||
} catch (e) {
|
||||
@@ -486,33 +499,14 @@ export async function getChapterContent(bookId: string, chapterIndex: string, pr
|
||||
|
||||
}
|
||||
} else {
|
||||
console.log(`[${providerName}] Content cache expired for Book ID ${bookId}, Index ${chapterIndex}`);
|
||||
console.log(`[${providerName}] Content cache expired for Book ID ${bookId}, Index ${chapterId}`);
|
||||
}
|
||||
}
|
||||
|
||||
const isExternal = source !== 'anilist';
|
||||
const chapterList = await getChaptersForBook(bookId, isExternal, providerName);
|
||||
|
||||
if (!chapterList?.chapters || chapterList.chapters.length === 0) {
|
||||
throw new Error("Chapters not found");
|
||||
}
|
||||
|
||||
const providerChapters = chapterList.chapters.filter(c => c.provider === providerName);
|
||||
const index = parseInt(chapterIndex, 10);
|
||||
|
||||
if (Number.isNaN(index)) {
|
||||
throw new Error("Invalid chapter index");
|
||||
}
|
||||
|
||||
if (!providerChapters[index]) {
|
||||
throw new Error("Chapter index out of range");
|
||||
}
|
||||
|
||||
const selectedChapter = providerChapters[index];
|
||||
|
||||
const chapterId = selectedChapter.id;
|
||||
const chapterTitle = selectedChapter.title || null;
|
||||
const chapterNumber = typeof selectedChapter.number === 'number' ? selectedChapter.number : index;
|
||||
const selectedChapter: any = {
|
||||
id: chapterId,
|
||||
provider: providerName
|
||||
};
|
||||
|
||||
try {
|
||||
if (!ext.findChapterPages) {
|
||||
@@ -522,12 +516,13 @@ export async function getChapterContent(bookId: string, chapterIndex: string, pr
|
||||
let contentResult: ChapterContent;
|
||||
|
||||
if (ext.mediaType === "manga") {
|
||||
// Usamos el ID directamente
|
||||
const pages = await ext.findChapterPages(chapterId);
|
||||
contentResult = {
|
||||
type: "manga",
|
||||
chapterId,
|
||||
title: chapterTitle,
|
||||
number: chapterNumber,
|
||||
chapterId: selectedChapter.id,
|
||||
title: selectedChapter.title,
|
||||
number: selectedChapter.number,
|
||||
provider: providerName,
|
||||
pages
|
||||
};
|
||||
@@ -535,9 +530,9 @@ export async function getChapterContent(bookId: string, chapterIndex: string, pr
|
||||
const content = await ext.findChapterPages(chapterId);
|
||||
contentResult = {
|
||||
type: "ln",
|
||||
chapterId,
|
||||
title: chapterTitle,
|
||||
number: chapterNumber,
|
||||
chapterId: selectedChapter.id,
|
||||
title: selectedChapter.title,
|
||||
number: selectedChapter.number,
|
||||
provider: providerName,
|
||||
content
|
||||
};
|
||||
@@ -546,7 +541,6 @@ export async function getChapterContent(bookId: string, chapterIndex: string, pr
|
||||
}
|
||||
|
||||
await setCache(contentCacheKey, contentResult, CACHE_TTL_MS);
|
||||
|
||||
return contentResult;
|
||||
|
||||
} catch (err) {
|
||||
|
||||
@@ -79,6 +79,7 @@ export interface Episode {
|
||||
}
|
||||
|
||||
export interface Chapter {
|
||||
language?: string | null;
|
||||
index: number;
|
||||
id: string;
|
||||
number: string | number;
|
||||
|
||||
Reference in New Issue
Block a user