Preserve d tag when editing NIP-33 video notes

This commit is contained in:
thePR0M3TH3AN committed 2025-10-30 09:22:15 -04:00
1 parent ad3721fcdb
commit 864447fc71
2 files changed
+80 -3

No files matched your search

+12 -3
View File
@@ -4229,8 +4229,9 @@ export class NostrClient {
}
/**
* Edits a video by creating a *new event* with a brand-new d tag,
* but reuses the same videoRootId as the original.
* Edits a video by creating a new event that reuses the existing d tag
* so subsequent publishes overwrite the same NIP-33 addressable record
* while keeping the original videoRootId.
*
* This version forces version=2 for the original note and uses
* lowercase comparison for public keys.
@@ -4322,8 +4323,16 @@ export class NostrClient {
const oldRootId = baseEvent.videoRootId || baseEvent.id;
const preservedDTag = this.resolveEventDTag(baseEvent, originalEventStub);
const fallbackDTag =
(typeof baseEvent.id === "string" && baseEvent.id.trim()) ||
(typeof originalEventStub?.id === "string" && originalEventStub.id.trim()) ||
"";
const finalDTagValue =
preservedDTag || `${Date.now()}-edit-${Math.random().toString(36).slice(2)}`;
(typeof preservedDTag === "string" && preservedDTag.trim()) || fallbackDTag;
if (!finalDTagValue) {
throw new Error("Unable to determine a stable d tag for this edit.");
}
// Build the updated content object
const contentObject = {
+68
View File
@@ -96,3 +96,71 @@ test("editVideo preserves existing d tag", async (t) => {
"editVideo should preserve the original videoRootId",
);
});
test("editVideo falls back to base event id when d tag missing", async (t) => {
const client = new NostrClient();
const pubkey = "ABC123";
const baseEvent = {
id: "event-original-no-d",
pubkey,
version: 3,
videoRootId: "root-abc",
title: "Original Title",
url: "https://example.com/video.mp4",
magnet: "magnet:?xt=urn:btih:example",
ws: "wss://example.com",
xs: "https://example.com/file.torrent",
enableComments: true,
isPrivate: false,
isNsfw: false,
isForKids: false,
nip71: null,
thumbnail: "https://example.com/thumb.jpg",
description: "original",
mode: "live",
tags: [["t", "video"]],
};
client.getEventById = async (id) => (id === baseEvent.id ? baseEvent : null);
client.relays = ["wss://relay.one"];
client.pool = createStubPool();
client.ensureExtensionPermissions = async () => ({ ok: true });
const signedEvents = [];
const signer = {
type: "app",
pubkey,
signEvent: async (event) => {
signedEvents.push(event);
return { ...event, id: `signed-${signedEvents.length}` };
},
};
setActiveSigner(signer);
client.ensureActiveSignerForPubkey = async () => signer;
t.after(() => {
clearActiveSigner();
signedEvents.length = 0;
});
const result = await client.editVideo({ id: baseEvent.id }, { title: "Updated" }, pubkey);
assert.ok(result, "editVideo should return the signed event");
assert.equal(signedEvents.length, 1, "editVideo should sign exactly one event");
const signedEvent = signedEvents[0];
assert.ok(signedEvent, "signed event should be captured");
const dTags = signedEvent.tags.filter((tag) => Array.isArray(tag) && tag[0] === "d");
assert.deepEqual(
dTags,
[["d", baseEvent.id]],
"editVideo should fall back to the base event id for the d tag when none exists",
);
const parsedContent = JSON.parse(signedEvent.content);
assert.equal(
parsedContent.videoRootId,
baseEvent.videoRootId,
"editVideo should continue to use the original videoRootId",
);
});