Merge pull request #1021 from PR0M3TH3AN/codex/update-isvideocommentevent-validation

Allow top-level comment events without parent tags
This commit is contained in:
thePR0M3TH3AN authored and GitHub committed 2025-10-30 21:01:06 -04:00
commit 2e8f826458
2 files changed
+95 -2

No files matched your search

+6 -2
View File
@@ -863,7 +863,7 @@ function isVideoCommentEvent(event, descriptor) {
let hasIdentifierTag = !requiresRootIdentifierMatch;
let hasDefinitionTag = !requiresAddressMatch;
let hasEventTag = !requiresEventMatch;
let hasParentTag = !requiresParentTag;
let hasParentTag = false;
const expectedRootKind = (() => {
if (typeof targetDescriptor.rootKind === "string") {
@@ -985,7 +985,11 @@ function isVideoCommentEvent(event, descriptor) {
}
}
if (!hasIdentifierTag || !hasDefinitionTag || !hasEventTag || !hasParentTag) {
if (!hasIdentifierTag || !hasDefinitionTag || !hasEventTag) {
return false;
}
if (requiresParentTag && !hasParentTag) {
return false;
}
+89
View File
@@ -2,6 +2,8 @@ import test from "node:test";
import assert from "node:assert/strict";
import CommentThreadService from "../js/services/commentThreadService.js";
import { listVideoComments } from "../js/nostr/commentEvents.js";
import { buildCommentEvent } from "../js/nostrEventSchemas.js";
function createBaseVideo() {
return {
@@ -35,6 +37,93 @@ function createComment({
const tick = (ms = 0) => new Promise((resolve) => setTimeout(resolve, ms));
test(
"listVideoComments accepts builder events without parent ids and filters replies",
async () => {
const relayUrl = "wss://relay.example";
const videoEventId = "video123";
const videoDefinitionAddress = "30078:authorpk:video-root";
const topLevelCommentId = "comment-root";
const replyCommentId = "comment-reply";
const topLevelEvent = {
id: topLevelCommentId,
...buildCommentEvent({
pubkey: "commenterpk",
created_at: 1700000000,
videoEventId,
videoEventRelay: relayUrl,
videoDefinitionAddress,
videoDefinitionRelay: relayUrl,
rootIdentifier: "video-root",
rootIdentifierRelay: relayUrl,
rootKind: "30078",
rootAuthorPubkey: "authorpk",
}),
};
const replyEvent = {
id: replyCommentId,
...buildCommentEvent({
pubkey: "replypk",
created_at: 1700000300,
videoEventId,
videoEventRelay: relayUrl,
videoDefinitionAddress,
videoDefinitionRelay: relayUrl,
rootIdentifier: "video-root",
rootIdentifierRelay: relayUrl,
rootKind: "30078",
rootAuthorPubkey: "authorpk",
parentCommentId: topLevelCommentId,
parentCommentRelay: relayUrl,
parentAuthorPubkey: "commenterpk",
}),
};
const listCalls = [];
const client = {
relays: [relayUrl],
pool: {
list: async (relays, filters) => {
listCalls.push({ relays, filters });
return [[topLevelEvent, replyEvent]];
},
},
};
const baseTarget = {
videoEventId,
videoDefinitionAddress,
videoEventRelay: relayUrl,
videoDefinitionRelay: relayUrl,
rootIdentifier: "video-root",
};
const topLevelResults = await listVideoComments(client, baseTarget, {
relays: [relayUrl],
});
assert.equal(
topLevelResults.some((event) => event.id === topLevelCommentId),
true,
"top-level builder comment should be returned when no parent is specified",
);
const replyResults = await listVideoComments(
client,
{ ...baseTarget, parentCommentId: topLevelCommentId },
{ relays: [relayUrl] },
);
assert.deepStrictEqual(
replyResults.map((event) => event.id),
[replyCommentId],
"reply queries should filter to child events when parent id is provided",
);
assert.equal(listCalls.length, 2, "pool.list should be invoked for each query");
},
);
test(
"CommentThreadService hydrates, subscribes, and dedupes incoming comment events",
async (t) => {