diff options
Diffstat (limited to 'src/lib/Data/AniList/activity.ts')
| -rw-r--r-- | src/lib/Data/AniList/activity.ts | 450 |
1 files changed, 225 insertions, 225 deletions
diff --git a/src/lib/Data/AniList/activity.ts b/src/lib/Data/AniList/activity.ts index c50ffa62..d10a5da7 100644 --- a/src/lib/Data/AniList/activity.ts +++ b/src/lib/Data/AniList/activity.ts @@ -3,269 +3,269 @@ import type { User } from './follow'; import type { AniListAuthorisation, UserIdentity } from './identity'; export interface ActivityHistoryEntry { - date: number; - amount: number; + date: number; + amount: number; } interface ActivityHistoryOptions { - stats: { - activityHistory: ActivityHistoryEntry[]; - }; - options: { - timezone: string; - }; + stats: { + activityHistory: ActivityHistoryEntry[]; + }; + options: { + timezone: string; + }; } interface LastActivity { - date: Date; - timezone: string; + date: Date; + timezone: string; } export const fillMissingDays = ( - inputActivities: ActivityHistoryEntry[], - startOfYear = false, - year = new Date().getFullYear() + inputActivities: ActivityHistoryEntry[], + startOfYear = false, + year = new Date().getFullYear() ): ActivityHistoryEntry[] => { - const yearDate = new Date(year, 0, 0); - - if (inputActivities.length === 0) - return startOfYear - ? fillDateRange( - new Date(yearDate.getUTCFullYear(), 0, 1), - new Date(yearDate.getUTCFullYear() + 1, 0, 1) - ) - : []; - - const sortedActivities = [...inputActivities].sort((a, b) => a.date - b.date); - const endDate = new Date(sortedActivities[sortedActivities.length - 1].date * 1000); - - endDate.setUTCDate(endDate.getUTCDate() + 1); - - return fillDateRange( - startOfYear - ? new Date(yearDate.getUTCFullYear(), 0, 1) - : new Date(sortedActivities[0].date * 1000), - endDate, - sortedActivities - ); + const yearDate = new Date(year, 0, 0); + + if (inputActivities.length === 0) + return startOfYear + ? fillDateRange( + new Date(yearDate.getUTCFullYear(), 0, 1), + new Date(yearDate.getUTCFullYear() + 1, 0, 1) + ) + : []; + + const sortedActivities = [...inputActivities].sort((a, b) => a.date - b.date); + const endDate = new Date(sortedActivities[sortedActivities.length - 1].date * 1000); + + endDate.setUTCDate(endDate.getUTCDate() + 1); + + return fillDateRange( + startOfYear + ? new Date(yearDate.getUTCFullYear(), 0, 1) + : new Date(sortedActivities[0].date * 1000), + endDate, + sortedActivities + ); }; const fillDateRange = ( - startDate: Date, - endDate: Date, - existingActivities: ActivityHistoryEntry[] = [] + startDate: Date, + endDate: Date, + existingActivities: ActivityHistoryEntry[] = [] ): ActivityHistoryEntry[] => { - const outputActivities: ActivityHistoryEntry[] = []; - - for (let dt = new Date(startDate); dt < endDate; dt.setUTCDate(dt.getUTCDate() + 1)) { - const dateString = dt.toDateString(); - - if ( - !new Set( - existingActivities.map((activity) => new Date(activity.date * 1000).toDateString()) - ).has(dateString) - ) { - outputActivities.push({ date: Math.floor(dt.getTime() / 1000), amount: 0 }); - } else { - const activity = existingActivities.find( - (activity) => new Date(activity.date * 1000).toDateString() === dateString - ); - - if (activity) outputActivities.push(activity); - } - } - - return outputActivities; + const outputActivities: ActivityHistoryEntry[] = []; + + for (let dt = new Date(startDate); dt < endDate; dt.setUTCDate(dt.getUTCDate() + 1)) { + const dateString = dt.toDateString(); + + if ( + !new Set( + existingActivities.map((activity) => new Date(activity.date * 1000).toDateString()) + ).has(dateString) + ) { + outputActivities.push({ date: Math.floor(dt.getTime() / 1000), amount: 0 }); + } else { + const activity = existingActivities.find( + (activity) => new Date(activity.date * 1000).toDateString() === dateString + ); + + if (activity) outputActivities.push(activity); + } + } + + return outputActivities; }; export const activityHistoryOptions = async ( - userIdentity: UserIdentity, - authorisation?: AniListAuthorisation + userIdentity: UserIdentity, + authorisation?: AniListAuthorisation ): Promise<ActivityHistoryOptions> => { - return ( - await ( - await fetch('https://graphql.anilist.co', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json', - ...(authorisation - ? { Authorization: `${authorisation.tokenType} ${authorisation.accessToken}` } - : {}) - }, - body: JSON.stringify({ - query: `{ User(id: ${userIdentity.id}) { + return ( + await ( + await fetch('https://graphql.anilist.co', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + ...(authorisation + ? { Authorization: `${authorisation.tokenType} ${authorisation.accessToken}` } + : {}) + }, + body: JSON.stringify({ + query: `{ User(id: ${userIdentity.id}) { stats { activityHistory { date amount } } ${authorisation ? 'options { timezone }' : ''} } }` - }) - }) - ).json() - )['data']['User']; + }) + }) + ).json() + )['data']['User']; }; const convertToTimezoneOffset = (timeStr: string) => { - const [hours, minutes] = timeStr.split(':'); - let totalMinutes = parseInt(hours, 10) * 60 + parseInt(minutes, 10); + const [hours, minutes] = timeStr.split(':'); + let totalMinutes = parseInt(hours, 10) * 60 + parseInt(minutes, 10); - totalMinutes = -totalMinutes; + totalMinutes = -totalMinutes; - return totalMinutes; + return totalMinutes; }; export const activityHistory = async ( - userIdentity: UserIdentity, - authorisation?: AniListAuthorisation + userIdentity: UserIdentity, + authorisation?: AniListAuthorisation ): Promise<ActivityHistoryEntry[]> => - (await activityHistoryOptions(userIdentity, authorisation)).stats.activityHistory; + (await activityHistoryOptions(userIdentity, authorisation)).stats.activityHistory; export const lastActivityDate = async ( - userIdentity: UserIdentity, - authorisation: AniListAuthorisation + userIdentity: UserIdentity, + authorisation: AniListAuthorisation ): Promise<LastActivity> => { - if (userIdentity.id === -1 || userIdentity.id === -2) - return { date: new Date(8640000000000000), timezone: '' }; + if (userIdentity.id === -1 || userIdentity.id === -2) + return { date: new Date(8640000000000000), timezone: '' }; - const history = await activityHistoryOptions(userIdentity, authorisation); - const date = new Date( - Number(history.stats.activityHistory[history.stats.activityHistory.length - 1].date) * 1000 + - convertToTimezoneOffset(history.options.timezone) - ); + const history = await activityHistoryOptions(userIdentity, authorisation); + const date = new Date( + Number(history.stats.activityHistory[history.stats.activityHistory.length - 1].date) * 1000 + + convertToTimezoneOffset(history.options.timezone) + ); - date.setDate(date.getDate() + 1); + date.setDate(date.getDate() + 1); - return { date, timezone: history.options.timezone }; + return { date, timezone: history.options.timezone }; }; export interface ActivitiesPage { - data: { - Page: { - pageInfo: { - hasNextPage: boolean; - }; - activities: { - createdAt: number; - }[]; - }; - }; + data: { + Page: { + pageInfo: { + hasNextPage: boolean; + }; + activities: { + createdAt: number; + }[]; + }; + }; } const activitiesPage = async ( - page: number, - anilistAuthorisation: AniListAuthorisation, - userIdentity: UserIdentity, - year = new Date().getFullYear() + page: number, + anilistAuthorisation: AniListAuthorisation, + userIdentity: UserIdentity, + year = new Date().getFullYear() ): Promise<ActivitiesPage> => - 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: `{ + 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 } activities(userId: ${userIdentity.id}, createdAt_greater: ${Math.floor( - new Date(year, 0, 1).getTime() / 1000 - )}, createdAt_lesser: ${Math.floor(new Date(year, 7, 1).getTime() / 1000)}) { + new Date(year, 0, 1).getTime() / 1000 + )}, createdAt_lesser: ${Math.floor(new Date(year, 7, 1).getTime() / 1000)}) { ... on TextActivity { createdAt } ... on ListActivity { createdAt } ... on MessageActivity { createdAt } } } }` - }) - }) - ).json(); + }) + }) + ).json(); export const fullActivityHistory = async ( - anilistAuthorisation: AniListAuthorisation, - userIdentity: UserIdentity, - year = new Date().getFullYear() + anilistAuthorisation: AniListAuthorisation, + userIdentity: UserIdentity, + year = new Date().getFullYear() ): Promise<ActivityHistoryEntry[]> => { - const activities = []; - let page = 1; - let currentDatabasePage = await database.activities.get(page); - let currentPage; - - if (currentDatabasePage) currentPage = currentDatabasePage.data; - else { - currentPage = await activitiesPage(page, anilistAuthorisation, userIdentity, year); - database.activities.add({ - page, - data: currentPage - }); - } - - for (const activity of currentPage.data.Page.activities) activities.push(activity); - - while (currentPage['data']['Page']['pageInfo']['hasNextPage']) { - for (const activity of currentPage.data.Page.activities) activities.push(activity); - - page += 1; - currentDatabasePage = await database.activities.get(page); - - if (currentDatabasePage) currentPage = currentDatabasePage.data; - else { - currentPage = await activitiesPage(page, anilistAuthorisation, userIdentity, year); - database.activities.add({ - page, - data: currentPage - }); - } - } - - for (const activity of currentPage.data.Page.activities) activities.push(activity); - - let fullLocalActivityHistory: ActivityHistoryEntry[] = []; - - for (const activity of activities) { - const date = new Date(activity.createdAt * 1000); - const dateString = date.toDateString(); - - const activityHistoryEntry = fullLocalActivityHistory.find( - (activityHistoryEntry) => - new Date(activityHistoryEntry.date * 1000).toDateString() === dateString - ); - - if (activityHistoryEntry) activityHistoryEntry.amount += 1; - else fullLocalActivityHistory.push({ date: Math.floor(date.getTime() / 1000), amount: 1 }); - } - - fullLocalActivityHistory = fullLocalActivityHistory.filter((a) => !isNaN(a.date)); - - if (new Date().getMonth() > 6) - fullLocalActivityHistory.push(...(await activityHistory(userIdentity))); - - fullLocalActivityHistory = fullLocalActivityHistory.filter( - (activityHistoryEntry, index, self) => - self.findIndex( - (a) => - new Date(a.date * 1000).toDateString() === - new Date(activityHistoryEntry.date * 1000).toDateString() - ) === index - ); - - fullLocalActivityHistory = fullLocalActivityHistory.filter( - (activityHistoryEntry) => new Date(activityHistoryEntry.date * 1000).getFullYear() === year - ); - - return fullLocalActivityHistory; + const activities = []; + let page = 1; + let currentDatabasePage = await database.activities.get(page); + let currentPage; + + if (currentDatabasePage) currentPage = currentDatabasePage.data; + else { + currentPage = await activitiesPage(page, anilistAuthorisation, userIdentity, year); + database.activities.add({ + page, + data: currentPage + }); + } + + for (const activity of currentPage.data.Page.activities) activities.push(activity); + + while (currentPage['data']['Page']['pageInfo']['hasNextPage']) { + for (const activity of currentPage.data.Page.activities) activities.push(activity); + + page += 1; + currentDatabasePage = await database.activities.get(page); + + if (currentDatabasePage) currentPage = currentDatabasePage.data; + else { + currentPage = await activitiesPage(page, anilistAuthorisation, userIdentity, year); + database.activities.add({ + page, + data: currentPage + }); + } + } + + for (const activity of currentPage.data.Page.activities) activities.push(activity); + + let fullLocalActivityHistory: ActivityHistoryEntry[] = []; + + for (const activity of activities) { + const date = new Date(activity.createdAt * 1000); + const dateString = date.toDateString(); + + const activityHistoryEntry = fullLocalActivityHistory.find( + (activityHistoryEntry) => + new Date(activityHistoryEntry.date * 1000).toDateString() === dateString + ); + + if (activityHistoryEntry) activityHistoryEntry.amount += 1; + else fullLocalActivityHistory.push({ date: Math.floor(date.getTime() / 1000), amount: 1 }); + } + + fullLocalActivityHistory = fullLocalActivityHistory.filter((a) => !isNaN(a.date)); + + if (new Date().getMonth() > 6) + fullLocalActivityHistory.push(...(await activityHistory(userIdentity))); + + fullLocalActivityHistory = fullLocalActivityHistory.filter( + (activityHistoryEntry, index, self) => + self.findIndex( + (a) => + new Date(a.date * 1000).toDateString() === + new Date(activityHistoryEntry.date * 1000).toDateString() + ) === index + ); + + fullLocalActivityHistory = fullLocalActivityHistory.filter( + (activityHistoryEntry) => new Date(activityHistoryEntry.date * 1000).getFullYear() === year + ); + + return fullLocalActivityHistory; }; export const activityLikes = async (id: number): Promise<Partial<User>[]> => { - const activityResponse = await ( - await fetch('https://graphql.anilist.co', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json' - }, - body: JSON.stringify({ - query: `{ + const activityResponse = await ( + await fetch('https://graphql.anilist.co', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json' + }, + body: JSON.stringify({ + query: `{ Activity(id: ${id}) { __typename ... on TextActivity { likes { name avatar { large } } } @@ -273,34 +273,34 @@ export const activityLikes = async (id: number): Promise<Partial<User>[]> => { ... on MessageActivity { likes { name avatar { large } } } } }` - }) - }) - ).json(); + }) + }) + ).json(); - return activityResponse['data']['Activity']['likes']; + return activityResponse['data']['Activity']['likes']; }; export const activityText = async (id: number, replies = false): Promise<string> => { - const activityResponse = await ( - await fetch('https://graphql.anilist.co', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json' - }, - body: JSON.stringify({ - query: `{ + const activityResponse = await ( + await fetch('https://graphql.anilist.co', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json' + }, + body: JSON.stringify({ + query: `{ Activity(id: ${id}) { ... on TextActivity { text(asHtml: true) ${replies ? 'replies { text(asHtml: true) }' : ''} } } }` - }) - }) - ).json(); - let text = activityResponse['data']['Activity']['text']; + }) + }) + ).json(); + let text = activityResponse['data']['Activity']['text']; - if (replies) - for (const reply of activityResponse['data']['Activity']['replies']) text += reply.text; + if (replies) + for (const reply of activityResponse['data']['Activity']['replies']) text += reply.text; - return text; + return text; }; |