Removes the `Env` parameter from several functions to simplify their signatures and rely on the global `env` for configuration. This change reduces the number of arguments passed around, making the code cleaner and easier to maintain.
134 lines
3.3 KiB
TypeScript
134 lines
3.3 KiB
TypeScript
import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
|
|
import type { HonoRequest } from "hono";
|
|
|
|
import { maybeScheduleNextAiringEpisode } from "~/libs/maybeScheduleNextAiringEpisode";
|
|
import { buildNewEpisodeTaskId } from "~/libs/tasks/id";
|
|
import { queueTask } from "~/libs/tasks/queueTask";
|
|
import { removeTask } from "~/libs/tasks/removeTask";
|
|
import { setWatchStatus } from "~/models/watchStatus";
|
|
import {
|
|
AniListIdSchema,
|
|
ErrorResponse,
|
|
ErrorResponseSchema,
|
|
SuccessResponse,
|
|
SuccessResponseSchema,
|
|
} from "~/types/schema";
|
|
import { WatchStatus } from "~/types/title/watchStatus";
|
|
|
|
import { maybeUpdateWatchStatusOnAnilist } from "./anilist";
|
|
|
|
const app = new OpenAPIHono<Cloudflare.Env>();
|
|
|
|
const UpdateWatchStatusRequest = z.object({
|
|
deviceId: z.string(),
|
|
watchStatus: WatchStatus.nullable(),
|
|
titleId: AniListIdSchema,
|
|
isRetrying: z.boolean().optional().default(false),
|
|
});
|
|
|
|
const route = createRoute({
|
|
tags: ["aniplay", "title"],
|
|
operationId: "updateWatchStatus",
|
|
summary: "Update watch status for a title",
|
|
description:
|
|
"Updates the watch status for a title. If the user sets the watch status to 'watching', they'll start getting notified about new episodes.",
|
|
method: "post",
|
|
path: "/",
|
|
request: {
|
|
body: {
|
|
content: {
|
|
"application/json": {
|
|
schema: UpdateWatchStatusRequest,
|
|
},
|
|
},
|
|
},
|
|
headers: z.object({ "x-anilist-token": z.string().nullish() }),
|
|
},
|
|
responses: {
|
|
200: {
|
|
content: {
|
|
"application/json": {
|
|
schema: SuccessResponseSchema(),
|
|
},
|
|
},
|
|
description: "Watch status was successfully updated",
|
|
},
|
|
500: {
|
|
content: {
|
|
"application/json": {
|
|
schema: ErrorResponseSchema,
|
|
},
|
|
},
|
|
description: "Failed to update watch status",
|
|
},
|
|
},
|
|
});
|
|
|
|
export async function updateWatchStatus(
|
|
req: HonoRequest,
|
|
deviceId: string,
|
|
titleId: number,
|
|
watchStatus: WatchStatus | null,
|
|
) {
|
|
const { wasAdded, wasDeleted } = await setWatchStatus(
|
|
deviceId,
|
|
Number(titleId),
|
|
watchStatus,
|
|
);
|
|
if (wasAdded) {
|
|
await maybeScheduleNextAiringEpisode(req, titleId);
|
|
} else if (wasDeleted) {
|
|
await removeTask("new-episode", buildNewEpisodeTaskId(titleId));
|
|
}
|
|
}
|
|
|
|
app.openapi(route, async (c) => {
|
|
const {
|
|
deviceId,
|
|
watchStatus,
|
|
titleId,
|
|
isRetrying = false,
|
|
} = await c.req.json<typeof UpdateWatchStatusRequest._type>();
|
|
const aniListToken = c.req.header("X-AniList-Token");
|
|
|
|
if (!isRetrying) {
|
|
try {
|
|
await updateWatchStatus(c.req, deviceId, titleId, watchStatus);
|
|
} catch (error) {
|
|
console.error("Error setting watch status");
|
|
console.error(error);
|
|
return c.json(ErrorResponse, { status: 500 });
|
|
}
|
|
}
|
|
|
|
try {
|
|
await maybeUpdateWatchStatusOnAnilist(
|
|
Number(titleId),
|
|
watchStatus,
|
|
aniListToken,
|
|
);
|
|
} catch (error) {
|
|
console.error("Failed to update watch status on Anilist");
|
|
console.error(error);
|
|
if (isRetrying) {
|
|
return c.json(ErrorResponse, { status: 500 });
|
|
}
|
|
|
|
await queueTask(
|
|
"anilist-updates",
|
|
{
|
|
deviceId,
|
|
watchStatus,
|
|
titleId,
|
|
isRetrying: true,
|
|
nameSuffix: "watch-status",
|
|
},
|
|
{ req: c.req, scheduleConfig: { delay: { minute: 1 } } },
|
|
);
|
|
}
|
|
|
|
return c.json(SuccessResponse, { status: 200 });
|
|
});
|
|
|
|
export default app;
|