feat: support legacy routes

Summary:

Test Plan:
This commit is contained in:
2024-06-02 06:46:22 -04:00
parent d2645028c5
commit 79fd51951b
4 changed files with 207 additions and 0 deletions

View File

@@ -0,0 +1,117 @@
import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
import { env } from "hono/adapter";
import { Env } from "~/types/env";
import {
AniListIdSchema,
ErrorResponse,
ErrorResponseSchema,
SkippableSchema,
SuccessResponseSchema,
} from "~/types/schema";
import { getSourcesFromAmvstrm } from "./getEpisodeUrl/amvstrm";
import { getSourcesFromAnify } from "./getEpisodeUrl/anify";
import { getSourcesFromConsumet } from "./getEpisodeUrl/consumet";
const DownloadRequest = z.object({
provider: z.string(),
watchId: z.string(),
aniListId: AniListIdSchema,
});
const DownloadResponse = SuccessResponseSchema(
z.object({
source: z.string(),
subtitles: z.array(z.object({ url: z.string(), lang: z.string() })),
audio: z.array(z.object({ url: z.string(), lang: z.string() })),
intro: SkippableSchema,
outro: SkippableSchema,
headers: z.record(z.string()).optional(),
}),
);
const route = createRoute({
tags: ["aniplay", "episodes"],
summary: "Fetch stream URL (usually an .m3u8 stream)",
method: "post",
path: "/",
request: {
body: {
content: {
"application/json": {
schema: DownloadRequest,
},
},
},
},
responses: {
200: {
description: "Returns a stream URL",
content: {
"application/json": {
schema: DownloadResponse,
},
},
},
400: {
description: "Invalid request body",
content: {
"application/json": {
schema: ErrorResponseSchema,
},
},
},
},
});
const app = new OpenAPIHono();
app.openapi(route, async (c) => {
const { provider, watchId, aniListId } =
await c.req.json<typeof DownloadRequest._type>();
if (provider === "amvstrm") {
try {
return {
success: true,
result: await getSourcesFromAmvstrm(watchId),
};
} catch (e) {
console.error("Failed to fetch download URL from Amvstrm", e);
return c.json(ErrorResponse, { status: 500 });
}
}
if (provider === "consumet" || !env<Env>(c).ENABLE_ANIFY) {
try {
return c.json({
success: true,
result: await getSourcesFromConsumet(watchId),
});
} catch (e) {
console.error("Failed to fetch download URL from Consumet", e);
return c.json(ErrorResponse, { status: 500 });
}
}
// provider is not consumet
if (!aniListId) {
return c.json(ErrorResponse, { status: 400 });
}
try {
return c.json({
success: true,
result: await getSourcesFromAnify(provider, watchId, aniListId),
});
} catch (e) {
console.error("Failed to fetch download URL from Anify", e);
return c.json(ErrorResponse, { status: 500 });
}
});
export default app;

View File

@@ -0,0 +1,77 @@
import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
import { fetchFromMultipleSources } from "~/libs/fetchFromMultipleSources";
import { readEnvVariable } from "~/libs/readEnvVariable";
import type { Env } from "~/types/env";
import {
AniListIdQuerySchema,
ErrorResponse,
ErrorResponseSchema,
SuccessResponseSchema,
} from "~/types/schema";
import { getEpisodesFromAnify } from "./getByAniListId/anify";
import { EpisodesResponse } from "./getByAniListId/episode";
const EpisodesResponseSchema = SuccessResponseSchema(EpisodesResponse);
const route = createRoute({
tags: ["aniplay", "episodes"],
summary: "Fetch episodes for a title",
operationId: "fetchEpisodes",
method: "get",
path: "/",
request: {
query: z.object({ aniListId: AniListIdQuerySchema }),
},
responses: {
200: {
content: {
"application/json": {
schema: EpisodesResponseSchema,
},
},
description: "Returns a list of episodes",
},
404: {
content: {
"application/json": {
schema: ErrorResponseSchema,
},
},
description: "Returns an empty list because episodes not found",
},
},
});
const app = new OpenAPIHono<Env>();
app.openapi(route, async (c) => {
const aniListId = Number(c.req.query("aniListId"));
const episodes = await fetchFromMultipleSources([
() => {
const isAnifyEnabled = readEnvVariable<boolean>(c.env, "ENABLE_ANIFY");
return getEpisodesFromAnify(isAnifyEnabled, aniListId);
},
() =>
import("./getByAniListId/consumet").then(({ getEpisodesFromConsumet }) =>
getEpisodesFromConsumet(aniListId),
),
() =>
import("./getByAniListId/amvstrm").then(({ getEpisodesFromAmvstrm }) =>
getEpisodesFromAmvstrm(aniListId),
),
]);
if (!episodes) {
return c.json(ErrorResponse, { status: 404 });
}
return c.json({
success: true,
result: episodes,
});
});
export default app;

View File

@@ -11,4 +11,10 @@ app.route(
await import("./getEpisodeUrl").then((controller) => controller.default), await import("./getEpisodeUrl").then((controller) => controller.default),
); );
// TODO: Remove this route once v2 is ready
app.route(
"/",
await import("./getEpisodesLegacy").then((controller) => controller.default),
);
export default app; export default app;

View File

@@ -23,6 +23,13 @@ app.route(
"/search", "/search",
await import("~/controllers/search").then((controller) => controller.default), await import("~/controllers/search").then((controller) => controller.default),
); );
// TODO: Remove this route once v2 is ready
app.route(
"/download",
await import("~/controllers/episodes/downloadLegacy").then(
(controller) => controller.default,
),
);
// The OpenAPI documentation will be available at /doc // The OpenAPI documentation will be available at /doc
app.doc("/openapi.json", { app.doc("/openapi.json", {