feat: schedule next airing episode

happens when new title is saved, or when new episode internal route is run successfully
This commit is contained in:
2024-09-09 03:53:34 -05:00
parent 38195776c2
commit 336701a84b
14 changed files with 353 additions and 19 deletions

View File

@@ -0,0 +1,28 @@
import { graphql } from "gql.tada";
import { GraphQLClient } from "graphql-request";
const GetNextEpisodeAiringAtQuery = graphql(`
query GetNextEpisodeAiringAt($id: Int!) {
Media(id: $id) {
nextAiringEpisode {
episode
timeUntilAiring
}
}
}
`);
export function getNextEpisodeTimeUntilAiring(aniListId: number) {
const client = new GraphQLClient("https://graphql.anilist.co/");
return client
.request(GetNextEpisodeAiringAtQuery, { id: aniListId })
.then((data) => {
const nextAiring = data!.Media!.nextAiringEpisode;
if (!nextAiring) {
return null;
}
return nextAiring;
});
}

View File

@@ -0,0 +1,32 @@
import { Client } from "@upstash/qstash";
import type { HonoRequest } from "hono";
import { setTitleMessage } from "~/models/titleMessages";
import type { Env } from "~/types/env";
import { getNextEpisodeTimeUntilAiring } from "./anilist/getNextEpisodeAiringAt";
import { getCurrentDomain } from "./getCurrentDomain";
export async function maybeScheduleNextAiringEpisode(
env: Env,
req: HonoRequest,
aniListId: number,
) {
const nextAiring = await getNextEpisodeTimeUntilAiring(aniListId);
if (!nextAiring) {
return;
}
const { timeUntilAiring, episode: nextEpisode } = nextAiring;
const client = new Client({ token: env.QSTASH_TOKEN });
const domain = getCurrentDomain(req);
const { messageId } = await client.publishJSON({
url: `${domain}/internal/new-episode`,
body: { aniListId, episode: nextEpisode },
retries: 0,
delay: timeUntilAiring,
contentBasedDeduplication: true,
});
await setTitleMessage(env, aniListId, messageId);
}