From 72970bf4807ddcda190344d7e825001d5938b20b Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Wed, 7 Aug 2024 18:50:32 -0500 Subject: [PATCH] Code style changes --- src/config.ts | 5 ++-- src/controllers/frontend.ts | 46 ++++++++++++++++++++++--------------- src/utils/og-metadata.ts | 14 +++++------ src/views/meta.ts | 44 +++++++++++++++++++---------------- 4 files changed, 61 insertions(+), 48 deletions(-) diff --git a/src/config.ts b/src/config.ts index 86cb05cd..9d89d026 100644 --- a/src/config.ts +++ b/src/config.ts @@ -250,8 +250,9 @@ class Conf { static get cronEnabled(): boolean { return optionalBooleanSchema.parse(Deno.env.get('CRON_ENABLED')) ?? true; } - static get opengraphRouteRegex(): string { - return Deno.env.get('OPENGRAPH_ROUTE_REGEX') || + /** Crawler User-Agent regex to render link previews to. */ + static get crawlerRegex(): string { + return Deno.env.get('CRAWLER_REGEX') || 'googlebot|bingbot|yandex|baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterestbot|slackbot|vkShare|W3C_Validator|whatsapp|mastodon|pleroma|Discordbot|AhrefsBot|SEMrushBot|MJ12bot|SeekportBot|Synapse|Matrix'; } /** Path to the custom policy module. Must be an absolute path, https:, npm:, or jsr: URI. */ diff --git a/src/controllers/frontend.ts b/src/controllers/frontend.ts index 72e3931d..5c7e4c62 100644 --- a/src/controllers/frontend.ts +++ b/src/controllers/frontend.ts @@ -21,30 +21,43 @@ const META_PLACEHOLDER = '' as const; async function buildTemplateOpts(params: PathParams, url: string): Promise { const store = await Storages.db(); const meta = await getInstanceMetadata(store); + const res: OpenGraphTemplateOpts = { - title: `View this page on ${meta.name}`, + title: meta.name, type: 'article', description: meta.about, url, site: meta.name, image: { url: Conf.local('/favicon.ico'), - w: 48, - h: 48, }, }; + try { - if (params.acct && !params.statusId) { + if (params.statusId) { + const { description, image, title } = await getStatusInfo(params.statusId); + + res.description = description; + res.title = title; + + if (res.image) { + res.image = image; + } + } else if (params.acct) { const key = /^[a-f0-9]{64}$/.test(params.acct) ? 'pubkey' : 'handle'; let handle = ''; try { const profile = await fetchProfile({ [key]: params.acct }); handle = await getHandle(params.acct, profile); - res.description = profile.meta.about || `@${handle}'s Nostr profile`; + + res.description = profile.meta.about; + if (profile.meta.picture) { - res.image = { url: profile.meta.picture, h: 150, w: 150 }; + res.image = { + url: profile.meta.picture, + }; } - } catch (_) { + } catch { console.debug(`couldn't find kind 0 for ${params.acct}`); // @ts-ignore we don't want getHandle trying to do a lookup here // but we do want it to give us a nice pretty npub @@ -52,14 +65,8 @@ async function buildTemplateOpts(params: PathParams, url: string): Promise { try { const content = await Deno.readTextFile(new URL('../../public/index.html', import.meta.url)); + const ua = c.req.header('User-Agent'); console.debug('ua', ua); - if (!SHOULD_INJECT_RE.test(ua || '')) { + + if (!new RegExp(Conf.crawlerRegex, 'i').test(ua ?? '')) { return c.html(content); } + if (content.includes(META_PLACEHOLDER)) { const params = getPathParams(c.req.path); if (params) { @@ -87,7 +95,7 @@ export const frontendController: AppMiddleware = async (c, next) => { const meta = metadataView(await buildTemplateOpts(params, Conf.local(c.req.path))); return c.html(content.replace(META_PLACEHOLDER, meta)); } catch (e) { - console.log(`Error in building meta tags: ${e}`); + console.log(`Error building meta tags: ${e}`); return c.html(content); } } diff --git a/src/utils/og-metadata.ts b/src/utils/og-metadata.ts index 7c748b5b..beaaac95 100644 --- a/src/utils/og-metadata.ts +++ b/src/utils/og-metadata.ts @@ -1,9 +1,9 @@ import { NostrEvent, NostrMetadata, NSchema as n } from '@nostrify/nostrify'; -import { getAuthor, getEvent } from '@/queries.ts'; +import { Stickynotes } from '@soapbox/stickynotes'; import { nip19, nip27 } from 'nostr-tools'; import { match } from 'path-to-regexp'; -import { Stickynotes } from '@soapbox/stickynotes'; +import { getAuthor, getEvent } from '@/queries.ts'; import { lookupPubkey } from '@/utils/lookup.ts'; import { parseAndVerifyNip05 } from '@/utils/nip05.ts'; import { parseNip05 } from '@/utils.ts'; @@ -15,7 +15,7 @@ export interface OpenGraphTemplateOpts { type: 'article' | 'profile' | 'website'; url: string; image?: StatusInfo['image']; - description: string; + description?: string; site: string; } @@ -26,8 +26,8 @@ interface StatusInfo { description: string; image?: { url: string; - w: number; - h: number; + w?: number; + h?: number; alt?: string; }; } @@ -50,7 +50,7 @@ const SSR_ROUTES = [ const SSR_ROUTE_MATCHERS = SSR_ROUTES.map((route) => match(route, { decode: decodeURIComponent })); -export function getPathParams(path: string) { +export function getPathParams(path: string): PathParams | undefined { for (const matcher of SSR_ROUTE_MATCHERS) { const result = matcher(path); if (!result) continue; @@ -144,7 +144,7 @@ export async function getHandle(id: string, acc?: ProfileInfo) { export async function getStatusInfo(id: string): Promise { const event = await getEvent(id); - if (!id || !event) throw new Error('Invalid post id supplied'); + if (!event) throw new Error('Invalid post id supplied'); let title = 'View post on Ditto'; try { const handle = await getHandle(event.pubkey); diff --git a/src/views/meta.ts b/src/views/meta.ts index f4f2b470..5cdc9a4d 100644 --- a/src/views/meta.ts +++ b/src/views/meta.ts @@ -6,31 +6,35 @@ import { OpenGraphTemplateOpts } from '@/utils/og-metadata.ts'; * @param opts the metadata to use to fill the template. * @returns the built OpenGraph metadata. */ -export const metadataView = ({ title, type, url, image, description, site }: OpenGraphTemplateOpts): string => { - const res = []; - res.push(html`\ - - - - - - - - - `); +export function metadataView({ title, type, url, image, description, site }: OpenGraphTemplateOpts): string { + const res: string[] = [ + html` `, + html` `, + html` `, + html` `, + html` `, + html` `, + ]; + + if (description) { + res.push(html``); + res.push(html``); + } if (image) { - res.push(html`\ - - - - - `); + res.push(html``); + res.push(html``); + + if (image.w && image.h) { + res.push(html``); + res.push(html``); + } + if (image.alt) { res.push(html``); res.push(html``); } } - return res.join('\n').replace(/\n+/g, '\n').replace(/^[ ]+/gm, ''); -}; + return res.join(''); +}