diff options
| author | Fuwn <[email protected]> | 2024-02-08 00:01:24 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2024-02-08 00:01:24 -0800 |
| commit | f78f5f4857f24ee5338fb1643c666a6b18d75769 (patch) | |
| tree | 57b1b09f20b6b261a3b1ae15bfa441965f71ecd9 /src/lib/Data/AniList/prequels.ts | |
| parent | refactor(data): move static data to module (diff) | |
| download | due.moe-f78f5f4857f24ee5338fb1643c666a6b18d75769.tar.xz due.moe-f78f5f4857f24ee5338fb1643c666a6b18d75769.zip | |
refactor(anilist): move to data module
Diffstat (limited to 'src/lib/Data/AniList/prequels.ts')
| -rw-r--r-- | src/lib/Data/AniList/prequels.ts | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/src/lib/Data/AniList/prequels.ts b/src/lib/Data/AniList/prequels.ts new file mode 100644 index 00000000..3009e9ba --- /dev/null +++ b/src/lib/Data/AniList/prequels.ts @@ -0,0 +1,175 @@ +import type { AniListAuthorisation } from './identity'; +import type { MediaTitle } from './media'; + +export interface MediaPrequel { + id: number; + title: MediaTitle; + episodes: number; + seen: number; + nextAiringEpisode?: { + episode: number; + airingAt?: number; + }; + startDate: { + year: number; + month: number; + day: number; + }; + coverImage: { + extraLarge: string; + }; +} + +interface PrequelRelations { + edges: { + relationType: string; + node: { + title: MediaTitle; + episodes: number; + mediaListEntry: { + status: string; + progress: number; + }; + coverImage: { + extraLarge: string; + }; + }; + }[]; +} + +interface PrequelsPage { + data: { + Page: { + media: { + title: MediaTitle; + id: number; + relations: PrequelRelations; + nextAiringEpisode?: { + episode: number; + airingAt?: number; + }; + startDate: { + year: number; + month: number; + day: number; + }; + coverImage: { + extraLarge: string; + }; + }[]; + pageInfo: { + hasNextPage: boolean; + }; + }; + }; +} + +const prequelsPage = async ( + page: number, + anilistAuthorisation: AniListAuthorisation, + year: number, + season: 'WINTER' | 'SPRING' | 'SUMMER' | 'FALL' +): Promise<PrequelsPage> => + await ( + await fetch('https://graphql.anilist.co', { + method: 'POST', + headers: { + Authorization: `${anilistAuthorisation.tokenType} ${anilistAuthorisation.accessToken}`, + 'Content-Type': 'application/json', + Accept: 'application/json' + }, + body: JSON.stringify({ + query: `{ + Page(page: ${page}) { + pageInfo { + hasNextPage + } + media(season: ${season}, seasonYear: ${year}) { + title { + english + romaji + } + coverImage { extraLarge } + id + nextAiringEpisode { episode airingAt } + startDate { year month day } + relations { + edges { + relationType + node { + title { + english + romaji + } + episodes + mediaListEntry { + status + progress + } + coverImage { extraLarge } + } + } + } + } + } +}` + }) + }) + ).json(); + +export const prequels = async ( + anilistAuthorisation: AniListAuthorisation, + year: number, + season: 'WINTER' | 'SPRING' | 'SUMMER' | 'FALL' +): Promise<MediaPrequel[]> => { + const candidates = []; + let page = 1; + let currentPage = await prequelsPage(page, anilistAuthorisation, year, season); + + for (const candidate of currentPage.data.Page.media) candidates.push(candidate); + + while (currentPage['data']['Page']['pageInfo']['hasNextPage']) { + for (const candidate of currentPage.data.Page.media) candidates.push(candidate); + + page += 1; + currentPage = await prequelsPage(page, anilistAuthorisation, year, season); + } + + for (const candidate of currentPage.data.Page.media) candidates.push(candidate); + + const media: MediaPrequel[] = []; + + for (const candidate of candidates) { + let episodes = 0; + let seen = 0; + + for (const relation of candidate.relations.edges) { + if (relation.relationType === 'PREQUEL' || relation.relationType === 'PARENT') { + if ( + relation.node.mediaListEntry === null || + relation.node.mediaListEntry.status !== 'COMPLETED' + ) { + episodes += relation.node.episodes; + + if (relation.node.mediaListEntry !== null) + seen += relation.node.mediaListEntry.progress || 0; + } + } + } + + if (media.some((m) => m.id === candidate.id)) continue; + + if (episodes !== 0) + media.push({ + id: candidate.id, + title: candidate.title, + episodes, + seen, + nextAiringEpisode: candidate.nextAiringEpisode, + startDate: candidate.startDate, + coverImage: candidate.coverImage + }); + } + + return media; +}; |