From e6b6522f6ffb6bb06e7de77e0fb249f9d1fcbd0e Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Sat, 27 Sep 2025 12:34:21 -0400 Subject: [PATCH] Handle legacy video deletions without d tags --- js/channelProfile.js | 19 +++++++++---------- js/nostr.js | 39 +++++++++++++++++++++++---------------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/js/channelProfile.js b/js/channelProfile.js index 1a5037cb..531d5ad4 100644 --- a/js/channelProfile.js +++ b/js/channelProfile.js @@ -218,19 +218,18 @@ async function loadUserVideos(pubkey) { } } - // 3) Convert to "video" objects - let videos = []; - for (const evt of events) { - const vid = sharedConvertEventToVideo(evt); - if (!vid.invalid && !vid.deleted) { - videos.push(vid); - } - } + // 3) Convert to "video" objects and keep everything (including tombstones) + const convertedVideos = events + .map((evt) => sharedConvertEventToVideo(evt)) + .filter((vid) => !vid.invalid); // 4) Deduplicate older overshadowed versions => newest only - videos = app?.dedupeVideosByRoot?.(videos) ?? dedupeToNewestByRoot(videos); + const newestByRoot = + app?.dedupeVideosByRoot?.(convertedVideos) ?? + dedupeToNewestByRoot(convertedVideos); - // 5) Filter out blacklisted IDs / authors + // 5) Filter out tombstones, blacklisted IDs / authors + let videos = newestByRoot.filter((video) => !video.deleted); videos = videos.filter((video) => { // Event-level blacklisting if (app.blacklistedEventIds.has(video.id)) return false; diff --git a/js/nostr.js b/js/nostr.js index 6df1dffc..4b51be4f 100644 --- a/js/nostr.js +++ b/js/nostr.js @@ -854,21 +854,26 @@ class NostrClient { }; } - const dTag = baseEvent.tags.find((t) => t[0] === "d"); - if (!dTag) { - throw new Error( - 'No "d" tag => cannot revert addressable kind=30078 event.' - ); - } - const existingD = dTag[1]; + const safeTags = Array.isArray(baseEvent.tags) ? baseEvent.tags : []; + const dTag = safeTags.find((t) => t[0] === "d"); + const existingD = dTag ? dTag[1] : null; - const oldContent = JSON.parse(baseEvent.content || "{}"); + let oldContent = {}; + try { + oldContent = JSON.parse(baseEvent.content || "{}"); + } catch (err) { + if (isDevMode) { + console.warn("[nostr] Failed to parse baseEvent.content while reverting:", err); + } + oldContent = {}; + } const oldVersion = oldContent.version ?? 1; - let finalRootId = oldContent.videoRootId || null; - if (!finalRootId) { - finalRootId = `LEGACY:${baseEvent.pubkey}:${existingD}`; - } + const finalRootId = + oldContent.videoRootId || + (existingD + ? `LEGACY:${baseEvent.pubkey}:${existingD}` + : baseEvent.id); const contentObject = { videoRootId: finalRootId, @@ -883,14 +888,16 @@ class NostrClient { mode: oldContent.mode || "live", }; + const tags = [["t", "video"]]; + if (existingD) { + tags.push(["d", existingD]); + } + const event = { kind: 30078, pubkey, created_at: Math.floor(Date.now() / 1000), - tags: [ - ["t", "video"], - ["d", existingD], - ], + tags, content: JSON.stringify(contentObject), };