From c882139e901aee871db8b50bfe4e5d269187e7e5 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Tue, 4 Nov 2025 16:52:12 -0500 Subject: [PATCH] Fix comment event matching for uppercase addresses --- js/nostr/commentEvents.js | 43 ++++++++++++++++++++++------- tests/nostr/comment-events.test.mjs | 36 ++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 10 deletions(-) diff --git a/js/nostr/commentEvents.js b/js/nostr/commentEvents.js index 63e82c44..f40c9be4 100644 --- a/js/nostr/commentEvents.js +++ b/js/nostr/commentEvents.js @@ -916,13 +916,27 @@ function isVideoCommentEvent(event, descriptor) { descriptor && typeof descriptor === "object" ? descriptor : {}; const tags = Array.isArray(event.tags) ? event.tags : []; - const requiresRootIdentifierMatch = Boolean(targetDescriptor.rootIdentifier); + const normalizedRootIdentifier = normalizeTagValue( + targetDescriptor.rootIdentifier, + ); + const normalizedVideoDefinitionAddress = normalizeTagValue( + targetDescriptor.videoDefinitionAddress, + ); + const normalizedVideoEventId = normalizeTagValue( + targetDescriptor.videoEventId, + ); + const normalizedParentCommentId = normalizeTagValue( + targetDescriptor.parentCommentId, + ); + + const requiresRootIdentifierMatch = Boolean(normalizedRootIdentifier); const requiresAddressMatch = - !requiresRootIdentifierMatch && Boolean(targetDescriptor.videoDefinitionAddress); + !requiresRootIdentifierMatch && Boolean(normalizedVideoDefinitionAddress); const requiresEventMatch = - !requiresRootIdentifierMatch && !requiresAddressMatch && - Boolean(targetDescriptor.videoEventId); - const requiresParentTag = Boolean(targetDescriptor.parentCommentId); + !requiresRootIdentifierMatch && + !requiresAddressMatch && + Boolean(normalizedVideoEventId); + const requiresParentTag = Boolean(normalizedParentCommentId); let hasIdentifierTag = !requiresRootIdentifierMatch; let hasDefinitionTag = !requiresAddressMatch; @@ -972,20 +986,29 @@ function isVideoCommentEvent(event, descriptor) { } if (lowerName === "i") { - if (normalizedValue === targetDescriptor.rootIdentifier) { + if ( + normalizedRootIdentifier && + normalizedValue === normalizedRootIdentifier + ) { hasIdentifierTag = true; } } else if (lowerName === "a") { - if (normalizedValue === targetDescriptor.videoDefinitionAddress) { + if ( + normalizedVideoDefinitionAddress && + normalizedValue === normalizedVideoDefinitionAddress + ) { hasDefinitionTag = true; } } else if (lowerName === "e") { - if (normalizedValue === targetDescriptor.videoEventId) { + if ( + normalizedVideoEventId && + normalizedValue === normalizedVideoEventId + ) { hasEventTag = true; } if ( - targetDescriptor.parentCommentId && - normalizedValue === targetDescriptor.parentCommentId + normalizedParentCommentId && + normalizedValue === normalizedParentCommentId ) { hasParentTag = true; } diff --git a/tests/nostr/comment-events.test.mjs b/tests/nostr/comment-events.test.mjs index cb07115e..7f8098af 100644 --- a/tests/nostr/comment-events.test.mjs +++ b/tests/nostr/comment-events.test.mjs @@ -6,8 +6,11 @@ import { publishComment, listVideoComments, subscribeVideoComments, + __testExports, } from "../../js/nostr/commentEvents.js"; +const { normalizeCommentTarget, isVideoCommentEvent } = __testExports; + function createMockClient({ actorPubkey = "actor-pubkey", relays = ["wss://primary"], @@ -281,6 +284,39 @@ test("listVideoComments matches comments even when tag casing and whitespace dif "isVideoCommentEvent should treat tag casing and whitespace as insignificant", ); }); + +test("listVideoComments matches uppercase definition addresses without lowering", async () => { + const uppercasePointer = "30078:AUTHOR:Clip42"; + const matchingEvent = { + id: "uppercase-comment", + kind: COMMENT_EVENT_KIND, + created_at: 1700000400, + tags: [ + ["A", uppercasePointer], + ["e", "video-1"], + ], + }; + + const { client, pool } = createMockClient(); + pool.list = async () => [[matchingEvent]]; + + const descriptorInput = { + videoEventId: "video-1", + videoDefinitionAddress: uppercasePointer, + }; + + const events = await listVideoComments(client, descriptorInput); + assert.equal(events.length, 1, "uppercase pointer should still match"); + assert.equal(events[0].id, "uppercase-comment", "matched event should be returned"); + + const normalizedDescriptor = normalizeCommentTarget(descriptorInput); + assert.ok(normalizedDescriptor, "normalizeCommentTarget should produce a descriptor"); + assert.equal( + isVideoCommentEvent(matchingEvent, normalizedDescriptor), + true, + "isVideoCommentEvent should respect descriptor casing for definition pointers", + ); +}); test("listVideoComments matches comments even when tag casing and whitespace differ", async () => { const mismatchedEvent = { id: "case-comment",