From 462f4bed9e6c617e1a7638eefdc37dfce22ede43 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Wed, 29 Oct 2025 22:20:55 -0400 Subject: [PATCH] Normalize imeta MIME casing --- js/nostr/nip71.js | 3 ++- js/services/videoNotePayload.js | 2 +- tests/nip71-base-event-tags.test.mjs | 18 ++++++++++++++++++ tests/nip71-builder.test.mjs | 2 +- tests/nostr/nip71.test.js | 2 +- 5 files changed, 23 insertions(+), 4 deletions(-) diff --git a/js/nostr/nip71.js b/js/nostr/nip71.js index 376164de..249d5fe4 100644 --- a/js/nostr/nip71.js +++ b/js/nostr/nip71.js @@ -177,7 +177,8 @@ function buildImetaTags(variants) { const dim = stringFromInput(variant.dim); const url = stringFromInput(variant.url); const x = stringFromInput(variant.x); - const mime = stringFromInput(variant.m); + const rawMime = stringFromInput(variant.m); + const mime = rawMime ? rawMime.toLowerCase() : ""; const duration = formatNonNegativeNumber(variant.duration, { allowFloat: true, }); diff --git a/js/services/videoNotePayload.js b/js/services/videoNotePayload.js index 95510373..653ca2b5 100644 --- a/js/services/videoNotePayload.js +++ b/js/services/videoNotePayload.js @@ -85,7 +85,7 @@ function normalizeImetaVariant(variant) { } const normalized = {}; const m = normalizeString(variant.m); - if (m) normalized.m = m; + if (m) normalized.m = m.toLowerCase(); const dim = normalizeString(variant.dim); if (dim) normalized.dim = dim; const url = normalizeString(variant.url); diff --git a/tests/nip71-base-event-tags.test.mjs b/tests/nip71-base-event-tags.test.mjs index fbe1dbaa..b1050579 100644 --- a/tests/nip71-base-event-tags.test.mjs +++ b/tests/nip71-base-event-tags.test.mjs @@ -86,3 +86,21 @@ test("30078 events carry nip71 metadata tags and hydrate fallback metadata", () assert.deepEqual(video.nip71.references, ["https://example.com/info"]); assert.equal(video.nip71Source?.eventId, "event-123"); }); + +test("imeta tags lower-case mime values", () => { + const metadataInput = { + imeta: [ + { m: "VIDEO/MP4", url: "https://cdn.example/video.mp4" }, + { m: "APPLICATION/DASH+XML" }, + ], + }; + + const tags = buildNip71MetadataTags(metadataInput); + const mimeEntries = tags + .filter((tag) => tag[0] === "imeta") + .map((tag) => tag.find((value) => typeof value === "string" && value.startsWith("m "))) + .filter(Boolean) + .map((entry) => entry.slice(2)); + + assert.deepEqual(mimeEntries, ["video/mp4", "application/dash+xml"]); +}); diff --git a/tests/nip71-builder.test.mjs b/tests/nip71-builder.test.mjs index 3da345c8..6fa005be 100644 --- a/tests/nip71-builder.test.mjs +++ b/tests/nip71-builder.test.mjs @@ -145,7 +145,7 @@ test("buildNip71VideoEvent assembles rich metadata", () => { assert.deepEqual(imetaTags[1], [ "imeta", "url https://cdn.example/video-hls.m3u8", - "m application/x-mpegURL", + "m application/x-mpegurl", "duration 45.789", "bitrate 2200000", ]); diff --git a/tests/nostr/nip71.test.js b/tests/nostr/nip71.test.js index 87136e2d..d9055f65 100644 --- a/tests/nostr/nip71.test.js +++ b/tests/nostr/nip71.test.js @@ -92,7 +92,7 @@ test("buildNip71MetadataTags normalizes structured fields", () => { tags.some( (tag) => tag[0] === "p" && - tag[1] === "A".repeat(64) && + tag[1] === "a".repeat(64) && tag[2] === "wss://relay.example", ), );