booru-api/src/routes/[booru]/id/[id].ts
creations 9cb178aea4
All checks were successful
Code quality checks / biome (push) Successful in 9s
move to biomejs, add workflow move auth to header check readme
2025-04-15 17:33:24 -04:00

242 lines
4.3 KiB
TypeScript

import {
determineBooru,
getE621Auth,
getGelBooruAuth,
postExpectedFormat,
} from "@helpers/char";
import { fetch } from "bun";
import { logger } from "@helpers/logger";
const routeDef: RouteDef = {
method: "GET",
accepts: "*/*",
returns: "application/json",
};
async function handler(
request: Request,
_server: BunServer,
_requestBody: unknown,
query: Query,
params: Params,
): Promise<Response> {
const { tag_format } = query as {
tag_format: string;
};
const { booru, id } = params as { booru: string; id: string };
if (!booru || !id) {
return Response.json(
{
success: false,
code: 400,
error: "Missing booru or id",
},
{
status: 400,
},
);
}
const booruConfig: IBooruConfig | null = determineBooru(booru);
const isE621: boolean = booruConfig?.name === "e621.net";
const isGelbooru: boolean = booruConfig?.name === "gelbooru.com";
const gelbooruAuth: Record<string, string> | null = getGelBooruAuth(
request.headers,
);
if (isGelbooru && !gelbooruAuth) {
return Response.json(
{
success: false,
code: 401,
error: "Missing Gelbooru authentication headers",
},
{
status: 401,
},
);
}
if (!booruConfig) {
return Response.json(
{
success: false,
code: 404,
error: "Booru not found",
},
{
status: 404,
},
);
}
if (!booruConfig.enabled) {
return Response.json(
{
success: false,
code: 403,
error: "Booru is disabled",
},
{
status: 403,
},
);
}
const funcString: string | [string, string] = booruConfig.functions.id;
let url = `https://${booruConfig.endpoint}/${booruConfig.functions.id}${id}`;
if (isGelbooru && gelbooruAuth) {
url += `?api_key=${gelbooruAuth.api_key}&user_id=${gelbooruAuth.user_id}`;
}
if (Array.isArray(funcString)) {
const [start, end] = funcString;
url = `https://${booruConfig.endpoint}/${start}${id}${end}`;
}
try {
let headers: Record<string, string> | undefined;
if (isE621) {
const e621Auth: Record<string, string> | null = getE621Auth(
request.headers,
);
if (!e621Auth) {
return Response.json(
{
success: false,
code: 401,
error: "Missing E621 authentication headers",
},
{
status: 401,
},
);
}
headers = {
...e621Auth,
};
}
const response: Response = await fetch(url, {
headers,
});
if (!response.ok) {
logger.error([
"Failed to fetch post",
`Booru: ${booru}`,
`ID: ${id}`,
`Status: ${response.status}`,
`Status Text: ${response.statusText}`,
]);
return Response.json(
{
success: false,
code: response.status || 500,
error: response.statusText || "Could not reach booru",
},
{
status: response.status || 500,
},
);
}
const data: unknown = await response.json();
if (!data) {
logger.error(["No data returned", `Booru: ${booru}`, `ID: ${id}`]);
return Response.json(
{
success: false,
code: 404,
error: "Post not found, or no json data was returned",
},
{
status: 404,
},
);
}
const parsedData: Data = data as Data;
let posts: BooruPost[] = [];
if (parsedData.post) {
posts = [parsedData.post];
} else if (parsedData.posts) {
posts = parsedData.posts;
} else {
posts = Array.isArray(data) ? (data as BooruPost[]) : [];
}
if (posts.length === 0) {
logger.error(["No posts found", `Booru: ${booru}`, `ID: ${id}`]);
return Response.json(
{
success: false,
code: 404,
error: "Post not found",
},
{
status: 404,
},
);
}
const expectedData: { posts: BooruPost[] } | null = postExpectedFormat(
booruConfig,
posts,
tag_format,
);
if (!expectedData) {
logger.error([
"Unexpected data format",
`Booru: ${booru}`,
`ID: ${id}`,
`Data: ${JSON.stringify(data)}`,
]);
return Response.json(
{
success: false,
code: 500,
error: "Unexpected data format",
},
{
status: 500,
},
);
}
return Response.json(
{
success: true,
code: 200,
post: expectedData?.posts[0] || null,
},
{
status: 200,
},
);
} catch {
return Response.json(
{
success: false,
code: 500,
error: "Internal Server Error",
},
{
status: 500,
},
);
}
}
export { handler, routeDef };