// Per-video OpenGraph rendering for crawlers — see api/_lib/ogRenderer.mjs.
//
// Two things here are security-relevant and get the most attention:
// 1. Escaping. Titles/descriptions come from arbitrary nostr events, and this
// HTML is served from bitvid's own origin.
// 2. Gating. A crawler never authenticates, so anything emitted is public
// forever in third-party caches. Deleted/private/NSFW/non-whitelisted
// videos must fall back to the generic site card.
import test from "node:test";
import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import {
CRAWLER_USER_AGENT_PATTERN,
escapeHtmlAttribute,
isCrawlerUserAgent,
isPubliclyShareable,
normalizeText,
parseVideoEvent,
renderOgHtml,
sanitizeAbsoluteUrl,
} from "../api/_lib/ogRenderer.mjs";
const PUBKEY = "b7c6f6915cfa9a62fff6a1f02604de88c23c6c6c6d1b8f62c7cc10749f307e81";
const publicVideo = () => ({
pubkey: PUBKEY,
title: "Why I'm (sort of) not worried about AI",
description: "A talk about creativity and machines.",
thumbnail: "https://cdn.example/thumb.jpg",
deleted: false,
isPrivate: false,
isNsfw: false,
invalid: false,
});
const FALLBACK = {
siteName: "bitvid",
title: "bitvid - Decentralized Video Sharing",
description: "Decentralized video sharing on Nostr.",
image: "https://bitvid.network/assets/jpg/bitvid.jpg",
url: "https://bitvid.network",
};
const render = (video, extra = {}) =>
renderOgHtml({
video,
shareUrl: "https://bitvid.network/?v=nevent1abc",
embedUrl: "https://bitvid.network/embed.html?pointer=nevent1abc",
fallback: FALLBACK,
gate: isPubliclyShareable(video, extra.gateOptions || {}),
...extra.render,
});
// --- escaping -------------------------------------------------------------
test("escapeHtmlAttribute neutralizes attribute-breaking characters", () => {
assert.equal(
escapeHtmlAttribute(`">`),
""><script>alert(1)</script>"
);
assert.equal(escapeHtmlAttribute("a & b"), "a & b");
assert.equal(escapeHtmlAttribute("it's"), "it's");
assert.equal(escapeHtmlAttribute(null), "");
assert.equal(escapeHtmlAttribute(42), "");
});
test("a hostile title cannot break out of the meta tag", () => {
const video = publicVideo();
video.title = `">"), false, "no raw script tag");
assert.equal(html.includes(`">