diff --git a/src/api/anilist/anilist.service.ts b/src/api/anilist/anilist.service.ts index 32ca5d6..842cf6f 100644 --- a/src/api/anilist/anilist.service.ts +++ b/src/api/anilist/anilist.service.ts @@ -517,8 +517,13 @@ export async function getSingleAniListEntry( }) }); + if (res.status === 404) { + return null; // ✅ No existe entry todavía → es totalmente válido + } + if (!res.ok) { - throw new Error(`Failed to fetch entry: ${res.status}`); + const errorText = await res.text(); + throw new Error(`AniList fetch failed: ${res.status} - ${errorText}`); } const json = await res.json(); diff --git a/src/api/list/list.controller.ts b/src/api/list/list.controller.ts index 3490c04..9234dc9 100644 --- a/src/api/list/list.controller.ts +++ b/src/api/list/list.controller.ts @@ -5,16 +5,6 @@ interface UserRequest extends FastifyRequest { user?: { id: number }; } -interface UpsertEntryBody { - entry_type: any; - entry_id: number; - external_id?: string | null; - source: string; - status: string; - progress: number; - score: number; -} - interface EntryParams { entryId: string; diff --git a/src/api/list/list.service.ts b/src/api/list/list.service.ts index 4a3b000..9cc4aae 100644 --- a/src/api/list/list.service.ts +++ b/src/api/list/list.service.ts @@ -35,21 +35,60 @@ export async function upsertListEntry(entry: any) { is_private } = entry; + let prev: any = null; + + try { + prev = await getSingleListEntry(user_id, entry_id, source, entry_type); + } catch { + prev = null; // ✅ si AniList da 404 u otro error → se trata como nuevo + } + + const isNew = !prev; + +// ✅ NO permitir retroceso SOLO si ya existía + if (!isNew && prev?.progress != null && progress < prev.progress) { + return { changes: 0, ignored: true }; + } + + const today = new Date().toISOString().slice(0, 10); + +// ✅ NUNCA borrar start_date si ya existía + if (prev?.start_date && !entry.start_date) { + entry.start_date = prev.start_date; + } + +// ✅ START DATE solo al comenzar de verdad + if (!prev?.start_date && progress === 1) { + entry.start_date = today; + } + +// ✅ TOTAL solo si existe + const total = + prev?.total_episodes ?? + prev?.total_chapters ?? + null; + +// ✅ COMPLETED automático + if (total && progress >= total) { + entry.status = 'COMPLETED'; + entry.end_date = today; + } + if (source === 'anilist') { const token = await getActiveAccessToken(user_id); if (token) { try { const result = await aniListService.updateAniListEntry(token, { - mediaId: entry_id, - status, - progress, - score, - start_date, - end_date, - repeat_count, - notes, - is_private + mediaId: entry.entry_id, + status: entry.status, + progress: entry.progress, + score: entry.score, + start_date: entry.start_date, + end_date: entry.end_date, + repeat_count: entry.repeat_count, + notes: entry.notes, + is_private: entry.is_private }); @@ -85,20 +124,21 @@ export async function upsertListEntry(entry: any) { `; const params = [ - user_id, - entry_id, - source, - entry_type, - status, - progress, - score ?? null, - start_date || null, - end_date || null, - repeat_count ?? 0, - notes || null, - is_private ?? 0 + entry.user_id, + entry.entry_id, + entry.source, + entry.entry_type, + entry.status, + entry.progress, + entry.score ?? null, + entry.start_date || null, + entry.end_date || null, + entry.repeat_count ?? 0, + entry.notes || null, + entry.is_private ?? 0 ]; + try { const result = await run(sql, params, USER_DB); return { changes: result.changes, lastID: result.lastID, external: false }; diff --git a/src/scripts/anime/animes.js b/src/scripts/anime/animes.js index 822a697..6c7e3b0 100644 --- a/src/scripts/anime/animes.js +++ b/src/scripts/anime/animes.js @@ -117,9 +117,9 @@ function renderContinueWatching(id, list) { const ep = item.progress || 1; if (item.source === 'anilist') { - window.location.href = `http://localhost:54322/watch/${item.entry_id}/${ep}`; + window.location.href = `http://localhost:54322/watch/${item.entry_id}/${ep + 1}`; } else { - window.location.href = `http://localhost:54322/watch/${item.entry_id}/${ep}?${item.source}`; + window.location.href = `http://localhost:54322/watch/${item.entry_id}/${ep + 1}?${item.source}`; } }; diff --git a/src/scripts/books/books.js b/src/scripts/books/books.js index e8278ba..c93fb3b 100644 --- a/src/scripts/books/books.js +++ b/src/scripts/books/books.js @@ -245,9 +245,9 @@ function renderContinueReading(id, list) { const ch = item.progress || 1; if (item.source === 'anilist') { - window.location.href = `http://localhost:54322/book/${item.entry_id}?chapter=${ch}`; + window.location.href = `http://localhost:54322/book/${item.entry_id}?chapter=${ch + 1}`; } else { - window.location.href = `http://localhost:54322/read/${item.source}/${ch}/${item.entry_id}?source=${item.source}`; + window.location.href = `http://localhost:54322/read/${item.source}/${ch + 1}/${item.entry_id}?source=${item.source}`; } };