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.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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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 ?? [],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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,
|
|
||||||
status,
|
|
||||||
bannerImage,
|
|
||||||
coverImage: {
|
|
||||||
extraLarge: extraLargeCoverImage,
|
|
||||||
large: largeCoverImage,
|
|
||||||
medium: mediumCoverImage,
|
|
||||||
},
|
|
||||||
countryOfOrigin,
|
|
||||||
nextair: nextAiringEpisode,
|
|
||||||
score: { averageScore },
|
|
||||||
},
|
|
||||||
anifyInfo,
|
|
||||||
]) => {
|
|
||||||
return {
|
return {
|
||||||
id,
|
id: amvstrmInfo.id,
|
||||||
idMal,
|
idMal: amvstrmInfo.idMal,
|
||||||
title: {
|
title: {
|
||||||
userPreferred: userPreferredTitle,
|
userPreferred: amvstrmInfo.title.userPreferred,
|
||||||
english: englishTitle,
|
english: amvstrmInfo.title.english,
|
||||||
},
|
},
|
||||||
description,
|
description: amvstrmInfo.description,
|
||||||
episodes,
|
episodes: amvstrmInfo.episodes,
|
||||||
genres,
|
genres: amvstrmInfo.genres,
|
||||||
status,
|
status: amvstrmInfo.status,
|
||||||
averageScore,
|
averageScore: amvstrmInfo.score.averageScore,
|
||||||
bannerImage: bannerImage ?? anifyInfo?.bannerImage,
|
bannerImage: amvstrmInfo.bannerImage ?? anifyInfo?.bannerImage,
|
||||||
coverImage: {
|
coverImage: {
|
||||||
extraLarge: extraLargeCoverImage,
|
extraLarge: amvstrmInfo.coverImage.extraLarge,
|
||||||
large: largeCoverImage,
|
large: amvstrmInfo.coverImage.large,
|
||||||
medium: mediumCoverImage,
|
medium: amvstrmInfo.coverImage.medium,
|
||||||
},
|
},
|
||||||
countryOfOrigin: countryOfOrigin ?? anifyInfo?.countryOfOrigin,
|
countryOfOrigin:
|
||||||
nextAiringEpisode,
|
amvstrmInfo.countryOfOrigin ?? anifyInfo?.countryOfOrigin,
|
||||||
|
nextAiringEpisode: amvstrmInfo.nextair,
|
||||||
mediaListEntry: null,
|
mediaListEntry: null,
|
||||||
};
|
};
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type AnifyInformation = {
|
type AnifyInformation = {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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: {
|
||||||
|
|||||||
Reference in New Issue
Block a user