Hey is a decentralized and permissionless social media app built with Lens Protocol 馃尶
at main 102 lines 4.4 kB view raw
1import { 2 BRAND_COLOR, 3 STATIC_IMAGES_URL, 4 TRANSFORMS 5} from "@hey/data/constants"; 6import escapeHtml from "@hey/helpers/escapeHtml"; 7import getAccount from "@hey/helpers/getAccount"; 8import getAvatar from "@hey/helpers/getAvatar"; 9import getPostData from "@hey/helpers/getPostData"; 10import normalizeDescription from "@hey/helpers/normalizeDescription"; 11import { PostDocument, type PostFragment } from "@hey/indexer"; 12import type { Context } from "hono"; 13import { html } from "hono/html"; 14import generateOg from "./ogUtils"; 15 16const getPost = async (ctx: Context) => { 17 const { slug } = ctx.req.param(); 18 19 return generateOg({ 20 buildHtml: (post: PostFragment) => { 21 const targetPost = 22 (post as any).__typename === "Repost" ? (post as any).repostOf : post; 23 const { author, metadata } = targetPost as any; 24 const { username } = getAccount(author); 25 const postData = getPostData(metadata); 26 const filteredContent = postData?.content || ""; 27 const title = `${(targetPost as any).__typename} by ${username} on Hey`; 28 const description = normalizeDescription(filteredContent, title); 29 const postUrl = `https://hey.xyz/posts/${(post as any).slug}`; 30 31 const escTitle = escapeHtml(title); 32 const escDescription = escapeHtml(description); 33 34 const asset = postData?.asset; 35 const attachments = postData?.attachments || []; 36 37 const imageUris = (() => { 38 const list: string[] = []; 39 if (asset?.type === "Image" && asset.uri) list.push(asset.uri); 40 for (const att of attachments) { 41 if (att.type === "Image" && att.uri) list.push(att.uri); 42 } 43 return Array.from(new Set(list)).slice(0, 4); 44 })(); 45 46 // OG/Twitter meta: prefer images; fallback to author avatar. No video support. 47 const ogImageCandidates = imageUris.length 48 ? imageUris 49 : [getAvatar(author, TRANSFORMS.AVATAR_BIG)]; 50 const ogType = "article"; 51 const twitterCard = imageUris.length ? "summary_large_image" : "summary"; 52 53 return html` 54 <html> 55 <head> 56 <meta charSet="utf-8" /> 57 <meta name="viewport" content="width=device-width" /> 58 <meta http-equiv="content-language" content="en-US" /> 59 <meta name="theme-color" content="${BRAND_COLOR}" /> 60 <title>${escTitle}</title> 61 <meta name="description" content="${escDescription}" /> 62 <meta property="og:title" content="${escTitle}" /> 63 <meta property="og:description" content="${escDescription}" /> 64 <meta property="og:type" content="${ogType}" /> 65 <meta property="og:site_name" content="Hey" /> 66 <meta property="og:url" content="https://hey.xyz/posts/${(post as any).slug}" /> 67 <meta property="og:logo" content="${STATIC_IMAGES_URL}/app-icon/0.png" /> 68 ${ogImageCandidates.map((img) => html`<meta property="og:image" content="${img}" />`)} 69 <meta name="twitter:card" content="${twitterCard}" /> 70 <meta name="twitter:title" content="${escTitle}" /> 71 <meta name="twitter:description" content="${escDescription}" /> 72 <meta name="twitter:image" content="${ogImageCandidates[0]}" /> 73 <meta name="twitter:site" content="@heydotxyz" /> 74 <link rel="icon" href="https://hey.xyz/favicon.ico" /> 75 <link rel="canonical" href="https://hey.xyz/posts/${(post as any).slug}" /> 76 </head> 77 <body> 78 <h1>${escTitle}</h1> 79 <h2>${escDescription}</h2> 80 <div> 81 <b>Stats</b> 82 <ul> 83 <li><a href="${postUrl}">Collects: ${targetPost.stats.collects}</a></li> 84 <li><a href="${postUrl}">Tips: ${targetPost.stats.tips}</a></li> 85 <li><a href="${postUrl}">Comments: ${targetPost.stats.comments}</a></li> 86 <li><a href="${postUrl}">Likes: ${targetPost.stats.reactions}</a></li> 87 <li><a href="${postUrl}">Reposts: ${targetPost.stats.reposts}</a></li> 88 <li><a href="${postUrl}/quotes">Quotes: ${targetPost.stats.quotes}</a></li> 89 </ul> 90 </div> 91 </body> 92 </html> 93 `; 94 }, 95 ctx, 96 extractData: (data) => data.post as PostFragment | null, 97 query: PostDocument, 98 variables: { request: { post: slug } } 99 }); 100}; 101 102export default getPost;