feat: add more error handling

This commit is contained in:
2024-06-07 23:13:30 -04:00
parent 6fd2cc4feb
commit c35c9b9e09
9 changed files with 71 additions and 66 deletions

View File

@@ -29,8 +29,8 @@ describe('requests the "/episodes" route', () => {
}, },
); );
expect(response.json()).resolves.toEqual({ success: false }); expect(response.json()).resolves.toEqual({ success: true, result: [] });
expect(response.status).toBe(404); expect(response.status).toBe(200);
}); });
it("Anify is disabled, returns no episode list from Anify", async () => { 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.json()).resolves.toEqual({ success: true, result: [] });
expect(response.status).toBe(404); expect(response.status).toBe(200);
}); });
it("with list of episodes from Consumet", async () => { 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 () => { it("with no episodes from all sources", async () => {
const response = await app.request("/episodes/-1"); const response = await app.request("/episodes/-1");
expect(response.json()).resolves.toEqual({ success: false }); expect(response.json()).resolves.toEqual({ success: true, result: [] });
expect(response.status).toBe(404); expect(response.status).toBe(200);
}); });
}); });

View File

@@ -33,13 +33,13 @@ const route = createRoute({
}, },
description: "Returns a list of episodes", description: "Returns a list of episodes",
}, },
404: { 500: {
content: { content: {
"application/json": { "application/json": {
schema: ErrorResponseSchema, 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) => { app.openapi(route, async (c) => {
const aniListId = Number(c.req.param("aniListId")); 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"); const isAnifyEnabled = readEnvVariable<boolean>(c.env, "ENABLE_ANIFY");
return getEpisodesFromAnify(isAnifyEnabled, aniListId); return getEpisodesFromAnify(isAnifyEnabled, aniListId);
@@ -64,13 +64,13 @@ app.openapi(route, async (c) => {
), ),
]); ]);
if (!episodes) { if (errors?.length > 0) {
return c.json(ErrorResponse, { status: 404 }); return c.json(ErrorResponse, { status: 500 });
} }
return c.json({ return c.json({
success: true, success: true,
result: episodes, result: episodes ?? [],
}); });
}); });

View File

@@ -19,12 +19,13 @@ describe('requests the "/search" route', () => {
}); });
it("query that returns no results", async () => { 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({ expect(response.json()).resolves.toEqual({
success: false, success: true,
results: [], results: [],
hasNextPage: false, hasNextPage: false,
}); });
expect(response.status).toBe(200);
}); });
}); });

View File

@@ -39,12 +39,17 @@ app.openapi(route, async (c) => {
const page = Number(c.req.query("page") ?? 1); const page = Number(c.req.query("page") ?? 1);
const limit = Number(c.req.query("limit") ?? 10); const limit = Number(c.req.query("limit") ?? 10);
const response = await fetchFromMultipleSources([ const { result: response, errors } = await fetchFromMultipleSources([
() => fetchSearchResultsFromAnilist(query, page, limit), () => fetchSearchResultsFromAnilist(query, page, limit),
() => fetchSearchResultsFromAmvstrm(query, page, limit), () => fetchSearchResultsFromAmvstrm(query, page, limit),
]); ]);
if (!response) { if (!response) {
return c.json({ success: false, results: [], hasNextPage: false }, 200); return c.json({
success: (errors ?? []).length === 0,
results: [],
hasNextPage: false,
});
} }
return c.json( return c.json(

View File

@@ -11,52 +11,38 @@ export async function fetchTitleFromAmvstrm(
console.error("Failed to get missing information from Anify", err); console.error("Failed to get missing information from Anify", err);
return null; return null;
}), }),
]).then( ]).then(async ([amvstrmInfo, anifyInfo]) => {
async ([ if (amvstrmInfo.code >= 400) {
{ console.error(
id, `Error trying to load title from amvstrm; aniListId: ${aniListId}, code: ${amvstrmInfo.code}, message: ${amvstrmInfo.message}`,
idMal, );
title: { english: englishTitle, userPreferred: userPreferredTitle }, return undefined;
description, }
episodes,
genres, return {
status, id: amvstrmInfo.id,
bannerImage, idMal: amvstrmInfo.idMal,
coverImage: { title: {
extraLarge: extraLargeCoverImage, userPreferred: amvstrmInfo.title.userPreferred,
large: largeCoverImage, english: amvstrmInfo.title.english,
medium: mediumCoverImage,
},
countryOfOrigin,
nextair: nextAiringEpisode,
score: { averageScore },
}, },
anifyInfo, description: amvstrmInfo.description,
]) => { episodes: amvstrmInfo.episodes,
return { genres: amvstrmInfo.genres,
id, status: amvstrmInfo.status,
idMal, averageScore: amvstrmInfo.score.averageScore,
title: { bannerImage: amvstrmInfo.bannerImage ?? anifyInfo?.bannerImage,
userPreferred: userPreferredTitle, coverImage: {
english: englishTitle, extraLarge: amvstrmInfo.coverImage.extraLarge,
}, large: amvstrmInfo.coverImage.large,
description, medium: amvstrmInfo.coverImage.medium,
episodes, },
genres, countryOfOrigin:
status, amvstrmInfo.countryOfOrigin ?? anifyInfo?.countryOfOrigin,
averageScore, nextAiringEpisode: amvstrmInfo.nextair,
bannerImage: bannerImage ?? anifyInfo?.bannerImage, mediaListEntry: null,
coverImage: { };
extraLarge: extraLargeCoverImage, });
large: largeCoverImage,
medium: mediumCoverImage,
},
countryOfOrigin: countryOfOrigin ?? anifyInfo?.countryOfOrigin,
nextAiringEpisode,
mediaListEntry: null,
};
},
);
} }
type AnifyInformation = { type AnifyInformation = {

View File

@@ -28,5 +28,12 @@ export async function fetchTitleFromAnilist(
return client return client
.request(GetTitleQuery, { id }, headers) .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;
});
} }

View File

@@ -3,6 +3,7 @@ import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
import { fetchFromMultipleSources } from "~/libs/fetchFromMultipleSources"; import { fetchFromMultipleSources } from "~/libs/fetchFromMultipleSources";
import { import {
AniListIdQuerySchema, AniListIdQuerySchema,
ErrorResponse,
ErrorResponseSchema, ErrorResponseSchema,
SuccessResponseSchema, SuccessResponseSchema,
} from "~/types/schema"; } from "~/types/schema";
@@ -47,12 +48,17 @@ app.openapi(route, async (c) => {
const aniListId = Number(c.req.query("id")); const aniListId = Number(c.req.query("id"));
const aniListToken = c.req.header("X-AniList-Token"); const aniListToken = c.req.header("X-AniList-Token");
const title = await fetchFromMultipleSources([ const { result: title, errors } = await fetchFromMultipleSources([
() => fetchTitleFromAnilist(aniListId, aniListToken ?? undefined), () => fetchTitleFromAnilist(aniListId, aniListToken ?? undefined),
() => fetchTitleFromAmvstrm(aniListId), () => fetchTitleFromAmvstrm(aniListId),
]); ]);
if (errors?.length > 0) {
return c.json(ErrorResponse, { status: 500 });
}
if (!title) { if (!title) {
return c.json({ success: false }, 404); return c.json(ErrorResponse, 404);
} }
return c.json({ success: true, result: title }, 200); return c.json({ success: true, result: title }, 200);

View File

@@ -7,7 +7,7 @@ export function getAmvstrmSearchResults() {
const url = new URL(urlString); const url = new URL(urlString);
const query = url.searchParams.get("q"); const query = url.searchParams.get("q");
if (!query) { if (!query || query === "a") {
return HttpResponse.json({ return HttpResponse.json({
code: 200, code: 200,
message: "success", message: "success",

View File

@@ -4,7 +4,7 @@ export function getAnilistSearchResults() {
return graphql.query("Search", ({ variables: { query, page } }) => { return graphql.query("Search", ({ variables: { query, page } }) => {
console.log(`Intercepting Search query with ${query} and page ${page}`); console.log(`Intercepting Search query with ${query} and page ${page}`);
if (!query || query === "amvstrm") { if (!query || query === "a" || query === "amvstrm") {
return HttpResponse.json({ return HttpResponse.json({
data: { data: {
Page: { Page: {