feat: add more error handling
This commit is contained in:
@@ -29,8 +29,8 @@ describe('requests the "/episodes" route', () => {
|
||||
},
|
||||
);
|
||||
|
||||
expect(response.json()).resolves.toEqual({ success: false });
|
||||
expect(response.status).toBe(404);
|
||||
expect(response.json()).resolves.toEqual({ success: true, result: [] });
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
|
||||
it("Anify is disabled, returns no episode list from Anify", async () => {
|
||||
@@ -42,8 +42,8 @@ describe('requests the "/episodes" route', () => {
|
||||
},
|
||||
);
|
||||
|
||||
expect(response.json()).resolves.toEqual({ success: false });
|
||||
expect(response.status).toBe(404);
|
||||
expect(response.json()).resolves.toEqual({ success: true, result: [] });
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
|
||||
it("with list of episodes from Consumet", async () => {
|
||||
@@ -100,7 +100,7 @@ describe('requests the "/episodes" route', () => {
|
||||
it("with no episodes from all sources", async () => {
|
||||
const response = await app.request("/episodes/-1");
|
||||
|
||||
expect(response.json()).resolves.toEqual({ success: false });
|
||||
expect(response.status).toBe(404);
|
||||
expect(response.json()).resolves.toEqual({ success: true, result: [] });
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -33,13 +33,13 @@ const route = createRoute({
|
||||
},
|
||||
description: "Returns a list of episodes",
|
||||
},
|
||||
404: {
|
||||
500: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorResponseSchema,
|
||||
},
|
||||
},
|
||||
description: "Returns an empty list because episodes not found",
|
||||
description: "Error fetching episodes",
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -49,7 +49,7 @@ const app = new OpenAPIHono<Env>();
|
||||
app.openapi(route, async (c) => {
|
||||
const aniListId = Number(c.req.param("aniListId"));
|
||||
|
||||
const episodes = await fetchFromMultipleSources([
|
||||
const { result: episodes, errors } = await fetchFromMultipleSources([
|
||||
() => {
|
||||
const isAnifyEnabled = readEnvVariable<boolean>(c.env, "ENABLE_ANIFY");
|
||||
return getEpisodesFromAnify(isAnifyEnabled, aniListId);
|
||||
@@ -64,13 +64,13 @@ app.openapi(route, async (c) => {
|
||||
),
|
||||
]);
|
||||
|
||||
if (!episodes) {
|
||||
return c.json(ErrorResponse, { status: 404 });
|
||||
if (errors?.length > 0) {
|
||||
return c.json(ErrorResponse, { status: 500 });
|
||||
}
|
||||
|
||||
return c.json({
|
||||
success: true,
|
||||
result: episodes,
|
||||
result: episodes ?? [],
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -19,12 +19,13 @@ describe('requests the "/search" route', () => {
|
||||
});
|
||||
|
||||
it("query that returns no results", async () => {
|
||||
const response = await app.request("/search?query=");
|
||||
const response = await app.request("/search?query=a");
|
||||
|
||||
expect(response.json()).resolves.toEqual({
|
||||
success: false,
|
||||
success: true,
|
||||
results: [],
|
||||
hasNextPage: false,
|
||||
});
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -39,12 +39,17 @@ app.openapi(route, async (c) => {
|
||||
const page = Number(c.req.query("page") ?? 1);
|
||||
const limit = Number(c.req.query("limit") ?? 10);
|
||||
|
||||
const response = await fetchFromMultipleSources([
|
||||
const { result: response, errors } = await fetchFromMultipleSources([
|
||||
() => fetchSearchResultsFromAnilist(query, page, limit),
|
||||
() => fetchSearchResultsFromAmvstrm(query, page, limit),
|
||||
]);
|
||||
|
||||
if (!response) {
|
||||
return c.json({ success: false, results: [], hasNextPage: false }, 200);
|
||||
return c.json({
|
||||
success: (errors ?? []).length === 0,
|
||||
results: [],
|
||||
hasNextPage: false,
|
||||
});
|
||||
}
|
||||
|
||||
return c.json(
|
||||
|
||||
@@ -11,52 +11,38 @@ export async function fetchTitleFromAmvstrm(
|
||||
console.error("Failed to get missing information from Anify", err);
|
||||
return null;
|
||||
}),
|
||||
]).then(
|
||||
async ([
|
||||
{
|
||||
id,
|
||||
idMal,
|
||||
title: { english: englishTitle, userPreferred: userPreferredTitle },
|
||||
description,
|
||||
episodes,
|
||||
genres,
|
||||
status,
|
||||
bannerImage,
|
||||
coverImage: {
|
||||
extraLarge: extraLargeCoverImage,
|
||||
large: largeCoverImage,
|
||||
medium: mediumCoverImage,
|
||||
},
|
||||
countryOfOrigin,
|
||||
nextair: nextAiringEpisode,
|
||||
score: { averageScore },
|
||||
]).then(async ([amvstrmInfo, anifyInfo]) => {
|
||||
if (amvstrmInfo.code >= 400) {
|
||||
console.error(
|
||||
`Error trying to load title from amvstrm; aniListId: ${aniListId}, code: ${amvstrmInfo.code}, message: ${amvstrmInfo.message}`,
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
id: amvstrmInfo.id,
|
||||
idMal: amvstrmInfo.idMal,
|
||||
title: {
|
||||
userPreferred: amvstrmInfo.title.userPreferred,
|
||||
english: amvstrmInfo.title.english,
|
||||
},
|
||||
anifyInfo,
|
||||
]) => {
|
||||
return {
|
||||
id,
|
||||
idMal,
|
||||
title: {
|
||||
userPreferred: userPreferredTitle,
|
||||
english: englishTitle,
|
||||
},
|
||||
description,
|
||||
episodes,
|
||||
genres,
|
||||
status,
|
||||
averageScore,
|
||||
bannerImage: bannerImage ?? anifyInfo?.bannerImage,
|
||||
coverImage: {
|
||||
extraLarge: extraLargeCoverImage,
|
||||
large: largeCoverImage,
|
||||
medium: mediumCoverImage,
|
||||
},
|
||||
countryOfOrigin: countryOfOrigin ?? anifyInfo?.countryOfOrigin,
|
||||
nextAiringEpisode,
|
||||
mediaListEntry: null,
|
||||
};
|
||||
},
|
||||
);
|
||||
description: amvstrmInfo.description,
|
||||
episodes: amvstrmInfo.episodes,
|
||||
genres: amvstrmInfo.genres,
|
||||
status: amvstrmInfo.status,
|
||||
averageScore: amvstrmInfo.score.averageScore,
|
||||
bannerImage: amvstrmInfo.bannerImage ?? anifyInfo?.bannerImage,
|
||||
coverImage: {
|
||||
extraLarge: amvstrmInfo.coverImage.extraLarge,
|
||||
large: amvstrmInfo.coverImage.large,
|
||||
medium: amvstrmInfo.coverImage.medium,
|
||||
},
|
||||
countryOfOrigin:
|
||||
amvstrmInfo.countryOfOrigin ?? anifyInfo?.countryOfOrigin,
|
||||
nextAiringEpisode: amvstrmInfo.nextair,
|
||||
mediaListEntry: null,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
type AnifyInformation = {
|
||||
|
||||
@@ -28,5 +28,12 @@ export async function fetchTitleFromAnilist(
|
||||
|
||||
return client
|
||||
.request(GetTitleQuery, { id }, headers)
|
||||
.then((data) => data?.Media ?? undefined);
|
||||
.then((data) => data?.Media ?? undefined)
|
||||
.catch((error) => {
|
||||
if (error.message.includes("Not Found")) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
|
||||
import { fetchFromMultipleSources } from "~/libs/fetchFromMultipleSources";
|
||||
import {
|
||||
AniListIdQuerySchema,
|
||||
ErrorResponse,
|
||||
ErrorResponseSchema,
|
||||
SuccessResponseSchema,
|
||||
} from "~/types/schema";
|
||||
@@ -47,12 +48,17 @@ app.openapi(route, async (c) => {
|
||||
const aniListId = Number(c.req.query("id"));
|
||||
const aniListToken = c.req.header("X-AniList-Token");
|
||||
|
||||
const title = await fetchFromMultipleSources([
|
||||
const { result: title, errors } = await fetchFromMultipleSources([
|
||||
() => fetchTitleFromAnilist(aniListId, aniListToken ?? undefined),
|
||||
() => fetchTitleFromAmvstrm(aniListId),
|
||||
]);
|
||||
|
||||
if (errors?.length > 0) {
|
||||
return c.json(ErrorResponse, { status: 500 });
|
||||
}
|
||||
|
||||
if (!title) {
|
||||
return c.json({ success: false }, 404);
|
||||
return c.json(ErrorResponse, 404);
|
||||
}
|
||||
|
||||
return c.json({ success: true, result: title }, 200);
|
||||
|
||||
Reference in New Issue
Block a user