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