mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-30 01:12:39 +00:00
Merge pull request #823 from PR0M3TH3AN/codex/extend-buildreactionevent-and-teach-videomodal-dogrjd
Add author metadata to reaction events
This commit is contained in:
4 files changed
+237
-5
No files matched your search
@@ -50,15 +50,38 @@ export async function publishVideoReaction(
|
||||
)
|
||||
: [];
|
||||
|
||||
const optionRelay =
|
||||
typeof options.pointerRelay === "string" && options.pointerRelay.trim()
|
||||
? options.pointerRelay.trim()
|
||||
: "";
|
||||
|
||||
const pointerRelay =
|
||||
typeof pointer.relay === "string" && pointer.relay.trim()
|
||||
? pointer.relay.trim()
|
||||
: optionRelay;
|
||||
|
||||
const pointerTag =
|
||||
pointer.type === "a"
|
||||
? pointer.relay
|
||||
? ["a", pointer.value, pointer.relay]
|
||||
? pointerRelay
|
||||
? ["a", pointer.value, pointerRelay]
|
||||
: ["a", pointer.value]
|
||||
: pointer.relay
|
||||
? ["e", pointer.value, pointer.relay]
|
||||
: pointerRelay
|
||||
? ["e", pointer.value, pointerRelay]
|
||||
: ["e", pointer.value];
|
||||
|
||||
const normalizedPointer = {
|
||||
type: pointer.type,
|
||||
value: pointer.value,
|
||||
relay: pointerRelay || null,
|
||||
};
|
||||
|
||||
const explicitTargetAuthor =
|
||||
typeof options.targetAuthorPubkey === "string" && options.targetAuthorPubkey.trim()
|
||||
? options.targetAuthorPubkey.trim()
|
||||
: typeof options.authorPubkey === "string" && options.authorPubkey.trim()
|
||||
? options.authorPubkey.trim()
|
||||
: "";
|
||||
|
||||
let content = "+";
|
||||
if (typeof options.content === "string") {
|
||||
content = options.content;
|
||||
@@ -82,6 +105,8 @@ export async function publishVideoReaction(
|
||||
created_at: createdAt,
|
||||
pointerValue: pointer.value,
|
||||
pointerTag,
|
||||
targetPointer: normalizedPointer,
|
||||
targetAuthorPubkey: explicitTargetAuthor,
|
||||
additionalTags,
|
||||
content,
|
||||
});
|
||||
|
||||
@@ -689,6 +689,8 @@ export function buildReactionEvent({
|
||||
pointerValue,
|
||||
pointerTag,
|
||||
pointerTags = [],
|
||||
targetPointer = null,
|
||||
targetAuthorPubkey = "",
|
||||
additionalTags = [],
|
||||
content = "",
|
||||
}) {
|
||||
@@ -704,6 +706,93 @@ export function buildReactionEvent({
|
||||
tags.push(tag);
|
||||
});
|
||||
|
||||
const resolvePointerDetails = (pointerCandidate) => {
|
||||
if (!pointerCandidate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Array.isArray(pointerCandidate) && pointerCandidate.length >= 2) {
|
||||
const [type, value, relay] = pointerCandidate;
|
||||
const normalizedType = type === "a" ? "a" : type === "e" ? "e" : "";
|
||||
const normalizedValue = typeof value === "string" ? value.trim() : "";
|
||||
if (!normalizedType || !normalizedValue) {
|
||||
return null;
|
||||
}
|
||||
const normalizedRelay =
|
||||
typeof relay === "string" && relay.trim() ? relay.trim() : "";
|
||||
return { type: normalizedType, value: normalizedValue, relay: normalizedRelay };
|
||||
}
|
||||
|
||||
if (pointerCandidate && typeof pointerCandidate === "object") {
|
||||
const { type, value, relay } = pointerCandidate;
|
||||
const normalizedType = type === "a" ? "a" : type === "e" ? "e" : "";
|
||||
const normalizedValue = typeof value === "string" ? value.trim() : "";
|
||||
if (!normalizedType || !normalizedValue) {
|
||||
return null;
|
||||
}
|
||||
const normalizedRelay =
|
||||
typeof relay === "string" && relay.trim() ? relay.trim() : "";
|
||||
return { type: normalizedType, value: normalizedValue, relay: normalizedRelay };
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const pointerDetails = (() => {
|
||||
const explicitPointer = resolvePointerDetails(targetPointer);
|
||||
if (explicitPointer) {
|
||||
return explicitPointer;
|
||||
}
|
||||
|
||||
const pointerTagEntry = normalizedPointerTags.find(
|
||||
(tag) => Array.isArray(tag) && tag.length >= 2 && (tag[0] === "a" || tag[0] === "e")
|
||||
);
|
||||
if (!pointerTagEntry) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return resolvePointerDetails(pointerTagEntry);
|
||||
})();
|
||||
|
||||
const resolvedRelay = pointerDetails?.relay || "";
|
||||
|
||||
const normalizedAuthorPubkey = (() => {
|
||||
if (typeof targetAuthorPubkey === "string" && targetAuthorPubkey.trim()) {
|
||||
return targetAuthorPubkey.trim();
|
||||
}
|
||||
|
||||
if (pointerDetails?.type === "a" && pointerDetails.value) {
|
||||
const segments = pointerDetails.value.split(":");
|
||||
if (segments.length >= 2) {
|
||||
const candidate = segments[1]?.trim();
|
||||
if (candidate) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
})();
|
||||
|
||||
if (normalizedAuthorPubkey) {
|
||||
const existingAuthorTag = tags.find(
|
||||
(tag) => Array.isArray(tag) && tag[0] === "p" && tag[1] === normalizedAuthorPubkey
|
||||
);
|
||||
if (!existingAuthorTag) {
|
||||
if (resolvedRelay) {
|
||||
tags.push(["p", normalizedAuthorPubkey, resolvedRelay]);
|
||||
} else {
|
||||
tags.push(["p", normalizedAuthorPubkey]);
|
||||
}
|
||||
} else if (resolvedRelay) {
|
||||
if (existingAuthorTag.length < 3) {
|
||||
existingAuthorTag.push(resolvedRelay);
|
||||
} else if (existingAuthorTag[2] !== resolvedRelay) {
|
||||
existingAuthorTag[2] = resolvedRelay;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(additionalTags)) {
|
||||
additionalTags.forEach((tag) => {
|
||||
if (Array.isArray(tag) && tag.length >= 2) {
|
||||
|
||||
+80
-1
@@ -4,7 +4,86 @@ import { devLogger, userLogger } from "./utils/logger.js";
|
||||
export const reactionCounter = {
|
||||
async publish(pointer, options = {}) {
|
||||
try {
|
||||
const result = await publishVideoReaction(pointer, options);
|
||||
const publishOptions = { ...options };
|
||||
|
||||
const pointerRelayFromPointer = (() => {
|
||||
if (Array.isArray(pointer) && pointer.length >= 3) {
|
||||
const relay = pointer[2];
|
||||
if (typeof relay === "string" && relay.trim()) {
|
||||
return relay.trim();
|
||||
}
|
||||
}
|
||||
if (pointer && typeof pointer === "object") {
|
||||
const relay = pointer.relay;
|
||||
if (typeof relay === "string" && relay.trim()) {
|
||||
return relay.trim();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
})();
|
||||
|
||||
const pointerRelay =
|
||||
typeof publishOptions.pointerRelay === "string" && publishOptions.pointerRelay.trim()
|
||||
? publishOptions.pointerRelay.trim()
|
||||
: pointerRelayFromPointer;
|
||||
|
||||
if (pointerRelay && !publishOptions.pointerRelay) {
|
||||
publishOptions.pointerRelay = pointerRelay;
|
||||
}
|
||||
|
||||
const enrichedPointer = (() => {
|
||||
if (!pointerRelay) {
|
||||
return pointer;
|
||||
}
|
||||
|
||||
if (Array.isArray(pointer) && pointer.length >= 2) {
|
||||
const [type, value] = pointer;
|
||||
return [type, value, pointerRelay];
|
||||
}
|
||||
|
||||
if (pointer && typeof pointer === "object") {
|
||||
return { ...pointer, relay: pointerRelay };
|
||||
}
|
||||
|
||||
return pointer;
|
||||
})();
|
||||
|
||||
const explicitAuthor =
|
||||
typeof publishOptions.targetAuthorPubkey === "string" &&
|
||||
publishOptions.targetAuthorPubkey.trim()
|
||||
? publishOptions.targetAuthorPubkey.trim()
|
||||
: "";
|
||||
|
||||
if (!explicitAuthor) {
|
||||
const fallbackAuthor = (() => {
|
||||
if (
|
||||
typeof publishOptions.authorPubkey === "string" &&
|
||||
publishOptions.authorPubkey.trim()
|
||||
) {
|
||||
return publishOptions.authorPubkey.trim();
|
||||
}
|
||||
if (
|
||||
typeof publishOptions.currentVideoPubkey === "string" &&
|
||||
publishOptions.currentVideoPubkey.trim()
|
||||
) {
|
||||
return publishOptions.currentVideoPubkey.trim();
|
||||
}
|
||||
if (
|
||||
publishOptions.video &&
|
||||
typeof publishOptions.video.pubkey === "string" &&
|
||||
publishOptions.video.pubkey.trim()
|
||||
) {
|
||||
return publishOptions.video.pubkey.trim();
|
||||
}
|
||||
return "";
|
||||
})();
|
||||
|
||||
if (fallbackAuthor) {
|
||||
publishOptions.targetAuthorPubkey = fallbackAuthor;
|
||||
}
|
||||
}
|
||||
|
||||
const result = await publishVideoReaction(enrichedPointer, publishOptions);
|
||||
if (!result || !result.ok) {
|
||||
userLogger.warn(
|
||||
"[reactionCounter] Reaction publish rejected by relays:",
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import { buildReactionEvent } from "../js/nostrEventSchemas.js";
|
||||
|
||||
test("buildReactionEvent includes pointer and author tags when pubkey provided", () => {
|
||||
const event = buildReactionEvent({
|
||||
pubkey: "viewer",
|
||||
created_at: 1700000000,
|
||||
pointerValue: "event-id",
|
||||
pointerTag: ["e", "event-id", "wss://relay.example"],
|
||||
targetPointer: { type: "e", value: "event-id", relay: "wss://relay.example" },
|
||||
targetAuthorPubkey: "author-pubkey",
|
||||
content: "+",
|
||||
});
|
||||
|
||||
const pointerTags = event.tags.filter((tag) => Array.isArray(tag) && tag[0] === "e");
|
||||
assert.deepEqual(pointerTags, [["e", "event-id", "wss://relay.example"]]);
|
||||
|
||||
const authorTags = event.tags.filter((tag) => Array.isArray(tag) && tag[0] === "p");
|
||||
assert.deepEqual(authorTags, [["p", "author-pubkey", "wss://relay.example"]]);
|
||||
});
|
||||
|
||||
test("buildReactionEvent derives author pubkey from address pointer", () => {
|
||||
const event = buildReactionEvent({
|
||||
pubkey: "viewer",
|
||||
created_at: 1700000001,
|
||||
pointerValue: "30078:deadbeefcafebabe:clip-1",
|
||||
pointerTag: ["a", "30078:deadbeefcafebabe:clip-1"],
|
||||
targetPointer: { type: "a", value: "30078:deadbeefcafebabe:clip-1" },
|
||||
content: "+",
|
||||
});
|
||||
|
||||
const addressTags = event.tags.filter((tag) => Array.isArray(tag) && tag[0] === "a");
|
||||
assert.deepEqual(addressTags, [["a", "30078:deadbeefcafebabe:clip-1"]]);
|
||||
|
||||
const authorTags = event.tags.filter((tag) => Array.isArray(tag) && tag[0] === "p");
|
||||
assert.deepEqual(authorTags, [["p", "deadbeefcafebabe"]]);
|
||||
});
|
||||
Reference in new issue
Block a user