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