Stop default view events from adding legacy tags

This commit is contained in:
thePR0M3TH3AN
2025-10-01 15:40:10 -04:00
parent 7a0cf00810
commit ff452ebe77
3 changed files with 60 additions and 8 deletions

View File

@@ -48,7 +48,7 @@ read/write split.
| Video post (`NOTE_TYPES.VIDEO_POST`) | `30078` | `['t','video']`, `['d', <stable video identifier>]` plus optional schema append tags | JSON payload using Content Schema v3 (`version`, `title`, optional `url`, `magnet`, `thumbnail`, `description`, `mode`, `videoRootId`, `deleted`, `isPrivate`, `enableComments`, `ws`, `xs`) |
| NIP-94 mirror (`NOTE_TYPES.VIDEO_MIRROR`) | `1063` | Tags forwarded from `publishVideo` (URL, mime type, thumbnail, alt text, magnet) | Plain text alt description |
| Relay list (`NOTE_TYPES.RELAY_LIST`) | `10002` | Repeating `['r', <relay url>]` tags, optionally with a marker of `'read'` or `'write'` to scope the relay; marker omitted for read/write relays | Empty content |
| View counter (`NOTE_TYPES.VIEW_EVENT`) | `WATCH_HISTORY_KIND` (default `30078`) | `['t','view']`, `['video', <pointer id>]`, pointer tag (`['a', ...]` or `['e', ...]`), optional dedupe `['d', <scope>]`, optional `['session','true']` when a session actor signs, plus any extra debugging tags | Optional plaintext message |
| View counter (`NOTE_TYPES.VIEW_EVENT`) | `WATCH_HISTORY_KIND` (default `30078`) | Canonical tag set: `['t','view']` plus either `['e', <eventId>]` or `['a', <address>]`, with optional `['session','true']` when a session actor signs; schema overrides may append extra tags. `['video', ...]` is supported for legacy overrides only. | Optional plaintext message |
| Watch history index (`NOTE_TYPES.WATCH_HISTORY_INDEX`) | `WATCH_HISTORY_KIND` | `['d', WATCH_HISTORY_LIST_IDENTIFIER]`, `['snapshot', <id>]`, `['chunks', <total>]`, repeated `['a', <address>]` pointers to each chunk event plus schema append tags | JSON payload `{ snapshot, totalChunks }` |
| Watch history chunk (`NOTE_TYPES.WATCH_HISTORY_CHUNK`) | `WATCH_HISTORY_KIND` | `['d', <chunk identifier>]`, `['encrypted','nip04']`, `['snapshot', <id>]`, `['chunk', <index>, <total>]`, pointer tags for each entry, plus schema append tags | NIP-04 encrypted JSON chunk (`{ version, snapshot, chunkIndex, totalChunks, items[] }`) |
| Subscription list (`NOTE_TYPES.SUBSCRIPTION_LIST`) | `30002` | `['d', 'subscriptions']` | NIP-04 encrypted JSON `{ subPubkeys: string[] }` |

View File

@@ -83,8 +83,6 @@ const BASE_SCHEMAS = {
label: "View counter",
kind: WATCH_HISTORY_KIND,
topicTag: { name: "t", value: "view" },
pointerTagName: "video",
identifierTag: { name: "d" },
sessionTag: { name: "session", value: "true" },
appendTags: DEFAULT_APPEND_TAGS,
content: {
@@ -418,6 +416,7 @@ export function buildViewEvent({
created_at,
pointerValue,
pointerTag,
pointerTags = [],
dedupeTag,
includeSessionTag = false,
additionalTags = [],
@@ -429,13 +428,28 @@ export function buildViewEvent({
tags.push([schema.topicTag.name, schema.topicTag.value]);
}
const pointerTagName = schema?.pointerTagName || "video";
if (pointerValue) {
const pointerTagName = schema?.pointerTagName;
if (pointerValue && pointerTagName) {
tags.push([pointerTagName, pointerValue]);
}
const normalizedPointerTags = [];
if (Array.isArray(pointerTag) && pointerTag.length >= 2) {
tags.push(pointerTag.map((value) => (typeof value === "string" ? value : String(value))));
normalizedPointerTags.push(
pointerTag.map((value) => (typeof value === "string" ? value : String(value)))
);
}
if (Array.isArray(pointerTags)) {
pointerTags.forEach((tag) => {
if (Array.isArray(tag) && tag.length >= 2) {
normalizedPointerTags.push(
tag.map((value) => (typeof value === "string" ? value : String(value)))
);
}
});
}
normalizedPointerTags.forEach((tag) => {
tags.push(tag);
});
if (Array.isArray(additionalTags)) {
additionalTags.forEach((tag) => {
if (Array.isArray(tag) && tag.length >= 2) {
@@ -444,8 +458,8 @@ export function buildViewEvent({
});
}
if (dedupeTag) {
const identifierName = schema?.identifierTag?.name || "d";
if (dedupeTag && schema?.identifierTag?.name) {
const identifierName = schema.identifierTag.name;
const hasDedupe = tags.some(
(tag) => tag[0] === identifierName && tag[1] === dedupeTag
);

View File

@@ -9,6 +9,10 @@ const {
VIEW_COUNT_CACHE_TTL_MS,
} = await import("../js/config.js");
const { buildViewEvent, setNostrEventSchemaOverrides } = await import(
"../js/nostrEventSchemas.js"
);
const VIEW_COUNTER_STORAGE_KEY = "bitvid:view-counter:v1";
const CACHE_TTL_TEST_POINTER = { type: "e", value: "view-counter-cache-ttl" };
@@ -42,6 +46,40 @@ if (!globalThis.window.NostrTools) {
globalThis.window.NostrTools = {};
}
setNostrEventSchemaOverrides({});
const canonicalViewEvent = buildViewEvent({
pubkey: "actor-canonical",
created_at: 1000,
pointerValue: CACHE_TTL_TEST_POINTER.value,
pointerTag: [CACHE_TTL_TEST_POINTER.type, CACHE_TTL_TEST_POINTER.value],
dedupeTag: "ignore-dedupe",
});
assert.deepEqual(
canonicalViewEvent.tags,
[["t", "view"], [CACHE_TTL_TEST_POINTER.type, CACHE_TTL_TEST_POINTER.value]],
"view event should only include topic and supplied pointer tags by default"
);
const sessionViewEvent = buildViewEvent({
pubkey: "actor-session",
created_at: 2000,
pointerValue: "kind:1234:actor-session",
pointerTag: ["a", "kind:1234:actor-session"],
includeSessionTag: true,
});
assert.deepEqual(
sessionViewEvent.tags,
[
["t", "view"],
["a", "kind:1234:actor-session"],
["session", "true"],
],
"view event should append the session tag when requested"
);
const { nostrClient } = await import("../js/nostr.js");
function createMockNostrHarness() {