import { swaggerUI } from "@hono/swagger-ui"; import { OpenAPIHono } from "@hono/zod-openapi"; import { maybeUpdateLastConnectedAt } from "~/controllers/maybeUpdateLastConnectedAt"; import type { QueueName } from "~/libs/tasks/queueName.ts"; import { onNewEpisode } from "./controllers/internal/new-episode"; import { AnilistUpdateType } from "./libs/anilist/updateType"; import type { QueueBody } from "./libs/tasks/queueTask"; export const app = new OpenAPIHono<{ Bindings: Env }>(); app.use(maybeUpdateLastConnectedAt); app.route( "/", await import("~/controllers/health-check").then( (controller) => controller.default, ), ); app.route( "/title", await import("~/controllers/title").then((controller) => controller.default), ); app.route( "/episodes", await import("~/controllers/episodes").then( (controller) => controller.default, ), ); app.route( "/search", await import("~/controllers/search").then((controller) => controller.default), ); app.route( "/watch-status", await import("~/controllers/watch-status").then( (controller) => controller.default, ), ); app.route( "/token", await import("~/controllers/token").then((controller) => controller.default), ); app.route( "/auth", await import("~/controllers/auth").then((controller) => controller.default), ); app.route( "/popular", await import("~/controllers/popular").then( (controller) => controller.default, ), ); app.route( "/internal", await import("~/controllers/internal").then( (controller) => controller.default, ), ); // The OpenAPI documentation will be available at /doc app.doc("/openapi.json", { openapi: "3.0.0", info: { version: "1.0.0", title: "Aniplay API", }, }); app.get("/docs", swaggerUI({ url: "/openapi.json" })); export default { fetch: app.fetch, async queue(batch) { switch (batch.queue as QueueName) { case "ANILIST_UPDATES": for (const message of ( batch as MessageBatch ).messages) { switch (message.body.updateType) { case AnilistUpdateType.UpdateWatchStatus: if (!message.body[AnilistUpdateType.UpdateWatchStatus]) { throw new Error( `Discarding update, unknown body ${JSON.stringify(message.body)}`, ); } const { updateWatchStatusOnAnilist } = await import("~/controllers/watch-status/anilist"); const payload = message.body[AnilistUpdateType.UpdateWatchStatus]; await updateWatchStatusOnAnilist( payload.titleId, payload.watchStatus, payload.aniListToken, ); break; } message.ack(); } break; case "NEW_EPISODE": for (const message of (batch as MessageBatch) .messages) { await onNewEpisode( message.body.aniListId, message.body.episodeNumber, ); message.ack(); } break; } }, async scheduled(event, env, ctx) { const { processDelayedTasks } = await import("~/libs/tasks/processDelayedTasks"); await processDelayedTasks(env, ctx); }, } satisfies ExportedHandler; export { AnilistDurableObject as AnilistDo } from "~/libs/anilist/anilist-do.ts";