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