fixed tracking
This commit is contained in:
@@ -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) {
|
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();
|
const json = await res.json();
|
||||||
|
|||||||
@@ -5,16 +5,6 @@ interface UserRequest extends FastifyRequest {
|
|||||||
user?: { id: number };
|
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 {
|
interface EntryParams {
|
||||||
entryId: string;
|
entryId: string;
|
||||||
|
|
||||||
|
|||||||
@@ -35,21 +35,60 @@ export async function upsertListEntry(entry: any) {
|
|||||||
is_private
|
is_private
|
||||||
} = entry;
|
} = 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') {
|
if (source === 'anilist') {
|
||||||
const token = await getActiveAccessToken(user_id);
|
const token = await getActiveAccessToken(user_id);
|
||||||
|
|
||||||
if (token) {
|
if (token) {
|
||||||
try {
|
try {
|
||||||
const result = await aniListService.updateAniListEntry(token, {
|
const result = await aniListService.updateAniListEntry(token, {
|
||||||
mediaId: entry_id,
|
mediaId: entry.entry_id,
|
||||||
status,
|
status: entry.status,
|
||||||
progress,
|
progress: entry.progress,
|
||||||
score,
|
score: entry.score,
|
||||||
start_date,
|
start_date: entry.start_date,
|
||||||
end_date,
|
end_date: entry.end_date,
|
||||||
repeat_count,
|
repeat_count: entry.repeat_count,
|
||||||
notes,
|
notes: entry.notes,
|
||||||
is_private
|
is_private: entry.is_private
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -85,20 +124,21 @@ export async function upsertListEntry(entry: any) {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const params = [
|
const params = [
|
||||||
user_id,
|
entry.user_id,
|
||||||
entry_id,
|
entry.entry_id,
|
||||||
source,
|
entry.source,
|
||||||
entry_type,
|
entry.entry_type,
|
||||||
status,
|
entry.status,
|
||||||
progress,
|
entry.progress,
|
||||||
score ?? null,
|
entry.score ?? null,
|
||||||
start_date || null,
|
entry.start_date || null,
|
||||||
end_date || null,
|
entry.end_date || null,
|
||||||
repeat_count ?? 0,
|
entry.repeat_count ?? 0,
|
||||||
notes || null,
|
entry.notes || null,
|
||||||
is_private ?? 0
|
entry.is_private ?? 0
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await run(sql, params, USER_DB);
|
const result = await run(sql, params, USER_DB);
|
||||||
return { changes: result.changes, lastID: result.lastID, external: false };
|
return { changes: result.changes, lastID: result.lastID, external: false };
|
||||||
|
|||||||
@@ -117,9 +117,9 @@ function renderContinueWatching(id, list) {
|
|||||||
const ep = item.progress || 1;
|
const ep = item.progress || 1;
|
||||||
|
|
||||||
if (item.source === 'anilist') {
|
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 {
|
} 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}`;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -245,9 +245,9 @@ function renderContinueReading(id, list) {
|
|||||||
const ch = item.progress || 1;
|
const ch = item.progress || 1;
|
||||||
|
|
||||||
if (item.source === 'anilist') {
|
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 {
|
} 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}`;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user