fix: rename route from /upcoming/titles to /upcoming-titles

This commit is contained in:
2024-09-02 13:41:27 -04:00
parent 690b5aa426
commit ae04542ef9
4 changed files with 3 additions and 13 deletions

View File

@@ -0,0 +1,89 @@
import { graphql } from "gql.tada";
import { GraphQLClient } from "graphql-request";
import { DateTime } from "luxon";
import { getValue, setValue } from "~/models/kv";
import type { Env } from "~/types/env";
import type { Title } from "~/types/title";
import { MediaFragment } from "~/types/title/mediaFragment";
const GetUpcomingTitlesQuery = graphql(
`
query GetUpcomingTitles(
$page: Int!
$airingAtLowerBound: Int!
$airingAtUpperBound: Int!
) {
Page(page: $page) {
airingSchedules(
notYetAired: true
sort: TIME
airingAt_lesser: $airingAtUpperBound
airingAt_greater: $airingAtLowerBound
) {
id
airingAt
timeUntilAiring
episode
media {
...Media
}
}
pageInfo {
hasNextPage
}
}
}
`,
[MediaFragment],
);
type AiringSchedule = {
media: Title;
episode: number;
timeUntilAiring: number;
airingAt: number;
id: number;
};
export async function getUpcomingTitlesFromAnilist(env: Env) {
const client = new GraphQLClient("https://graphql.anilist.co/");
const lastCheckedScheduleAt = await getValue(
env,
"schedule_last_checked_at",
).then((value) => (value ? Number(value) : DateTime.now().toUnixInteger()));
console.log(lastCheckedScheduleAt);
const twoDaysFromNow = DateTime.now().plus({ days: 2 }).toUnixInteger();
let currentPage = 1;
let scheduleList: AiringSchedule[] = [];
let shouldContinue = true;
do {
const { Page } = await client.request(GetUpcomingTitlesQuery, {
page: currentPage++,
airingAtLowerBound: lastCheckedScheduleAt,
airingAtUpperBound: twoDaysFromNow,
});
const { airingSchedules, pageInfo } = Page!;
scheduleList = scheduleList.concat(
airingSchedules!.filter(
(schedule): schedule is AiringSchedule => !!schedule,
),
);
shouldContinue = pageInfo?.hasNextPage ?? false;
} while (shouldContinue);
if (scheduleList.length === 0) {
return [];
}
await setValue(
env,
"schedule_last_checked_at",
scheduleList[scheduleList.length - 1].airingAt.toString(),
);
return scheduleList;
}

View File

@@ -0,0 +1,76 @@
import { Hono } from "hono";
import { env } from "hono/adapter";
import mapKeys from "lodash.mapkeys";
import { DateTime } from "luxon";
import { Case, changeStringCase } from "~/libs/changeStringCase";
import type { AdminSdkCredentials } from "~/libs/fcm/getGoogleAuthToken";
import { sendFcmMessage } from "~/libs/fcm/sendFcmMessage";
import { verifyQstashHeader } from "~/libs/qstash/verifyQstashHeader";
import { readEnvVariable } from "~/libs/readEnvVariable";
import type { Env } from "~/types/env";
import { ErrorResponse, SuccessResponse } from "~/types/schema";
import { getUpcomingTitlesFromAnilist } from "./anilist";
const app = new Hono();
app.post("/", async (c) => {
if (
!(await verifyQstashHeader(
env<Env, typeof c>(c, "workerd"),
c.req.path,
c.req.header("Upstash-Signature"),
await c.req.text(),
))
) {
return c.json(ErrorResponse, { status: 401 });
}
const titles = await getUpcomingTitlesFromAnilist(
env<Env, typeof c>(c, "workerd"),
);
await Promise.all(
titles.map(async (title) => {
const titleName =
title.media.title?.userPreferred ??
title.media.title?.english ??
"Unknown Title";
return sendFcmMessage(
mapKeys(
readEnvVariable<AdminSdkCredentials>(c.env, "ADMIN_SDK_JSON"),
(_, key) => changeStringCase(key, Case.snake_case, Case.camelCase),
) as unknown as AdminSdkCredentials,
{
topic: "newTitles",
data: {
type: "new_title",
aniListId: title.media.id.toString(),
title: titleName,
airingAt: title.airingAt.toString(),
},
notification: {
title: "New Series Alert",
body: `${titleName} will be released on ${DateTime.fromSeconds(title.airingAt).toRelative({ unit: "days" })}`,
image:
title.media.coverImage?.medium ??
title.media.coverImage?.large ??
title.media.coverImage?.extraLarge ??
undefined,
},
android: {
notification: {
click_action: "HANDLE_FCM_NOTIFICATION",
},
},
},
);
}),
);
return c.json(SuccessResponse, 200);
});
export default app;