feat: add user profile fetch in middleware

This commit is contained in:
2025-12-18 08:46:50 -05:00
parent b64bd4fc26
commit 4c96f58cb0
8 changed files with 114 additions and 44 deletions

View File

@@ -8,6 +8,7 @@ import {
GetNextEpisodeAiringAtQuery,
GetPopularTitlesQuery,
GetTitleQuery,
GetTitleUserDataQuery,
GetTrendingTitlesQuery,
GetUpcomingTitlesQuery,
GetUserProfileQuery,
@@ -18,6 +19,7 @@ import {
SearchQuery,
} from "~/libs/anilist/queries";
import { sleep } from "~/libs/sleep.ts";
import type { Title } from "~/types/title";
const nextAiringEpisodeSchema = z.nullable(
z.object({
@@ -38,30 +40,54 @@ export class AnilistDurableObject extends DurableObject {
return new Response("Not found", { status: 404 });
}
async getTitle(id: number, token?: string) {
return this.handleCachedRequest(
`title:${id}`,
async () => {
const anilistResponse = await this.fetchFromAnilist(
GetTitleQuery,
{ id },
token,
);
return anilistResponse?.Media ?? null;
},
(media) => {
if (!media) return undefined;
// Cast to any to access fragment fields without unmasking
const nextAiringEpisode = nextAiringEpisodeSchema.parse(
(media as any)?.nextAiringEpisode,
);
const airingAt = (nextAiringEpisode?.airingAt ?? 0) * 1000;
if (airingAt) {
return airingAt - Date.now();
}
return undefined;
},
async getTitle(
id: number,
userId?: string,
token?: string,
): Promise<Title | null> {
const promises: Promise<any>[] = [
this.handleCachedRequest(
`title:${id}`,
async () => {
const anilistResponse = await this.fetchFromAnilist(GetTitleQuery, {
id,
});
return anilistResponse?.Media ?? null;
},
(media) => {
if (!media) return undefined;
// Cast to any to access fragment fields without unmasking
const nextAiringEpisode = nextAiringEpisodeSchema.parse(
(media as any)?.nextAiringEpisode,
);
return nextAiringEpisode?.airingAt
? DateTime.fromMillis(nextAiringEpisode?.airingAt)
: undefined;
},
),
];
promises.push(
userId
? this.handleCachedRequest(
`title:${id}:${userId}`,
async () => {
const anilistResponse = await this.fetchFromAnilist(
GetTitleUserDataQuery,
{ id },
{ token },
);
return anilistResponse?.Media ?? null;
},
DateTime.now().plus({ days: 1 }),
)
: Promise.resolve({ mediaListEntry: null }),
);
return Promise.all(promises).then(([title, userTitle]) => ({
...title,
...userTitle,
}));
}
async getNextEpisodeAiringAt(id: number) {