summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorseth <[email protected]>2024-10-12 14:28:54 -0400
committerseth <[email protected]>2024-10-12 14:59:04 -0400
commit6a2d9e752fab27b59da4f194b0ef6daf7e8b6d81 (patch)
treeed8f9f07861a0a4463dcd910baa349b6cc6656aa /src
parent08912b439bd61088dd849b9342a81341fa9e4a23 (diff)
port to deno
Diffstat (limited to 'src')
-rw-r--r--src/consts.ts4
-rw-r--r--src/env.ts6
-rw-r--r--src/index.ts93
-rw-r--r--src/schemas.ts34
-rw-r--r--src/teawie.ts98
5 files changed, 0 insertions, 235 deletions
diff --git a/src/consts.ts b/src/consts.ts
deleted file mode 100644
index 0e31b83..0000000
--- a/src/consts.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import { version } from "../package.json";
-
-export const VERSION = version;
-export const USER_AGENT = `teawieAPI/${version}`;
diff --git a/src/env.ts b/src/env.ts
deleted file mode 100644
index 2ee3db7..0000000
--- a/src/env.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export type Bindings = {
- REDIRECT_ROOT?: string;
- TEAWIE_API: KVNamespace;
-};
-
-export type Variables = Record<string, never>;
diff --git a/src/index.ts b/src/index.ts
deleted file mode 100644
index 82eaad9..0000000
--- a/src/index.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import { logger } from "hono/logger";
-import { prettyJSON } from "hono/pretty-json";
-import { swaggerUI } from "@hono/swagger-ui";
-import { OpenAPIHono, createRoute } from "@hono/zod-openapi";
-import { VERSION } from "./consts";
-import { Bindings, Variables } from "./env";
-import {
- ListTeawiesParams,
- ListTeawiesResponse,
- RandomTeawiesResponse,
-} from "./schemas";
-import { imageUrls } from "./teawie";
-
-const app = new OpenAPIHono<{ Bindings: Bindings; Variables: Variables }>();
-
-app.use("*", logger());
-app.use("*", prettyJSON());
-
-app.get("/", (c) =>
- c.redirect(c.env.REDIRECT_ROOT ?? "https://github.com/getchoo/teawieAPI"),
-);
-
-app.get("/swagger", swaggerUI({ url: "/doc" }));
-
-app.doc("/doc", {
- openapi: "3.0.0",
- info: {
- version: VERSION,
- title: "teawieAPI",
- },
-});
-
-app.openapi(
- createRoute({
- method: "get",
- path: "/list_teawies",
- request: {
- params: ListTeawiesParams,
- },
- responses: {
- 200: {
- content: {
- "application/json": {
- schema: ListTeawiesResponse,
- },
- },
- description: "List known Teawie URLS",
- },
- },
- }),
- async (c) => {
- const { limit } = c.req.query();
- const urls = await imageUrls(c.env.TEAWIE_API);
-
- return c.json(
- {
- urls: urls.splice(0, parseInt(limit ?? "5")),
- },
- 200,
- );
- },
-);
-
-app.openapi(
- createRoute({
- method: "get",
- path: "/random_teawie",
- responses: {
- 200: {
- content: {
- "application/json": {
- schema: RandomTeawiesResponse,
- },
- },
- description: "A random URL to a picture of Teawie",
- },
- },
- }),
- async (c) =>
- imageUrls(c.env.TEAWIE_API).then((urls) =>
- c.json({
- url: urls[Math.floor(Math.random() * urls.length)],
- }),
- ),
-);
-
-app.onError((error, c) => {
- console.error(error);
-
- return c.json({ error: error.message }, 500);
-});
-
-export default app;
diff --git a/src/schemas.ts b/src/schemas.ts
deleted file mode 100644
index 669674a..0000000
--- a/src/schemas.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { z } from "@hono/zod-openapi";
-
-const ErrorResponse = z.string().optional().openapi({
- description: "Error message reported by server",
-});
-
-const TeawieURLResponse = z.object({
- url: z.string().url().optional().openapi({
- description: "URL to Teawie",
- }),
-
- error: ErrorResponse,
-});
-
-export const ListTeawiesParams = z.object({
- limit: z
- .string()
- .optional()
- .default("5")
- .refine((data) => {
- const parsed = parseInt(data);
- return !isNaN(parsed);
- })
- .openapi({
- description: "Maximum number of Teawie URLs to be returned",
- }),
-});
-
-export const ListTeawiesResponse = z.object({
- urls: z.array(z.string().url()).optional(),
- error: ErrorResponse,
-});
-
-export const RandomTeawiesResponse = TeawieURLResponse;
diff --git a/src/teawie.ts b/src/teawie.ts
deleted file mode 100644
index 65d6617..0000000
--- a/src/teawie.ts
+++ /dev/null
@@ -1,98 +0,0 @@
-import { USER_AGENT } from "./consts";
-import { Endpoints } from "@octokit/types";
-
-type repositoryPathContentsResponse =
- Endpoints["GET /repos/{owner}/{repo}/contents/{path}"]["response"];
-
-const GITHUB_API = "https://api.github.com";
-
-// Teawie repository owner and name
-const REPO_OWNER = "SympathyTea";
-const REPO_NAME = "Teawie-Archive";
-
-// Subdirectories of the above repository containing files we want
-const SUBDIRS = [
- "teawie-media/Original Teawies",
- "teawie-media/Teawie Variants",
- "teawie-media/Teawie in Places",
- "teawie-media/Unfinished Teawies",
-];
-
-// File extensions we consider to be images
-const IMAGE_EXTENSIONS = ["gif", "jpg", "jpeg", "png", "svg", "webp"];
-
-const contentsOf = (
- path: string,
-): Promise<repositoryPathContentsResponse["data"]> =>
- fetch(`${GITHUB_API}/repos/${REPO_OWNER}/${REPO_NAME}/contents/${path}`, {
- headers: {
- accept: "application/vnd.github+json",
- "user-agent": USER_AGENT,
- },
- })
- .then((response) => {
- if (!response.ok) {
- throw new Error(
- `HTTP Error ${response.status}: ${response.statusText}`,
- );
- }
-
- return response.json();
- })
- .then((json) => {
- return json as repositoryPathContentsResponse["data"];
- });
-
-const imageUrlsIn = (
- files: repositoryPathContentsResponse["data"],
-): string[] => {
- // NOTE: This is done because the response may only contain data
- // for a single file's path
- const filesArray = Array.isArray(files) ? files : [files];
-
- return (
- filesArray
- // Find *files* that are (probably) images and have a download URL
- .filter(
- (file) =>
- !Array.isArray(file) &&
- file.download_url &&
- file.type == "file" &&
- IMAGE_EXTENSIONS.includes(file.name.split(".").at(-1) ?? ""),
- )
- .map((file) => {
- // Should this happen? No
- // Could it? I don't know
- // But let's be safe :steamhappy:
- if (!file.download_url) {
- throw new Error(
- `Could not find download URL for file "${file.name}"`,
- );
- }
-
- return file.download_url;
- })
- );
-};
-
-export const imageUrls = async (kv: KVNamespace): Promise<string[]> => {
- const cached = await kv.get("urls");
- if (cached) {
- console.trace("Found Teawie URLs in cache!");
- return JSON.parse(cached);
- }
-
- console.warn("Couldn't find Teawie URLs in cache! Fetching fresh ones");
- const fresh = await Promise.all(SUBDIRS.map(contentsOf)).then((responses) => {
- // See the note above
- const flatResponses = responses.flatMap((response) =>
- Array.isArray(response) ? response : [response],
- );
-
- return imageUrlsIn(flatResponses);
- });
-
- await kv.put("urls", JSON.stringify(fresh), { expirationTtl: 60 * 60 });
-
- return fresh;
-};