mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-29 17:02:28 +00:00
Fix NIP-71 publish pubkey normalization
This commit is contained in:
1 parent
08afaf86c9
commit
4d3bf6f993
2 files changed
+95
-10
No files matched your search
+19
-10
@@ -3378,6 +3378,15 @@ export class NostrClient {
|
||||
async publishVideo(videoPayload, pubkey) {
|
||||
if (!pubkey) throw new Error("Not logged in to publish video.");
|
||||
|
||||
const normalizedPubkey =
|
||||
typeof pubkey === "string" ? pubkey.trim() : "";
|
||||
|
||||
if (!normalizedPubkey) {
|
||||
throw new Error("Not logged in to publish video.");
|
||||
}
|
||||
|
||||
const userPubkeyLower = normalizedPubkey.toLowerCase();
|
||||
|
||||
const { videoData, nip71Metadata } = extractVideoPublishPayload(videoPayload);
|
||||
const nip71EditedFlag =
|
||||
videoPayload && typeof videoPayload === "object"
|
||||
@@ -3389,7 +3398,7 @@ export class NostrClient {
|
||||
// controllers and revert helpers so all paths stay in lockstep.
|
||||
devLogger.log("Publishing new video with data:", videoData);
|
||||
if (nip71Metadata) {
|
||||
devLogger.log("Including NIP-71 metadata:", nip71Metadata);
|
||||
devLogger.log("Including NIP-71 metadata:", nip71Metadata);
|
||||
}
|
||||
|
||||
const rawMagnet = typeof videoData.magnet === "string" ? videoData.magnet : "";
|
||||
@@ -3455,7 +3464,7 @@ export class NostrClient {
|
||||
);
|
||||
|
||||
const event = buildVideoPostEvent({
|
||||
pubkey,
|
||||
pubkey: normalizedPubkey,
|
||||
created_at: createdAt,
|
||||
dTagValue,
|
||||
content: contentObject,
|
||||
@@ -3463,7 +3472,7 @@ export class NostrClient {
|
||||
});
|
||||
|
||||
devLogger.log("Publish event with brand-new root:", videoRootId);
|
||||
devLogger.log("Event content:", event.content);
|
||||
devLogger.log("Event content:", event.content);
|
||||
|
||||
try {
|
||||
const { signedEvent } = await this.signAndPublishEvent(event, {
|
||||
@@ -3496,7 +3505,7 @@ export class NostrClient {
|
||||
}
|
||||
|
||||
const mirrorEvent = buildVideoMirrorEvent({
|
||||
pubkey,
|
||||
pubkey: normalizedPubkey,
|
||||
created_at: createdAt,
|
||||
tags: mirrorTags,
|
||||
content: altText,
|
||||
@@ -3536,10 +3545,10 @@ export class NostrClient {
|
||||
description: contentObject.description,
|
||||
url: contentObject.url,
|
||||
magnet: contentObject.magnet,
|
||||
thumbnail: contentObject.thumbnail,
|
||||
mode: contentObject.mode,
|
||||
isPrivate: wantPrivate,
|
||||
isNsfw: contentObject.isNsfw,
|
||||
thumbnail: contentObject.thumbnail,
|
||||
mode: contentObject.mode,
|
||||
isPrivate: wantPrivate,
|
||||
isNsfw: contentObject.isNsfw,
|
||||
isForKids: contentObject.isForKids,
|
||||
};
|
||||
|
||||
@@ -3559,8 +3568,8 @@ export class NostrClient {
|
||||
},
|
||||
userPubkeyLower,
|
||||
{
|
||||
videoRootId: oldRootId,
|
||||
dTag: newD,
|
||||
videoRootId,
|
||||
dTag: dTagValue,
|
||||
eventId: signedEvent.id,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -283,9 +283,85 @@ try {
|
||||
}
|
||||
}
|
||||
|
||||
async function testPublishVideoNormalizesPubkeyForNip71Metadata() {
|
||||
const uppercasePubkey = "AB".repeat(32);
|
||||
const originalSignAndPublish = nostrClient.signAndPublishEvent;
|
||||
const originalPublishNip71 = nostrClient.publishNip71Video;
|
||||
|
||||
const publishedEvents = [];
|
||||
const nip71Calls = [];
|
||||
|
||||
nostrClient.signAndPublishEvent = async (event, options = {}) => {
|
||||
publishedEvents.push({ event, options });
|
||||
const contextLabel =
|
||||
typeof options?.context === "string" && options.context
|
||||
? options.context
|
||||
: "event";
|
||||
return {
|
||||
signedEvent: {
|
||||
...event,
|
||||
id: event?.id || `signed-${contextLabel}`,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
nostrClient.publishNip71Video = async (payload, pubkey, pointerOptions) => {
|
||||
nip71Calls.push({ payload, pubkey, pointerOptions });
|
||||
return null;
|
||||
};
|
||||
|
||||
try {
|
||||
const result = await nostrClient.publishVideo(
|
||||
{
|
||||
legacyFormData: {
|
||||
title: "Metadata Video",
|
||||
description: "Video with metadata",
|
||||
url: "https://cdn.example/video.mp4",
|
||||
mode: "live",
|
||||
},
|
||||
nip71: {
|
||||
title: "Metadata Video",
|
||||
imeta: [{ url: "https://cdn.example/video.mp4", m: "video/mp4" }],
|
||||
},
|
||||
},
|
||||
uppercasePubkey,
|
||||
);
|
||||
|
||||
assert.equal(typeof result?.id, "string", "publishVideo should resolve with a signed event");
|
||||
assert.ok(
|
||||
publishedEvents.some((entry) => entry.options?.context === "video note"),
|
||||
"publishVideo should sign the primary video note",
|
||||
);
|
||||
assert.equal(
|
||||
nip71Calls.length,
|
||||
1,
|
||||
"publishVideo should invoke publishNip71Video when metadata is provided",
|
||||
);
|
||||
assert.equal(
|
||||
nip71Calls[0]?.pubkey,
|
||||
uppercasePubkey.toLowerCase(),
|
||||
"publishVideo should normalize the pubkey passed to publishNip71Video",
|
||||
);
|
||||
assert.ok(
|
||||
typeof nip71Calls[0]?.pointerOptions?.videoRootId === "string" &&
|
||||
nip71Calls[0]?.pointerOptions?.videoRootId.length > 0,
|
||||
"publishVideo should supply pointer metadata for the new video",
|
||||
);
|
||||
assert.ok(
|
||||
typeof nip71Calls[0]?.pointerOptions?.dTag === "string" &&
|
||||
nip71Calls[0]?.pointerOptions?.dTag.length > 0,
|
||||
"publishVideo should provide the new d tag as a pointer",
|
||||
);
|
||||
} finally {
|
||||
nostrClient.signAndPublishEvent = originalSignAndPublish;
|
||||
nostrClient.publishNip71Video = originalPublishNip71;
|
||||
}
|
||||
}
|
||||
|
||||
await testPublishVideoRejectsWhenAllRelaysFail();
|
||||
await testPublishSubscriptionListRejectsWhenAllRelaysFail();
|
||||
await testPublishBlockListRejectsWhenAllRelaysFail();
|
||||
await testPublishVideoNormalizesPubkeyForNip71Metadata();
|
||||
|
||||
console.log("nostr publish rejection tests passed");
|
||||
} finally {
|
||||
|
||||
Reference in new issue
Block a user