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

@@ -7,7 +7,11 @@ import { getTestDb } from "~/libs/test/getTestDb";
import { getTestEnv } from "~/libs/test/getTestEnv";
import { resetTestDb } from "~/libs/test/resetTestDb";
import { server } from "~/mocks";
import { deviceTokensTable, watchStatusTable } from "~/models/schema";
import {
deviceTokensTable,
titleMessagesTable,
watchStatusTable,
} from "~/models/schema";
server.listen();
@@ -96,6 +100,9 @@ describe("requests the /watch-status route", () => {
await db
.insert(deviceTokensTable)
.values({ deviceId: "123", token: "asd" });
await db
.insert(titleMessagesTable)
.values({ titleId: 10, messageId: "123" });
const res = await app.request(
"/watch-status",
@@ -122,6 +129,9 @@ describe("requests the /watch-status route", () => {
await db
.insert(deviceTokensTable)
.values({ deviceId: "123", token: "asd" });
await db
.insert(titleMessagesTable)
.values({ titleId: -1, messageId: "123" });
const res = await app.request(
"/watch-status",
@@ -148,6 +158,9 @@ describe("requests the /watch-status route", () => {
await db
.insert(deviceTokensTable)
.values({ deviceId: "123", token: "asd" });
await db
.insert(titleMessagesTable)
.values({ titleId: 139518, messageId: "123" });
const res = await app.request("/watch-status", {
method: "POST",

View File

@@ -1,8 +1,11 @@
import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
import { Client } from "@upstash/qstash";
import { env } from "hono/adapter";
import { maybeScheduleNextAiringEpisode } from "~/libs/maybeScheduleNextAiringEpisode";
import { verifyQstashHeader } from "~/libs/qstash/verifyQstashHeader";
import { readEnvVariable } from "~/libs/readEnvVariable";
import { deleteTitleMessage, getTitleMessage } from "~/models/titleMessages";
import { setWatchStatus } from "~/models/watchStatus";
import type { Env } from "~/types/env";
import {
@@ -71,6 +74,7 @@ app.openapi(route, async (c) => {
isRetrying = false,
} = await c.req.json<typeof UpdateWatchStatusRequest._type>();
const aniListToken = c.req.header("X-AniList-Token");
const client = new Client({ token: readEnvVariable(c.env, "QSTASH_TOKEN") });
if (isRetrying) {
if (!(await verifyQstashHeader(env<Env, typeof c>(c, "workerd"), c.req))) {
@@ -84,6 +88,20 @@ app.openapi(route, async (c) => {
Number(titleId),
watchStatus,
);
if (wasAdded) {
await maybeScheduleNextAiringEpisode(
env<Env, typeof c>(c, "workerd"),
c.req,
titleId,
);
} else if (wasDeleted) {
const messageId = await getTitleMessage(
env<Env, typeof c>(c, "workerd"),
titleId,
);
await client.messages.delete(messageId);
await deleteTitleMessage(env<Env, typeof c>(c, "workerd"), titleId);
}
} catch (error) {
console.error(new Error("Error setting watch status", { cause: error }));
console.error(error);
@@ -101,19 +119,12 @@ app.openapi(route, async (c) => {
console.error(
new Error("Failed to update watch status on Anilist", { cause: error }),
);
await import("@upstash/qstash")
.then(
({ Client }) =>
new Client({ token: readEnvVariable(c.env, "QSTASH_TOKEN") }),
)
.then((client) =>
client.publishJSON({
url: c.req.url,
body: { deviceId, watchStatus, titleId, isRetrying: true },
retries: 0,
delay: 60,
}),
);
client.publishJSON({
url: c.req.url,
body: { deviceId, watchStatus, titleId, isRetrying: true },
retries: 0,
delay: 60,
});
}
return c.json(SuccessResponse, { status: 200 });