ditto/packages/ditto/utils/og-metadata.ts
2025-02-15 14:21:05 -06:00

66 lines
1.6 KiB
TypeScript

import { nip19 } from 'nostr-tools';
import { match } from 'path-to-regexp';
import { MastodonAccount } from '@/entities/MastodonAccount.ts';
import { MastodonStatus } from '@/entities/MastodonStatus.ts';
import { InstanceMetadata } from '@/utils/instance.ts';
export interface MetadataEntities {
status?: MastodonStatus;
account?: MastodonAccount;
instance: InstanceMetadata;
}
export interface MetadataPathParams {
statusId?: string;
acct?: string;
bech32?: string;
}
/** URL routes to serve metadata on. */
const SSR_ROUTES = [
'/\\@:acct/posts/:statusId',
'/\\@:acct/:statusId',
'/\\@:acct',
'/users/:acct/statuses/:statusId',
'/users/:acct',
'/statuses/:statusId',
'/notice/:statusId',
'/posts/:statusId',
'/:bech32',
] as const;
const SSR_ROUTE_MATCHERS = SSR_ROUTES.map((route) => match(route));
export function getPathParams(path: string): MetadataPathParams | undefined {
for (const matcher of SSR_ROUTE_MATCHERS) {
const result = matcher(path);
if (!result) continue;
const params: MetadataPathParams = result.params;
if (params.bech32) {
try {
const decoded = nip19.decode(params.bech32);
switch (decoded.type) {
case 'nevent':
params.statusId = decoded.data.id;
break;
case 'note':
params.statusId = decoded.data;
break;
case 'nprofile':
params.acct = decoded.data.pubkey;
break;
case 'npub':
params.acct = decoded.data;
break;
}
} catch {
// fall through
}
}
return params;
}
}