redirecter for ao3 that adds opengraph metadata
1import { getSeries, getUser, getWork } from "@fujocoded/ao3.js";
2import { Hono } from "hono";
3import PageSkeleton from "./pages/PageSkeleton.jsx";
4import Home from "./pages/Home.jsx";
5import Image from "./pages/Image.jsx";
6
7const app = new Hono();
8
9app.get("/", (c) => {
10 return c.html(<Home />);
11});
12
13app.get("/works/:workId", async (c) => {
14 const workId = c.req.param("workId");
15 const work = await getWork({
16 workId: c.req.param("workId"),
17 chapterId: c.req.param("chapterId"),
18 });
19 const authorsFormatted = work.authors.map((a) => {
20 if (a.anonymous) return "Anonymous";
21 if (a.pseud !== a.username) return `${a.pseud} (${a.username})`;
22 return a.username;
23 });
24 const authors = authorsFormatted.length > 1
25 ? authorsFormatted.slice(0, -1).join(", ") + " & " +
26 authorsFormatted.slice(-1)
27 : authorsFormatted[0];
28 const title = `${work.title} by ${authors} - ${work.fandoms.join(", ")}`;
29 const desc = `Rating: ${work.rating} | ${work.category} | Updated ${
30 work.updatedAt ? work.updatedAt : work.publishedAt
31 } | Words: ${work.words} | ${
32 work.complete ? "Complete | " : ""
33 } ${work.summary}`;
34 return c.html(
35 <PageSkeleton title={title} description={desc} addr={`works/${workId}`} />,
36 );
37});
38
39app.get("/works/:workId/chapters/:chapterId", async (c) => {
40 const workId = c.req.param("workId");
41 const chapterId = c.req.param("chapterId");
42 const work = await getWork({
43 workId: c.req.param("workId"),
44 chapterId: c.req.param("chapterId"),
45 });
46 const authorsFormatted = work.authors.map((a) => {
47 if (a.anonymous) return "Anonymous";
48 if (a.pseud !== a.username) return `${a.pseud} (${a.username})`;
49 return a.username;
50 });
51 const authors = authorsFormatted.length > 1
52 ? authorsFormatted.slice(0, -1).join(", ") + " & " +
53 authorsFormatted.slice(-1)
54 : authorsFormatted[0];
55 const title =
56 `${work.title} by ${authors}, Chapter ${work.chapterInfo.index}${
57 work.chapterInfo.name ? `: ${work.chapterInfo.name}` : ""
58 } - ${work.fandoms.join(", ")}`;
59 const desc = `Rating: ${work.rating} | ${work.category} | Updated ${
60 work.updatedAt ? work.updatedAt : work.publishedAt
61 } | Words: ${work.words} | ${work.complete ? "Complete | " : ""} ${
62 work.chapterInfo.summary ? work.chapterInfo.summary : work.summary
63 }`;
64 return c.html(
65 <PageSkeleton
66 title={title}
67 description={desc}
68 addr={`works/${workId}/chapters/${chapterId}`}
69 />,
70 );
71});
72
73app.get("/series/:seriesId", async (c) => {
74 const seriesId = c.req.param("seriesId");
75 const series = await getSeries({ seriesId: seriesId });
76 const authorsFormatted = series.authors.map((a) => {
77 if (a.anonymous) return "Anonymous";
78 if (a.pseud !== a.username) return `${a.pseud} (${a.username})`;
79 return a.username;
80 });
81 const authors = authorsFormatted.length > 1
82 ? authorsFormatted.slice(0, -1).join(", ") + " & " +
83 authorsFormatted.slice(-1)
84 : authorsFormatted[0];
85 const title = `${series.name} by ${authors}`;
86 const desc = ` Updated ${
87 series.updatedAt ? series.updatedAt : series.publishedAt
88 } | Works: ${series.worksCount} | ${
89 series.complete ? "Complete | " : ""
90 } ${series.notes}`;
91 return c.html(
92 <PageSkeleton
93 title={title}
94 description={desc}
95 addr={`series/${seriesId}`}
96 />,
97 );
98});
99
100app.get("/users/:username", async (c) => {
101 const username = c.req.param("username");
102 const user = await getUser({ username: username });
103 return c.html(
104 <PageSkeleton
105 title={`${username}`}
106 description={user.header}
107 addr={`users/${username}`}
108 />,
109 );
110});
111
112app.get("/users/:username/pseuds/:pseud", async (c) => {
113 const username = c.req.param("username");
114 const pseud = c.req.param("pseud");
115 const user = await getUser({ username: username });
116 return c.html(
117 <PageSkeleton
118 title={`${pseud} (${username})`}
119 description={user.header}
120 addr={`users/${username}`}
121 />,
122 );
123});
124
125app.get("/preview/works/:workId", async (c) => {
126 const workId = c.req.param("workId");
127 const work = await getWork({
128 workId: workId,
129 });
130 const addr = `works/${workId}`;
131 return Image({ data: work, addr: addr });
132});
133
134app.get("/preview/works/:workId/chapters/:chapterId", async (c) => {
135 const workId = c.req.param("workId");
136 const chapterId = c.req.param("chapterId");
137 const work = await getWork({
138 workId: workId,
139 chapterId: chapterId,
140 });
141 const addr = `works/${workId}/chapters/${chapterId}`;
142 return Image({ data: work, addr: addr })
143})
144
145export default app;