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