improvement on my lists
This commit is contained in:
@@ -95,30 +95,43 @@ export async function getUserAniList(appUserId: number) {
|
|||||||
anime: MediaListCollection(userId: $userId, type: ANIME) {
|
anime: MediaListCollection(userId: $userId, type: ANIME) {
|
||||||
lists {
|
lists {
|
||||||
entries {
|
entries {
|
||||||
mediaId
|
media {
|
||||||
|
id
|
||||||
|
title { romaji english userPreferred }
|
||||||
|
coverImage { extraLarge }
|
||||||
|
episodes
|
||||||
|
nextAiringEpisode { episode }
|
||||||
|
}
|
||||||
status
|
status
|
||||||
progress
|
progress
|
||||||
score
|
score
|
||||||
startedAt { year month day }
|
|
||||||
completedAt { year month day }
|
|
||||||
repeat
|
repeat
|
||||||
notes
|
notes
|
||||||
private
|
private
|
||||||
|
startedAt { year month day }
|
||||||
|
completedAt { year month day }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
manga: MediaListCollection(userId: $userId, type: MANGA) {
|
manga: MediaListCollection(userId: $userId, type: MANGA) {
|
||||||
lists {
|
lists {
|
||||||
entries {
|
entries {
|
||||||
mediaId
|
media {
|
||||||
|
id
|
||||||
|
title { romaji english userPreferred }
|
||||||
|
coverImage { extraLarge }
|
||||||
|
chapters
|
||||||
|
volumes
|
||||||
|
}
|
||||||
status
|
status
|
||||||
progress
|
progress
|
||||||
score
|
score
|
||||||
startedAt { year month day }
|
|
||||||
completedAt { year month day }
|
|
||||||
repeat
|
repeat
|
||||||
notes
|
notes
|
||||||
private
|
private
|
||||||
|
startedAt { year month day }
|
||||||
|
completedAt { year month day }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,15 +151,10 @@ export async function getUserAniList(appUserId: number) {
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) throw new Error(`AniList API error: ${res.status}`);
|
||||||
throw new Error(`AniList API error: ${res.status}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
|
if (json?.errors?.length) throw new Error(json.errors[0].message);
|
||||||
if (json?.errors?.length) {
|
|
||||||
throw new Error(json.errors[0].message);
|
|
||||||
}
|
|
||||||
|
|
||||||
const fromFuzzy = (d: any) => {
|
const fromFuzzy = (d: any) => {
|
||||||
if (!d?.year) return null;
|
if (!d?.year) return null;
|
||||||
@@ -160,9 +168,24 @@ export async function getUserAniList(appUserId: number) {
|
|||||||
|
|
||||||
for (const list of lists || []) {
|
for (const list of lists || []) {
|
||||||
for (const entry of list.entries || []) {
|
for (const entry of list.entries || []) {
|
||||||
|
const media = entry.media;
|
||||||
|
|
||||||
|
const totalEpisodes =
|
||||||
|
media?.episodes ||
|
||||||
|
(media?.nextAiringEpisode?.episode
|
||||||
|
? media.nextAiringEpisode.episode - 1
|
||||||
|
: 0);
|
||||||
|
|
||||||
|
const totalChapters =
|
||||||
|
media?.chapters ||
|
||||||
|
(media?.volumes ? media.volumes * 10 : 0);
|
||||||
|
|
||||||
result.push({
|
result.push({
|
||||||
user_id: appUserId,
|
user_id: appUserId,
|
||||||
entry_id: entry.mediaId,
|
|
||||||
|
// ✅ FIX CLAVE
|
||||||
|
entry_id: media.id,
|
||||||
|
|
||||||
source: 'anilist',
|
source: 'anilist',
|
||||||
entry_type: type,
|
entry_type: type,
|
||||||
status: entry.status,
|
status: entry.status,
|
||||||
@@ -172,7 +195,22 @@ export async function getUserAniList(appUserId: number) {
|
|||||||
end_date: fromFuzzy(entry.completedAt),
|
end_date: fromFuzzy(entry.completedAt),
|
||||||
repeat_count: entry.repeat || 0,
|
repeat_count: entry.repeat || 0,
|
||||||
notes: entry.notes || null,
|
notes: entry.notes || null,
|
||||||
is_private: entry.private ? 1 : 0
|
is_private: entry.private ? 1 : 0,
|
||||||
|
|
||||||
|
// ✅ CAMPOS QUE EL FRONTEND NECESITA
|
||||||
|
title: media?.title?.userPreferred
|
||||||
|
|| media?.title?.english
|
||||||
|
|| media?.title?.romaji
|
||||||
|
|| 'Unknown Title',
|
||||||
|
|
||||||
|
poster: media?.coverImage?.extraLarge
|
||||||
|
|| 'https://placehold.co/400x600?text=No+Cover',
|
||||||
|
|
||||||
|
total_episodes: type === 'ANIME' ? totalEpisodes : undefined,
|
||||||
|
total_chapters: type === 'MANGA' ? totalChapters : undefined,
|
||||||
|
|
||||||
|
// ✅ PARA ORDER BY EN EL FRONT
|
||||||
|
updated_at: new Date().toISOString()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,6 +222,7 @@ export async function getUserAniList(appUserId: number) {
|
|||||||
...normalize(json?.data?.anime?.lists, 'ANIME'),
|
...normalize(json?.data?.anime?.lists, 'ANIME'),
|
||||||
...normalize(json?.data?.manga?.lists, 'MANGA')
|
...normalize(json?.data?.manga?.lists, 'MANGA')
|
||||||
];
|
];
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching AniList data:', error);
|
console.error('Error fetching AniList data:', error);
|
||||||
return [];
|
return [];
|
||||||
|
|||||||
@@ -117,14 +117,12 @@ export async function getUserList(userId: number): Promise<any> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const dbList = await queryAll(sql, [userId], USER_DB) as ListEntryData[];
|
const dbList = await queryAll(sql, [userId], USER_DB) as ListEntryData[];
|
||||||
|
|
||||||
const connected = await isConnected(userId);
|
const connected = await isConnected(userId);
|
||||||
|
|
||||||
let finalList: ListEntryData[] = [...dbList];
|
let finalList: any[] = [...dbList];
|
||||||
|
|
||||||
if (connected) {
|
if (connected) {
|
||||||
const anilistEntries = await aniListService.getUserAniList(userId);
|
const anilistEntries = await aniListService.getUserAniList(userId);
|
||||||
|
|
||||||
const localWithoutAnilist = dbList.filter(
|
const localWithoutAnilist = dbList.filter(
|
||||||
entry => entry.source !== 'anilist'
|
entry => entry.source !== 'anilist'
|
||||||
);
|
);
|
||||||
@@ -133,42 +131,46 @@ export async function getUserList(userId: number): Promise<any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const enrichedListPromises = finalList.map(async (entry) => {
|
const enrichedListPromises = finalList.map(async (entry) => {
|
||||||
|
// ✅ Si viene de AniList, ya está completo → NO fetch
|
||||||
|
if (entry.source === 'anilist') {
|
||||||
|
let finalTitle = entry.title;
|
||||||
|
if (typeof finalTitle === 'object' && finalTitle !== null) {
|
||||||
|
finalTitle =
|
||||||
|
finalTitle.userPreferred ||
|
||||||
|
finalTitle.english ||
|
||||||
|
finalTitle.romaji ||
|
||||||
|
'Unknown Title';
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...entry,
|
||||||
|
title: finalTitle,
|
||||||
|
poster: entry.poster || 'https://placehold.co/400x600?text=No+Cover',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Solo se hace fetch para fuentes NO AniList
|
||||||
let contentDetails: any | null = null;
|
let contentDetails: any | null = null;
|
||||||
const id = entry.entry_id;
|
const id = entry.entry_id;
|
||||||
const source = entry.source;
|
|
||||||
const type = entry.entry_type;
|
const type = entry.entry_type;
|
||||||
|
const ext = getExtension(entry.source);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (type === 'ANIME') {
|
if (type === 'ANIME') {
|
||||||
let anime: any;
|
const anime: any = await animeService.getAnimeInfoExtension(ext, id.toString());
|
||||||
|
|
||||||
if (source === 'anilist') {
|
|
||||||
anime = await animeService.getAnimeById(id);
|
|
||||||
} else {
|
|
||||||
const ext = getExtension(source);
|
|
||||||
anime = await animeService.getAnimeInfoExtension(ext, id.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
contentDetails = {
|
contentDetails = {
|
||||||
title: anime?.title || 'Unknown Anime Title',
|
title: anime?.title || 'Unknown Anime Title',
|
||||||
poster: anime?.coverImage?.extraLarge || anime?.image || '',
|
poster: anime?.image || '',
|
||||||
total_episodes: anime?.episodes || anime?.nextAiringEpisode?.episode - 1 || 0,
|
total_episodes: anime?.episodes || 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
} else if (type === 'MANGA' || type === 'NOVEL') {
|
} else if (type === 'MANGA' || type === 'NOVEL') {
|
||||||
let book: any;
|
const book:any = await booksService.getBookInfoExtension(ext, id.toString());
|
||||||
|
|
||||||
if (source === 'anilist') {
|
|
||||||
book = await booksService.getBookById(id);
|
|
||||||
} else {
|
|
||||||
const ext = getExtension(source);
|
|
||||||
const result = await booksService.getBookInfoExtension(ext, id.toString());
|
|
||||||
book = result || null;
|
|
||||||
}
|
|
||||||
|
|
||||||
contentDetails = {
|
contentDetails = {
|
||||||
title: book?.title || 'Unknown Book Title',
|
title: book?.title || 'Unknown Book Title',
|
||||||
poster: book?.coverImage?.extraLarge || book?.image || '',
|
poster: book?.image || '',
|
||||||
total_chapters: book?.chapters || book?.volumes * 10 || 0,
|
total_chapters: book?.chapters || book?.volumes * 10 || 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -184,7 +186,11 @@ export async function getUserList(userId: number): Promise<any> {
|
|||||||
let finalPoster = contentDetails?.poster || 'https://placehold.co/400x600?text=No+Cover';
|
let finalPoster = contentDetails?.poster || 'https://placehold.co/400x600?text=No+Cover';
|
||||||
|
|
||||||
if (typeof finalTitle === 'object' && finalTitle !== null) {
|
if (typeof finalTitle === 'object' && finalTitle !== null) {
|
||||||
finalTitle = finalTitle.userPreferred || finalTitle.english || finalTitle.romaji || 'Unknown Title';
|
finalTitle =
|
||||||
|
finalTitle.userPreferred ||
|
||||||
|
finalTitle.english ||
|
||||||
|
finalTitle.romaji ||
|
||||||
|
'Unknown Title';
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user