import { recentMediaActivities, type Media } from "$lib/Data/AniList/media"; import { getChapterCount } from "$lib/Data/Manga/raw"; import proxy from "$lib/Utility/proxy"; import settings from "$stores/settings"; import type { UserIdentity } from "../../Data/AniList/identity"; import { database } from "../../Database/IDB/chapters"; const getManga = async ( statusIn: string, year: number, native: string | null, english: string | null, romaji: string | null, ) => { let status = ""; let error = false; switch (statusIn) { case "FINISHED": { status = "completed"; } break; case "RELEASING": { status = "ongoing"; } break; case "HIATUS": { status = "hiatus"; } break; case "CANCELLED": { status = "cancelled"; } break; } const nullIfNullString = (s: string | null) => (s === "null" ? null : s); const get = async (title: string) => { try { return await ( await fetch( proxy( `https://api.mangadex.org/manga?title=${encodeURIComponent( title, )}&year=${year}&status[]=${status}`, ), ) ).json(); } catch { error = true; } }; let mangadexData = await get( nullIfNullString(native) || nullIfNullString(english) || nullIfNullString(romaji) || "", ); if (error) return new Response("rate-limited"); if (mangadexData["data"] === undefined || mangadexData["data"].length === 0) { mangadexData = await get(nullIfNullString(english) || ""); if ( mangadexData["data"] === undefined || mangadexData["data"].length === 0 ) { mangadexData = await get(nullIfNullString(romaji) || ""); } } return Response.json(mangadexData, { headers: { "Cache-Control": "max-age=300", }, }); }; export const chapterCount = async ( identity: UserIdentity, manga: Media, disableGuessing: boolean, // preferActivity = false ): Promise => { const chapters = await database.chapters.get(manga.id); if (chapters !== undefined) return chapters.chapters === -1 ? null : chapters.chapters; // if (preferActivity) { // return await recentMediaActivities(identity, manga); // } const tryRecentMediaActivities = async () => { if (disableGuessing) { await database.chapters.put({ id: manga.id, chapters: -1, volumes: null, }); return null; } const anilistData = await recentMediaActivities( identity, manga, settings.get().calculateGuessMethod, ); await database.chapters.put({ id: manga.id, chapters: anilistData ? anilistData : -1, volumes: null, }); return anilistData; }; if (manga.format === "NOVEL") return await tryRecentMediaActivities(); let lastChapter = 0; let completedVolumes = null; if (!settings.get().calculatePreferNativeChapterCount) { const mangadexData = await getManga( manga.status, manga.startDate.year, manga.title.native, manga.title.english, manga.title.romaji, ); if ((await mangadexData.clone().text()) === "rate-limited") return -22; const mangadexDataJson = await mangadexData.json(); if ( mangadexDataJson["data"] === undefined || mangadexDataJson["data"].length === 0 ) return await tryRecentMediaActivities(); const mangadexId = mangadexDataJson["data"][0]["id"]; const lastChapterDataJson = await ( await fetch( proxy( `https://api.mangadex.org/manga/${mangadexId}/feed?order[chapter]=desc&translatedLanguage[]=en&limit=1&contentRating[]=safe&contentRating[]=suggestive&contentRating[]=erotica&contentRating[]=pornographic`, ), ) ).json(); if ( lastChapterDataJson["data"] === undefined || lastChapterDataJson["data"].length === 0 ) return await tryRecentMediaActivities(); lastChapter = lastChapterDataJson["data"][0]["attributes"]["chapter"]; completedVolumes = null; if ( (manga.mediaListEntry || { progress: 0 }).progress > lastChapter && !disableGuessing ) { const anilistData = await recentMediaActivities( identity, manga, settings.get().calculateGuessMethod, ); if (anilistData !== null && anilistData > lastChapter) lastChapter = anilistData; } if (!settings.get().calculateDisableOutOfDateVolumeWarning) { const volumeOfChapterData = await ( await fetch( proxy( `https://api.mangadex.org/chapter?manga=${mangadexId}&chapter=${manga.mediaListEntry?.progress}&contentRating[]=safe&contentRating[]=suggestive&contentRating[]=erotica&contentRating[]=pornographic&limit=1`, ), ) ).json(); let lastAvailableVolume = lastChapterDataJson["data"][0]["attributes"]["volume"]; if (lastAvailableVolume === null) { let chapterIndex = 0; while ( chapterIndex < lastChapterDataJson["data"].length && lastAvailableVolume === null ) { if ( lastChapterDataJson["data"][chapterIndex]["attributes"][ "volume" ] !== null ) lastAvailableVolume = lastChapterDataJson["data"][chapterIndex]["attributes"]["volume"]; chapterIndex += 1; } } if ( volumeOfChapterData["data"] !== undefined && volumeOfChapterData["data"].length > 0 ) { const volumeOfChapter = volumeOfChapterData["data"][0]["attributes"]["volume"]; if (volumeOfChapter !== null) completedVolumes = volumeOfChapter; if (completedVolumes === volumeOfChapter) completedVolumes -= 1; } } } else { lastChapter = (await getChapterCount(manga.title.native)) || 0; } if (lastChapter === 0) lastChapter = -1; await database.chapters.put({ id: manga.id, chapters: Number(lastChapter), volumes: completedVolumes, }); return Number(lastChapter); };