diff options
| author | Fuwn <[email protected]> | 2023-09-14 02:43:44 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2023-09-14 02:43:44 -0700 |
| commit | b220eddf448643fcf3c8f08adbb2b44103abf373 (patch) | |
| tree | 310a8868720859cf45e428d1048022cdda73008e /src | |
| parent | feat(updates): change loading style (diff) | |
| download | due.moe-b220eddf448643fcf3c8f08adbb2b44103abf373.tar.xz due.moe-b220eddf448643fcf3c8f08adbb2b44103abf373.zip | |
feat(manga): best guess estimation
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/AniList/media.ts | 80 | ||||
| -rw-r--r-- | src/lib/List/Due/MangaList.svelte | 2 | ||||
| -rw-r--r-- | src/lib/mangadex.ts | 47 |
3 files changed, 114 insertions, 15 deletions
diff --git a/src/lib/AniList/media.ts b/src/lib/AniList/media.ts index 341e09a4..6187094d 100644 --- a/src/lib/AniList/media.ts +++ b/src/lib/AniList/media.ts @@ -170,3 +170,83 @@ export const publicMediaListCollection = async (userId: number, type: Type): Pro return flattenLists(userIdResponse['data']['MediaListCollection']['lists']); }; + +export const recentMediaActivities = async ( + userIdentity: UserIdentity, + media: Media +): Promise<number | null> => { + const activities = await ( + await fetch('https://graphql.anilist.co', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json' + }, + body: JSON.stringify({ + query: `{ + Page(page: 1) { + activities(mediaId: ${media.id}, sort: ID_DESC) { + ... on ListActivity { progress } + } + } + + MediaList(userId: ${userIdentity.id}, mediaId: ${media.id}) { progress } + }` + }) + }) + ).json(); + // Essentially, just Automail estimation. All credit to hoh and the Automail contributors. + let guesses: number[] = []; + + activities['data']['Page']['activities'].forEach((activity: { progress: string }) => { + if (activity.progress !== null) { + const progress = Number((activity.progress.match(/\d+$/) || [0])[0]); + + if (progress !== 65535) { + guesses.push(progress); + } + } + }); + guesses.sort((a, b) => b - a); + + if (guesses.length) { + let bestGuess = guesses[0]; + + if (guesses.length > 2) { + if (guesses.filter((val) => val < 7000).length) { + guesses = guesses.filter((val) => val < 7000); + } + + const difference = guesses[0] - guesses[1]; + const inverseDifference = 1 + Math.ceil(25 / (difference + 1)); + + if (guesses.length >= inverseDifference) { + if ( + guesses[1] === guesses[inverseDifference] || + guesses[0] - guesses[1] > 500 || + (guesses[0] - guesses[1] > 100 && guesses[1] >= guesses[inverseDifference] - 1) + ) { + bestGuess = guesses[1]; + + if ( + guesses.length > 15 && + guesses[1] - guesses[2] > 50 && + guesses[2] === guesses[guesses.length - 1] + ) { + bestGuess = guesses[2]; + } + } + } + } + + if (activities['data']['MediaList']['progress'] !== null) { + if (activities['data']['MediaList']['progress'] > bestGuess) { + bestGuess = activities['data']['MediaList']['progress']; + } + } + + return bestGuess; + } + + return null; +}; diff --git a/src/lib/List/Due/MangaList.svelte b/src/lib/List/Due/MangaList.svelte index 836899fc..e13a4747 100644 --- a/src/lib/List/Due/MangaList.svelte +++ b/src/lib/List/Due/MangaList.svelte @@ -62,7 +62,7 @@ ); let finalMedia = releasingMedia; - const chapterPromises = finalMedia.map((m: Media) => chapterCount(m)); + const chapterPromises = finalMedia.map((m: Media) => chapterCount(identity, m)); const chapterCounts = await Promise.all(chapterPromises); finalMedia.forEach((m: Media, i) => { diff --git a/src/lib/mangadex.ts b/src/lib/mangadex.ts index b7656b43..d2eb8c3b 100644 --- a/src/lib/mangadex.ts +++ b/src/lib/mangadex.ts @@ -1,26 +1,50 @@ -import type { Media } from '$lib/AniList/media'; +import { recentMediaActivities, type Media } from '$lib/AniList/media'; +import type { UserIdentity } from './AniList/identity'; import { chapterDatabase } from './chapterDatabase'; -export const chapterCount = async (manga: Media): Promise<number | null> => { +export const chapterCount = async ( + identity: UserIdentity, + manga: Media, + preferActivity = false +): Promise<number | null> => { const chapters = await chapterDatabase.chapters.get(manga.id); if (chapters !== undefined) { return chapters.chapters === -1 ? null : chapters.chapters; } - const mangadexData = await ( - await fetch( - `/api/mangadex/manga?english=${manga.title.english}&year=${manga.startDate.year}&romaji=${manga.title.romaji}&native=${manga.title.native}` - ) - ).json(); + if (preferActivity) { + return await recentMediaActivities(identity, manga); + } + + const tryRecentMediaActivities = async () => { + const anilistData = await recentMediaActivities(identity, manga); + + if (anilistData !== null) { + await chapterDatabase.chapters.put({ + id: manga.id, + chapters: anilistData + }); + + return anilistData; + } - if (mangadexData['data'] === undefined || mangadexData['data'].length === 0) { await chapterDatabase.chapters.put({ id: manga.id, chapters: -1 }); return null; + }; + + const mangadexData = await ( + await fetch( + `/api/mangadex/manga?english=${manga.title.english}&year=${manga.startDate.year}&romaji=${manga.title.romaji}&native=${manga.title.native}` + ) + ).json(); + + if (mangadexData['data'] === undefined || mangadexData['data'].length === 0) { + return await tryRecentMediaActivities(); } const lastChapterData = await ( @@ -28,12 +52,7 @@ export const chapterCount = async (manga: Media): Promise<number | null> => { ).json(); if (lastChapterData['data'] === undefined || lastChapterData['data'].length === 0) { - await chapterDatabase.chapters.put({ - id: manga.id, - chapters: -1 - }); - - return null; + return await tryRecentMediaActivities(); } let lastChapter = lastChapterData['data'][0]['attributes']['chapter']; |