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