feat: create routes to load popular titles

This commit is contained in:
2024-10-27 13:59:49 -04:00
parent 99963083f0
commit 592cc08853
13 changed files with 554 additions and 21 deletions

View File

@@ -0,0 +1,157 @@
import { graphql } from "gql.tada";
import { GraphQLClient } from "graphql-request";
import { getCurrentAndNextSeason } from "~/libs/getCurrentAndNextSeason";
import { sleep } from "~/libs/sleep";
import { HomeTitleFragment } from "~/types/title/homeTitle";
import { mapTitle } from "../mapTitle";
const BrowsePopularQuery = graphql(
`
query BrowsePopular(
$season: MediaSeason!
$seasonYear: Int!
$nextSeason: MediaSeason!
$nextYear: Int!
$limit: Int!
) {
trending: Page(page: 1, perPage: $limit) {
media(sort: TRENDING_DESC, type: ANIME, isAdult: false) {
...HomeTitle
}
}
season: Page(page: 1, perPage: $limit) {
media(
season: $season
seasonYear: $seasonYear
sort: POPULARITY_DESC
type: ANIME
isAdult: false
) {
...HomeTitle
}
}
nextSeason: Page(page: 1, perPage: 1) {
media(
season: $nextSeason
seasonYear: $nextYear
sort: START_DATE
type: ANIME
isAdult: false
) {
nextAiringEpisode {
airingAt
timeUntilAiring
}
}
}
}
`,
[HomeTitleFragment],
);
const NextSeasonPopularQuery = graphql(`
query NextSeasonPopular(
$nextSeason: MediaSeason
$nextYear: Int
$limit: Int!
) {
Page(page: 1, perPage: $limit) {
media(
season: $nextSeason
seasonYear: $nextYear
sort: POPULARITY_DESC
type: ANIME
isAdult: false
) {
...media
}
}
}
fragment media on Media {
id
title {
english
userPreferred
}
coverImage {
extraLarge
large
medium
}
}
`);
export async function fetchPopularTitlesFromAnilist(
limit: number,
): Promise<any> {
const client = new GraphQLClient("https://graphql.anilist.co/");
const {
current: { season: currentSeason, year: currentYear },
next: { season: nextSeason, year: nextYear },
} = getCurrentAndNextSeason();
try {
const data = await client.request(BrowsePopularQuery, {
limit,
season: currentSeason,
seasonYear: currentYear,
nextSeason,
nextYear,
});
if (!data) return undefined;
const trendingTitles = data.trending?.media?.map((title) =>
mapTitle(title),
);
const popularSeasonTitles = data.season?.media?.map((title) =>
mapTitle(title),
);
if (!data.nextSeason?.media?.[0]?.nextAiringEpisode) {
return {
trending: trendingTitles,
season: popularSeasonTitles,
};
}
return await client
.request(NextSeasonPopularQuery, {
limit,
nextSeason,
nextYear,
})
.then((data) => ({
trending: trendingTitles,
season: popularSeasonTitles,
upcoming: data?.Page?.media?.map((title) => mapTitle(title)),
}));
} catch (error) {
const response = error.response;
if (response.status === 429) {
console.log("429, retrying in", response.headers.get("Retry-After"));
return sleep(Number(response.headers.get("Retry-After")!) * 1000).then(
() => fetchPopularTitlesFromAnilist(limit),
);
}
throw error;
}
}
type SearchResultsResponse = {
results:
| ({
id: number;
title: { userPreferred: string | null; english: string | null } | null;
coverImage: {
extraLarge: string | null;
large: string | null;
medium: string | null;
} | null;
} | null)[]
| null;
hasNextPage: boolean | null | undefined;
};