diff options
| author | Fuwn <[email protected]> | 2023-09-27 23:33:01 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2023-09-27 23:33:01 -0700 |
| commit | 8562ba4280c575b3f04df598b7954a2d28b19e50 (patch) | |
| tree | eaa43530441522b5104a1fd1e404ce6b663fc9b0 /src/lib/AniList | |
| parent | fix(anime): template increment render (diff) | |
| download | due.moe-8562ba4280c575b3f04df598b7954a2d28b19e50.tar.xz due.moe-8562ba4280c575b3f04df598b7954a2d28b19e50.zip | |
feat(wrapped): initial wrapped prototype
Diffstat (limited to 'src/lib/AniList')
| -rw-r--r-- | src/lib/AniList/activity.ts | 39 | ||||
| -rw-r--r-- | src/lib/AniList/media.ts | 12 | ||||
| -rw-r--r-- | src/lib/AniList/wrapped.ts | 113 |
3 files changed, 161 insertions, 3 deletions
diff --git a/src/lib/AniList/activity.ts b/src/lib/AniList/activity.ts index bd4bafc0..df150c96 100644 --- a/src/lib/AniList/activity.ts +++ b/src/lib/AniList/activity.ts @@ -5,6 +5,45 @@ export interface ActivityHistoryEntry { amount: number; } +export const fillMissingDays = ( + inputActivities: ActivityHistoryEntry[], + startOfYear = false +): ActivityHistoryEntry[] => { + const timezoneOffset = new Date().getTimezoneOffset() * 60 * 1000; + const activities = inputActivities; + const firstDate = startOfYear + ? new Date(new Date().getFullYear(), 0, 1, 0, 0, 0, 0) + : new Date(activities[0].date * 1000 + timezoneOffset); + const lastDate = new Date(activities[activities.length - 1].date * 1000 + timezoneOffset); + const currentDate = firstDate; + + while (currentDate <= lastDate) { + const current_unix_timestamp = currentDate.getTime(); + let found = false; + + for (let i = 0; i < activities.length; i++) { + if (activities[i].date * 1000 + timezoneOffset === current_unix_timestamp) { + found = true; + + break; + } + } + + if (!found) { + activities.push({ + date: current_unix_timestamp / 1000, + amount: 0 + }); + } + + currentDate.setDate(currentDate.getDate() + 1); + } + + // activities.sort((a: { date: number }, b: { date: number }) => a.date - b.date); + + return activities; +}; + export const activityHistory = async ( userIdentity: UserIdentity ): Promise<ActivityHistoryEntry[]> => { diff --git a/src/lib/AniList/media.ts b/src/lib/AniList/media.ts index 6187094d..d9ce5e57 100644 --- a/src/lib/AniList/media.ts +++ b/src/lib/AniList/media.ts @@ -28,10 +28,14 @@ export interface Media { mediaListEntry?: { progress: number; status: string; + score: number; }; startDate: { year: number; }; + coverImage: { + extraLarge: string; + }; } export const flattenLists = (lists: { entries: { media: Media }[] }[]) => { @@ -59,7 +63,8 @@ export const mediaListCollection = async ( type: Type, mediaCache: string | undefined, currentLastPruneAt: string | number, - forcePrune = false + forcePrune = false, + includeCompleted = false ): Promise<Media[]> => { let currentCacheMinutes; @@ -106,7 +111,7 @@ export const mediaListCollection = async ( body: JSON.stringify({ query: `{ MediaListCollection(userId: ${userIdentity.id}, type: ${ type === Type.Anime ? 'ANIME' : 'MANGA' - }, status_not_in: [ COMPLETED ]) { + }${includeCompleted ? '' : ', status_not_in: [ COMPLETED ]'}) { lists { entries { media { id status @@ -115,8 +120,9 @@ export const mediaListCollection = async ( format title { romaji english native } nextAiringEpisode { episode timeUntilAiring } - mediaListEntry { progress status } + mediaListEntry { progress status score(format: POINT_100) } startDate { year } + coverImage { extraLarge } } } } } }` diff --git a/src/lib/AniList/wrapped.ts b/src/lib/AniList/wrapped.ts new file mode 100644 index 00000000..bd700101 --- /dev/null +++ b/src/lib/AniList/wrapped.ts @@ -0,0 +1,113 @@ +import type { AniListAuthorisation, UserIdentity } from './identity'; + +export interface Wrapped { + statistics: { + anime: { + startYears: { + startYear: number; + minutesWatched: number; + count: number; + }[]; + }; + manga: { + startYears: { + startYear: number; + chaptersRead: number; + count: number; + }[]; + }; + }; + activities: { + statusCount: number; + messageCount: number; + }; + avatar: { + large: string; + }; +} + +const profileActivities = async (user: AniListAuthorisation, identity: UserIdentity) => { + const get = async (page: number) => + await ( + await fetch('https://graphql.anilist.co', { + method: 'POST', + headers: { + Authorization: `${user.tokenType} ${user.accessToken}`, + 'Content-Type': 'application/json', + Accept: 'application/json' + }, + body: JSON.stringify({ + query: `{ + Page(page: ${page}) { + activities(userId: ${identity.id}, type_in: [ TEXT, MESSAGE ]) { + ... on TextActivity { + type + } + ... on MessageActivity { + type + } + } + pageInfo { + hasNextPage + } + } +}` + }) + }) + ).json(); + + const pages = []; + let page = 1; + let response = await get(page); + + pages.push(response['data']['Page']['activities']); + + while (response['data']['Page']['pageInfo']['hasNextPage']) { + page += 1; + response = await get(page); + + pages.push(response['data']['Page']['activities']); + } + + return { + statusCount: pages.flat().filter((activity) => activity.type == 'TEXT').length, + messageCount: pages.flat().filter((activity) => activity.type == 'MESSAGE').length + }; +}; + +export const wrapped = async ( + anilistAuthorisation: AniListAuthorisation, + identity: UserIdentity +): Promise<Wrapped> => { + const wrappedResponse = 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: `{ + User(name: "${identity.name}") { + avatar { large } + statistics { + anime { startYears { startYear minutesWatched count } } + manga { startYears { startYear chaptersRead count } } + } + } +}` + }) + }) + ).json(); + const { statusCount, messageCount } = await profileActivities(anilistAuthorisation, identity); + + return { + statistics: wrappedResponse['data']['User']['statistics'], + activities: { + statusCount, + messageCount + }, + avatar: wrappedResponse['data']['User']['avatar'] + }; +}; |