mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Add NIP-71 metadata wiring and caching
This commit is contained in:
1 parent
c3f08a8178
commit
04865ffdc5
3 files changed
+990
-23
No files matched your search
+866
-18
File diff suppressed because it is too large.
Load diff
@@ -398,10 +398,6 @@ export class NostrService {
|
||||
let legacyResult = null;
|
||||
|
||||
try {
|
||||
nip71Result = await this.nostrClient.publishNip71Video(
|
||||
publishPayload,
|
||||
pubkey
|
||||
);
|
||||
legacyResult = await this.nostrClient.publishVideo(
|
||||
publishPayload,
|
||||
pubkey
|
||||
@@ -411,6 +407,51 @@ export class NostrService {
|
||||
throw error;
|
||||
}
|
||||
|
||||
let shouldAttemptNip71 = true;
|
||||
const pointerIdentifiers = {
|
||||
eventId: legacyResult?.id,
|
||||
};
|
||||
|
||||
if (Array.isArray(legacyResult?.tags)) {
|
||||
const dTag = legacyResult.tags.find(
|
||||
(tag) => Array.isArray(tag) && tag[0] === "d" && typeof tag[1] === "string"
|
||||
);
|
||||
if (dTag) {
|
||||
pointerIdentifiers.dTag = dTag[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (legacyResult?.content) {
|
||||
try {
|
||||
const parsed = JSON.parse(legacyResult.content);
|
||||
if (parsed && typeof parsed.videoRootId === "string") {
|
||||
pointerIdentifiers.videoRootId = parsed.videoRootId;
|
||||
}
|
||||
if (parsed && parsed.isPrivate) {
|
||||
shouldAttemptNip71 = false;
|
||||
}
|
||||
} catch (parseError) {
|
||||
this.log("[nostrService] Failed to parse legacy publish payload", parseError);
|
||||
}
|
||||
}
|
||||
|
||||
if (!pointerIdentifiers.videoRootId) {
|
||||
shouldAttemptNip71 = false;
|
||||
}
|
||||
|
||||
if (shouldAttemptNip71) {
|
||||
try {
|
||||
nip71Result = await this.nostrClient.publishNip71Video(
|
||||
publishPayload,
|
||||
pubkey,
|
||||
pointerIdentifiers
|
||||
);
|
||||
} catch (nip71Error) {
|
||||
detail.nip71Error = nip71Error;
|
||||
this.log("[nostrService] NIP-71 publish failed", nip71Error);
|
||||
}
|
||||
}
|
||||
|
||||
const result = { legacy: legacyResult, nip71: nip71Result };
|
||||
detail.result = result;
|
||||
this.emit("videos:published", detail);
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
|
||||
import { buildNip71VideoEvent } from "../js/nostr.js";
|
||||
import {
|
||||
buildNip71VideoEvent,
|
||||
extractNip71MetadataFromTags,
|
||||
} from "../js/nostr.js";
|
||||
|
||||
test("buildNip71VideoEvent assembles rich metadata", () => {
|
||||
const metadata = {
|
||||
@@ -162,3 +165,78 @@ test("buildNip71VideoEvent falls back to summary and selects kind", () => {
|
||||
"should use fallback summary when metadata summary missing"
|
||||
);
|
||||
});
|
||||
|
||||
test("buildNip71VideoEvent attaches pointer tags", () => {
|
||||
const metadata = {
|
||||
kind: 21,
|
||||
summary: "Pointer test",
|
||||
imeta: [{ url: "https://cdn.example/clip.mp4" }],
|
||||
};
|
||||
|
||||
const pubkey = "f".repeat(64);
|
||||
const pointerIdentifiers = {
|
||||
videoRootId: "root-123",
|
||||
eventId: "event-456",
|
||||
dTag: "pointer-d-tag",
|
||||
};
|
||||
|
||||
const event = buildNip71VideoEvent({
|
||||
metadata,
|
||||
pubkey,
|
||||
title: "Pointer Demo",
|
||||
pointerIdentifiers,
|
||||
});
|
||||
|
||||
assert.ok(event, "event should be built with pointer tags");
|
||||
const pointerTags = event.tags.filter((tag) =>
|
||||
["a", "video-root", "e", "d"].includes(tag[0])
|
||||
);
|
||||
assert.deepEqual(pointerTags, [
|
||||
["a", `30078:${pubkey}:${pointerIdentifiers.videoRootId}`],
|
||||
["video-root", pointerIdentifiers.videoRootId],
|
||||
["e", pointerIdentifiers.eventId],
|
||||
["d", pointerIdentifiers.dTag],
|
||||
]);
|
||||
});
|
||||
|
||||
test("extractNip71MetadataFromTags parses metadata and pointers", () => {
|
||||
const event = {
|
||||
id: "nip71-event",
|
||||
kind: 22,
|
||||
created_at: 123,
|
||||
content: "Summary text",
|
||||
tags: [
|
||||
["title", "Metadata Title"],
|
||||
["published_at", "1700000100"],
|
||||
["alt", "alt text"],
|
||||
["duration", "321"],
|
||||
["content-warning", "Bright lights"],
|
||||
["imeta", "url https://cdn.example/video.mp4", "m video/mp4"],
|
||||
["text-track", "https://cdn.example/captions.vtt", "captions", "en"],
|
||||
["segment", "00:00", "00:10", "Intro", "https://cdn.example/thumb.jpg"],
|
||||
["t", "nostr"],
|
||||
["p", "c".repeat(64), "wss://relay.example"],
|
||||
["r", "https://example.com/info"],
|
||||
["a", "30078:deadbeef:root-123"],
|
||||
["video-root", "root-123"],
|
||||
["e", "event-456"],
|
||||
["d", "d-pointer"],
|
||||
],
|
||||
};
|
||||
|
||||
const parsed = extractNip71MetadataFromTags(event);
|
||||
assert.ok(parsed, "parser should produce a result");
|
||||
assert.deepEqual(parsed.metadata.title, "Metadata Title");
|
||||
assert.deepEqual(parsed.metadata.summary, "Summary text");
|
||||
assert.equal(parsed.metadata.duration, 321);
|
||||
assert.equal(parsed.metadata.alt, "alt text");
|
||||
assert.equal(parsed.metadata.contentWarning, "Bright lights");
|
||||
assert.deepEqual(parsed.metadata.hashtags, ["nostr"]);
|
||||
assert.deepEqual(parsed.metadata.references, ["https://example.com/info"]);
|
||||
assert.equal(parsed.metadata.textTracks.length, 1);
|
||||
assert.equal(parsed.metadata.imeta.length, 1);
|
||||
assert(parsed.pointers.videoRootIds.has("root-123"));
|
||||
assert(parsed.pointers.videoEventIds.has("event-456"));
|
||||
assert(parsed.pointers.dTags.has("d-pointer"));
|
||||
assert(parsed.pointers.pointerValues.has("30078:deadbeef:root-123"));
|
||||
});
|
||||
Reference in new issue
Block a user