From e4ca45dbdce6547745c580b2f4a5213950a93216 Mon Sep 17 00:00:00 2001 From: Rushil Perera Date: Thu, 26 Sep 2024 04:30:45 -0400 Subject: [PATCH] fix: retry loading user if 429 returned --- src/controllers/auth/anilist/getUser.ts | 47 ++++++++++++++++------ src/libs/anilist/getNextEpisodeAiringAt.ts | 42 +++++++++++++++---- 2 files changed, 69 insertions(+), 20 deletions(-) diff --git a/src/controllers/auth/anilist/getUser.ts b/src/controllers/auth/anilist/getUser.ts index 0281278..b6584fb 100644 --- a/src/controllers/auth/anilist/getUser.ts +++ b/src/controllers/auth/anilist/getUser.ts @@ -1,6 +1,8 @@ import { graphql } from "gql.tada"; import { GraphQLClient } from "graphql-request"; +import { sleep } from "~/libs/sleep"; + const GetUserQuery = graphql(` query GetUser { Viewer { @@ -21,22 +23,43 @@ const GetUserQuery = graphql(` } `); -export function getUser(aniListToken: string) { +type User = { + statistics: { + minutesWatched?: number | undefined; + episodesWatched?: number | undefined; + count?: number | undefined; + meanScore?: number | undefined; + }; + name?: string | undefined; + avatar?: + | { + medium: string | null; + large: string | null; + } + | null + | undefined; +} | null; + +export async function getUser(aniListToken: string): Promise { const client = new GraphQLClient("https://graphql.anilist.co/"); - return client - .request(GetUserQuery, undefined, { + try { + const data = await client.request(GetUserQuery, undefined, { Authorization: `Bearer ${aniListToken}`, - }) - .then((data) => ({ + }); + return { ...data?.Viewer, statistics: { ...data?.Viewer?.statistics?.anime }, - })) - .catch((err) => { - if (err.response?.status === 401 || err.response?.status === 429) { - return null; - } + }; + } catch (err) { + if (err.response?.status === 401) { + return null; + } else if (err.response?.status === 429) { + return sleep( + Number(err.response.headers.get("Retry-After")!) * 1000, + ).then(() => getUser(aniListToken)); + } - throw err; - }); + throw err; + } } diff --git a/src/libs/anilist/getNextEpisodeAiringAt.ts b/src/libs/anilist/getNextEpisodeAiringAt.ts index b504528..c538cd4 100644 --- a/src/libs/anilist/getNextEpisodeAiringAt.ts +++ b/src/libs/anilist/getNextEpisodeAiringAt.ts @@ -1,6 +1,8 @@ import { graphql } from "gql.tada"; import { GraphQLClient } from "graphql-request"; +import { sleep } from "../sleep"; + const GetNextEpisodeAiringAtQuery = graphql(` query GetNextEpisodeAiringAt($id: Int!) { Media(id: $id) { @@ -13,15 +15,39 @@ const GetNextEpisodeAiringAtQuery = graphql(` } `); -export function getNextEpisodeTimeUntilAiring(aniListId: number) { +type NextAiringTime = { + status: + | "FINISHED" + | "RELEASING" + | "NOT_YET_RELEASED" + | "CANCELLED" + | "HIATUS" + | null; + nextAiring: { + episode: number; + airingAt: number; + } | null; +}; + +export async function getNextEpisodeTimeUntilAiring( + aniListId: number, +): Promise { const client = new GraphQLClient("https://graphql.anilist.co/"); - return client - .request(GetNextEpisodeAiringAtQuery, { id: aniListId }) - .then((data) => { - const status = data!.Media!.status; - const nextAiring = data!.Media!.nextAiringEpisode; + try { + const { status, nextAiringEpisode: nextAiring } = await client + .request(GetNextEpisodeAiringAtQuery, { + id: aniListId, + }) + .then((data) => data!.Media!); - return { status, nextAiring }; - }); + return { status, nextAiring }; + } catch (error) { + if (error.response.status === 429) { + await sleep(Number(error.response.headers.get("Retry-After")!) * 1000); + return getNextEpisodeTimeUntilAiring(aniListId); + } + + throw error; + } }