mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Merge pull request #1019 from PR0M3TH3AN/codex/update-schemas-and-refactor-list-functions
Update mute list schema and migrate encrypted list payloads
This commit is contained in:
6 files changed
+272
-80
No files matched your search
+16
-10
@@ -302,22 +302,24 @@ const BASE_SCHEMAS = {
|
||||
},
|
||||
appendTags: DEFAULT_APPEND_TAGS,
|
||||
content: {
|
||||
format: "nip04-json",
|
||||
description: "Encrypted JSON: { subPubkeys: string[] }.",
|
||||
format: "encrypted-tag-list",
|
||||
description:
|
||||
"NIP-04/NIP-44 encrypted JSON array of NIP-51 tag tuples (e.g., [['p', <hex>], …]).",
|
||||
},
|
||||
},
|
||||
[NOTE_TYPES.USER_BLOCK_LIST]: {
|
||||
type: NOTE_TYPES.USER_BLOCK_LIST,
|
||||
label: "User block list",
|
||||
kind: 30002,
|
||||
kind: 10000,
|
||||
identifierTag: {
|
||||
name: "d",
|
||||
value: BLOCK_LIST_IDENTIFIER,
|
||||
},
|
||||
appendTags: DEFAULT_APPEND_TAGS,
|
||||
content: {
|
||||
format: "nip04-json",
|
||||
description: "Encrypted JSON: { blockedPubkeys: string[] }.",
|
||||
format: "encrypted-tag-list",
|
||||
description:
|
||||
"NIP-04/NIP-44 encrypted JSON array of mute tags per NIP-51 (e.g., [['p', <hex>], …]).",
|
||||
},
|
||||
},
|
||||
[NOTE_TYPES.HASHTAG_PREFERENCES]: {
|
||||
@@ -1390,8 +1392,10 @@ export function buildSubscriptionListEvent({
|
||||
if (identifierName && identifierValue) {
|
||||
tags.push([identifierName, identifierValue]);
|
||||
}
|
||||
if (typeof encryption === "string" && encryption) {
|
||||
tags.push(["encrypted", encryption]);
|
||||
const normalizedEncryption =
|
||||
typeof encryption === "string" ? encryption.trim() : "";
|
||||
if (normalizedEncryption) {
|
||||
tags.push(["encrypted", normalizedEncryption]);
|
||||
}
|
||||
appendSchemaTags(tags, schema);
|
||||
return {
|
||||
@@ -1416,12 +1420,14 @@ export function buildBlockListEvent({
|
||||
if (identifierName && identifierValue) {
|
||||
tags.push([identifierName, identifierValue]);
|
||||
}
|
||||
if (typeof encryption === "string" && encryption) {
|
||||
tags.push(["encrypted", encryption]);
|
||||
const normalizedEncryption =
|
||||
typeof encryption === "string" ? encryption.trim() : "";
|
||||
if (normalizedEncryption) {
|
||||
tags.push(["encrypted", normalizedEncryption]);
|
||||
}
|
||||
appendSchemaTags(tags, schema);
|
||||
return {
|
||||
kind: schema?.kind ?? 30002,
|
||||
kind: schema?.kind ?? 10000,
|
||||
pubkey,
|
||||
created_at,
|
||||
tags,
|
||||
|
||||
+82
-11
@@ -126,6 +126,82 @@ function determineDecryptionOrder(event, availableSchemes) {
|
||||
return prioritized.length ? prioritized : available;
|
||||
}
|
||||
|
||||
function serializeSubscriptionTagMatrix(values) {
|
||||
const tags = [];
|
||||
const seen = new Set();
|
||||
if (!values) {
|
||||
return JSON.stringify(tags);
|
||||
}
|
||||
const iterable = Array.isArray(values)
|
||||
? values
|
||||
: values instanceof Set
|
||||
? Array.from(values)
|
||||
: [];
|
||||
for (const candidate of iterable) {
|
||||
const normalized = normalizeHexPubkey(candidate);
|
||||
if (!normalized || seen.has(normalized)) {
|
||||
continue;
|
||||
}
|
||||
seen.add(normalized);
|
||||
tags.push(["p", normalized]);
|
||||
}
|
||||
return JSON.stringify(tags);
|
||||
}
|
||||
|
||||
function parseSubscriptionPlaintext(plaintext) {
|
||||
if (typeof plaintext !== "string" || !plaintext) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let parsed;
|
||||
try {
|
||||
parsed = JSON.parse(plaintext);
|
||||
} catch (error) {
|
||||
devLogger.warn(
|
||||
"[SubscriptionsManager] Failed to parse subscription ciphertext as JSON; treating as empty.",
|
||||
error,
|
||||
);
|
||||
return [];
|
||||
}
|
||||
|
||||
if (Array.isArray(parsed)) {
|
||||
const collected = [];
|
||||
const seen = new Set();
|
||||
for (const entry of parsed) {
|
||||
if (!Array.isArray(entry) || entry.length < 2) {
|
||||
continue;
|
||||
}
|
||||
const marker = typeof entry[0] === "string" ? entry[0].trim().toLowerCase() : "";
|
||||
if (marker !== "p") {
|
||||
continue;
|
||||
}
|
||||
const normalized = normalizeHexPubkey(entry[1]);
|
||||
if (!normalized || seen.has(normalized)) {
|
||||
continue;
|
||||
}
|
||||
seen.add(normalized);
|
||||
collected.push(normalized);
|
||||
}
|
||||
return collected;
|
||||
}
|
||||
|
||||
if (parsed && typeof parsed === "object") {
|
||||
const tagArray = Array.isArray(parsed.tags) ? parsed.tags : [];
|
||||
if (tagArray.length) {
|
||||
try {
|
||||
return parseSubscriptionPlaintext(JSON.stringify(tagArray));
|
||||
} catch {
|
||||
// fall through to legacy handling
|
||||
}
|
||||
}
|
||||
|
||||
const legacy = Array.isArray(parsed.subPubkeys) ? parsed.subPubkeys : [];
|
||||
return legacy.map((value) => normalizeHexPubkey(value)).filter(Boolean);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
const getApp = () => getApplication();
|
||||
|
||||
const listVideoViewEventsApi = (pointer, options) =>
|
||||
@@ -135,7 +211,7 @@ const subscribeVideoViewEventsApi = (pointer, options) =>
|
||||
|
||||
/**
|
||||
* Manages the user's subscription list (kind=30002) *privately*,
|
||||
* using NIP-04 encryption for the content field.
|
||||
* using encrypted NIP-51 tag arrays (NIP-04/NIP-44) for the content field.
|
||||
* Also handles fetching and rendering subscribed channels' videos
|
||||
* in the same card style as your home page.
|
||||
*/
|
||||
@@ -295,13 +371,7 @@ class SubscriptionsManager {
|
||||
|
||||
const decryptedStr = decryptResult.plaintext;
|
||||
|
||||
const parsed = JSON.parse(decryptedStr);
|
||||
const subArray = Array.isArray(parsed.subPubkeys)
|
||||
? parsed.subPubkeys
|
||||
: [];
|
||||
const normalized = subArray
|
||||
.map((value) => normalizeHexPubkey(value))
|
||||
.filter((value) => Boolean(value));
|
||||
const normalized = parseSubscriptionPlaintext(decryptedStr);
|
||||
this.subscribedPubkeys = new Set(normalized);
|
||||
|
||||
this.loaded = true;
|
||||
@@ -534,8 +604,7 @@ class SubscriptionsManager {
|
||||
throw error;
|
||||
}
|
||||
|
||||
const plainObj = { subPubkeys: Array.from(this.subscribedPubkeys) };
|
||||
const plainStr = JSON.stringify(plainObj);
|
||||
const plainStr = serializeSubscriptionTagMatrix(this.subscribedPubkeys);
|
||||
|
||||
const encryptors = [];
|
||||
const registerEncryptor = (scheme, handler) => {
|
||||
@@ -604,7 +673,9 @@ class SubscriptionsManager {
|
||||
? "nip44_v2"
|
||||
: encryptionScheme === "nip44"
|
||||
? "nip44"
|
||||
: undefined;
|
||||
: encryptionScheme === "nip04"
|
||||
? "nip04"
|
||||
: undefined;
|
||||
|
||||
const evt = buildSubscriptionListEvent({
|
||||
pubkey: userPubkey,
|
||||
|
||||
+120
-22
@@ -159,6 +159,111 @@ function determineDecryptionOrder(event, availableSchemes) {
|
||||
return prioritized.length ? prioritized : available;
|
||||
}
|
||||
|
||||
function serializeBlockListTagMatrix(values, ownerPubkey) {
|
||||
const tags = [];
|
||||
const seen = new Set();
|
||||
const owner = normalizeHex(ownerPubkey);
|
||||
const iterable = Array.isArray(values)
|
||||
? values
|
||||
: values instanceof Set
|
||||
? Array.from(values)
|
||||
: values && typeof values[Symbol.iterator] === "function"
|
||||
? Array.from(values)
|
||||
: [];
|
||||
|
||||
for (const candidate of iterable) {
|
||||
const normalized = normalizeHex(candidate);
|
||||
if (!normalized || normalized === owner || seen.has(normalized)) {
|
||||
continue;
|
||||
}
|
||||
seen.add(normalized);
|
||||
tags.push(["p", normalized]);
|
||||
}
|
||||
|
||||
return JSON.stringify(tags);
|
||||
}
|
||||
|
||||
function parseBlockListPlaintext(plaintext, ownerPubkey) {
|
||||
if (typeof plaintext !== "string" || !plaintext) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let parsed;
|
||||
try {
|
||||
parsed = JSON.parse(plaintext);
|
||||
} catch (error) {
|
||||
userLogger.warn(
|
||||
"[UserBlockList] Failed to parse block list ciphertext as JSON; treating as empty.",
|
||||
error,
|
||||
);
|
||||
return [];
|
||||
}
|
||||
|
||||
const owner = normalizeHex(ownerPubkey);
|
||||
|
||||
const extractFromTags = (tags) => {
|
||||
const collected = [];
|
||||
const seen = new Set();
|
||||
for (const entry of tags) {
|
||||
if (!Array.isArray(entry) || entry.length < 2) {
|
||||
continue;
|
||||
}
|
||||
const label = typeof entry[0] === "string" ? entry[0].trim().toLowerCase() : "";
|
||||
if (label !== "p") {
|
||||
continue;
|
||||
}
|
||||
const normalized = normalizeHex(entry[1]);
|
||||
if (!normalized || normalized === owner || seen.has(normalized)) {
|
||||
continue;
|
||||
}
|
||||
seen.add(normalized);
|
||||
collected.push(normalized);
|
||||
}
|
||||
return collected;
|
||||
};
|
||||
|
||||
if (Array.isArray(parsed)) {
|
||||
return extractFromTags(parsed);
|
||||
}
|
||||
|
||||
if (parsed && typeof parsed === "object") {
|
||||
if (Array.isArray(parsed.tags) && parsed.tags.length) {
|
||||
return extractFromTags(parsed.tags);
|
||||
}
|
||||
|
||||
const legacy = Array.isArray(parsed.blockedPubkeys) ? parsed.blockedPubkeys : [];
|
||||
return legacy
|
||||
.map((value) => normalizeHex(value))
|
||||
.filter((value) => value && value !== owner);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
function isUserBlockListEvent(event) {
|
||||
if (!event || typeof event.kind !== "number") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.kind === 10000) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.kind === 30002) {
|
||||
const tags = Array.isArray(event.tags) ? event.tags : [];
|
||||
return tags.some(
|
||||
(tag) =>
|
||||
Array.isArray(tag) &&
|
||||
typeof tag[0] === "string" &&
|
||||
tag[0].trim().toLowerCase() === "d" &&
|
||||
typeof tag[1] === "string" &&
|
||||
tag[1].trim() === BLOCK_LIST_IDENTIFIER,
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function decodeNpubToHex(npub) {
|
||||
if (typeof npub !== "string") {
|
||||
return null;
|
||||
@@ -540,10 +645,9 @@ class UserBlockListManager {
|
||||
|
||||
try {
|
||||
const filter = {
|
||||
kinds: [30002],
|
||||
kinds: [10000, 30002],
|
||||
authors: [normalized],
|
||||
"#d": [BLOCK_LIST_IDENTIFIER],
|
||||
limit: 1,
|
||||
limit: 2,
|
||||
};
|
||||
|
||||
if (since !== null) {
|
||||
@@ -603,7 +707,10 @@ class UserBlockListManager {
|
||||
settled = true;
|
||||
clearTimeout(timer);
|
||||
const events = Array.isArray(result)
|
||||
? result.filter((event) => event && event.pubkey === normalized)
|
||||
? result.filter(
|
||||
(event) =>
|
||||
event && event.pubkey === normalized && isUserBlockListEvent(event),
|
||||
)
|
||||
: [];
|
||||
if (requireEvent && !events.length) {
|
||||
const emptyError = new Error(
|
||||
@@ -656,7 +763,10 @@ class UserBlockListManager {
|
||||
}
|
||||
|
||||
const sorted = events
|
||||
.filter((event) => event && event.pubkey === normalized)
|
||||
.filter(
|
||||
(event) =>
|
||||
event && event.pubkey === normalized && isUserBlockListEvent(event),
|
||||
)
|
||||
.sort((a, b) => (b?.created_at || 0) - (a?.created_at || 0));
|
||||
|
||||
if (!sorted.length) {
|
||||
@@ -810,21 +920,7 @@ class UserBlockListManager {
|
||||
}
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(decrypted);
|
||||
const list = Array.isArray(parsed?.blockedPubkeys)
|
||||
? parsed.blockedPubkeys
|
||||
: [];
|
||||
const sanitized = list
|
||||
.map((entry) => normalizeHex(entry))
|
||||
.filter((candidate) => {
|
||||
if (!candidate) {
|
||||
return false;
|
||||
}
|
||||
if (candidate === normalized) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
const sanitized = parseBlockListPlaintext(decrypted, normalized);
|
||||
applyBlockedPubkeys(sanitized, {
|
||||
source,
|
||||
reason: "applied",
|
||||
@@ -1336,7 +1432,7 @@ class UserBlockListManager {
|
||||
(candidate) => candidate && candidate !== normalized
|
||||
),
|
||||
};
|
||||
const plaintext = JSON.stringify(payload);
|
||||
const plaintext = serializeBlockListTagMatrix(payload.blockedPubkeys, normalized);
|
||||
|
||||
const encryptors = [];
|
||||
const registerEncryptor = (scheme, handler) => {
|
||||
@@ -1397,7 +1493,9 @@ class UserBlockListManager {
|
||||
? "nip44_v2"
|
||||
: encryptionScheme === "nip44"
|
||||
? "nip44"
|
||||
: undefined;
|
||||
: encryptionScheme === "nip04"
|
||||
? "nip04"
|
||||
: undefined;
|
||||
|
||||
const event = buildBlockListEvent({
|
||||
pubkey: normalized,
|
||||
|
||||
@@ -103,18 +103,24 @@ test("trusted mute lists from seeds hide authors for anonymous viewers", async (
|
||||
|
||||
await userBlocks.addBlock(mutedHex, seedHex);
|
||||
|
||||
const muteEvent = signedEvents.find((event) => event.kind === 10000);
|
||||
const muteEvent = signedEvents.find(
|
||||
(event) =>
|
||||
event.kind === 10000 &&
|
||||
Array.isArray(event.tags) &&
|
||||
event.tags.some((tag) => Array.isArray(tag) && tag[0] === "p"),
|
||||
);
|
||||
assert(muteEvent, "block list updates should publish a kind 10000 mute list event");
|
||||
assert(
|
||||
Array.isArray(muteEvent.tags) &&
|
||||
muteEvent.tags.some((tag) => Array.isArray(tag) && tag[0] === "p" && tag[1] === mutedHex),
|
||||
muteEvent.tags.some((tag) => Array.isArray(tag) && tag[0] === "p" && tag[1] === mutedHex),
|
||||
"mute list event should include p-tags for blocked pubkeys",
|
||||
);
|
||||
assert.equal(
|
||||
publishedEvents.filter((event) => event?.kind === 10000).length,
|
||||
1,
|
||||
"mute list event should be published to relays",
|
||||
const publishedMuteEvents = publishedEvents.filter(
|
||||
(event) =>
|
||||
event?.kind === 10000 &&
|
||||
Array.isArray(event.tags) &&
|
||||
event.tags.some((tag) => Array.isArray(tag) && tag[0] === "p"),
|
||||
);
|
||||
assert(publishedMuteEvents.length >= 1, "mute list event should be published to relays");
|
||||
|
||||
const { service } = createModerationServiceHarness(t, { userBlocks });
|
||||
service.refreshViewerFromClient = async () => {};
|
||||
|
||||
@@ -73,7 +73,7 @@ test("loadSubscriptions aggregates relay results when one rejects", async () =>
|
||||
async decrypt(_pubkey, ciphertext) {
|
||||
decryptCalls.push(ciphertext);
|
||||
if (ciphertext === "cipher-new") {
|
||||
return JSON.stringify({ subPubkeys: ["pub-new"] });
|
||||
return JSON.stringify([["p", "pub-new"]]);
|
||||
}
|
||||
return JSON.stringify({ subPubkeys: ["pub-old"] });
|
||||
},
|
||||
@@ -179,7 +179,7 @@ test("loadSubscriptions falls back to nip44 when hinted", async () => {
|
||||
nip44: {
|
||||
async decrypt(_pubkey, ciphertext) {
|
||||
decryptCalls.nip44 += 1;
|
||||
return JSON.stringify({ subPubkeys: ["pub-nip44"], hint: ciphertext });
|
||||
return JSON.stringify([["p", "pub-nip44", ciphertext]]);
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -264,7 +264,7 @@ test("loadSubscriptions handles nip44.v2 decryptors", async () => {
|
||||
v2: {
|
||||
async decrypt(_pubkey, ciphertext) {
|
||||
decryptCalls.nip44_v2 += 1;
|
||||
return JSON.stringify({ subPubkeys: ["pub-nip44-v2"], hint: ciphertext });
|
||||
return JSON.stringify([["p", "pub-nip44-v2"], ["t", ciphertext]]);
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -354,14 +354,14 @@ test("loadSubscriptions prefers nip44 decryptors when both are available", async
|
||||
nip04: {
|
||||
async decrypt() {
|
||||
decryptCalls.nip04 += 1;
|
||||
return JSON.stringify({ subPubkeys: ["pub-nip04"] });
|
||||
return JSON.stringify([["p", "pub-nip04"]]);
|
||||
},
|
||||
},
|
||||
nip44: {
|
||||
v2: {
|
||||
async decrypt(_pubkey, ciphertext) {
|
||||
decryptCalls.nip44 += 1;
|
||||
return JSON.stringify({ subPubkeys: ["pub-nip44-pref"], hint: ciphertext });
|
||||
return JSON.stringify([["p", "pub-nip44-pref", ciphertext]]);
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -443,7 +443,7 @@ test(
|
||||
pubkey: "user-pubkey-123",
|
||||
async nip04Decrypt(pubkey, ciphertext) {
|
||||
decryptCalls.push({ pubkey, ciphertext });
|
||||
return JSON.stringify({ subPubkeys: ["pub-direct"] });
|
||||
return JSON.stringify([["p", "pub-direct"]]);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -712,7 +712,7 @@ test(
|
||||
encryptCalls[0],
|
||||
{
|
||||
pubkey: "user-pubkey-123",
|
||||
plaintext: JSON.stringify({ subPubkeys: ["pub-direct"] }),
|
||||
plaintext: JSON.stringify([["p", "pub-direct"]]),
|
||||
},
|
||||
"nip04Encrypt should receive the serialized subscription list",
|
||||
);
|
||||
@@ -782,7 +782,7 @@ test("publishSubscriptionList prefers nip44 encryption when available", async ()
|
||||
assert.equal(pubkey, "user-pubkey-123");
|
||||
assert.equal(
|
||||
plaintext,
|
||||
JSON.stringify({ subPubkeys: ["pub-one", "pub-two"] }),
|
||||
JSON.stringify([["p", "pub-one"], ["p", "pub-two"]]),
|
||||
);
|
||||
return "cipher-nip44";
|
||||
},
|
||||
@@ -871,8 +871,8 @@ test("publishSubscriptionList falls back to nip04 when nip44 fails", async () =>
|
||||
encryptCalls.nip04 += 1;
|
||||
assert.equal(pubkey, "user-pubkey-123");
|
||||
assert.equal(
|
||||
plaintext,
|
||||
JSON.stringify({ subPubkeys: ["pub-three"] }),
|
||||
plaintext,
|
||||
JSON.stringify([["p", "pub-three"]]),
|
||||
);
|
||||
return "cipher-nip04";
|
||||
},
|
||||
@@ -894,10 +894,10 @@ test("publishSubscriptionList falls back to nip04 when nip44 fails", async () =>
|
||||
assert.equal(encryptCalls.nip04, 1, "nip04Encrypt should handle fallback");
|
||||
const signedEvent = signedEvents[0];
|
||||
const encryptedTags = signedEvent.tags.filter((tag) => tag[0] === "encrypted");
|
||||
assert.equal(
|
||||
encryptedTags.length,
|
||||
0,
|
||||
"fallback nip04 encryption should not advertise a nip44 tag",
|
||||
assert.deepEqual(
|
||||
encryptedTags,
|
||||
[["encrypted", "nip04"]],
|
||||
"fallback nip04 encryption should advertise nip04",
|
||||
);
|
||||
assert.equal(publishCalls.length, relayUrls.length, "event should publish to relays");
|
||||
assert.equal(manager.subsEventId, "signed-nip04-event");
|
||||
|
||||
+27
-16
@@ -490,9 +490,7 @@ await (async () => {
|
||||
let latestEventId = "event-initial";
|
||||
let latestCreatedAt = 1_000;
|
||||
|
||||
const decryptPayloads = new Map([
|
||||
[latestCiphertext, JSON.stringify({ blockedPubkeys: [] })],
|
||||
]);
|
||||
const decryptPayloads = new Map([[latestCiphertext, JSON.stringify([])]]);
|
||||
|
||||
const signedEvents = [];
|
||||
|
||||
@@ -541,9 +539,18 @@ await (async () => {
|
||||
} catch (error) {
|
||||
throw new Error(`unexpected payload ${plaintext}`);
|
||||
}
|
||||
const blocked = Array.isArray(parsed?.blockedPubkeys)
|
||||
? [...parsed.blockedPubkeys].sort()
|
||||
: [];
|
||||
let blocked;
|
||||
if (Array.isArray(parsed)) {
|
||||
blocked = parsed
|
||||
.filter((tag) => Array.isArray(tag) && tag.length >= 2 && tag[0] === "p")
|
||||
.map((tag) => tag[1])
|
||||
.filter((value) => typeof value === "string")
|
||||
.sort();
|
||||
} else if (Array.isArray(parsed?.blockedPubkeys)) {
|
||||
blocked = [...parsed.blockedPubkeys].sort();
|
||||
} else {
|
||||
blocked = [];
|
||||
}
|
||||
const cipher = `cipher:${JSON.stringify(blocked)}`;
|
||||
decryptPayloads.set(cipher, plaintext);
|
||||
return cipher;
|
||||
@@ -607,11 +614,15 @@ await (async () => {
|
||||
"direct signer flows should never trigger extension permission prompts",
|
||||
);
|
||||
|
||||
const muteEvent = signedEvents.find((event) => event.kind === 10000);
|
||||
const muteEvent = signedEvents.find(
|
||||
(event) =>
|
||||
event.kind === 10000 &&
|
||||
Array.isArray(event.tags) &&
|
||||
event.tags.some((tag) => Array.isArray(tag) && tag[0] === "p"),
|
||||
);
|
||||
assert(muteEvent, "block list updates should publish a kind 10000 mute list event");
|
||||
assert(
|
||||
Array.isArray(muteEvent.tags) &&
|
||||
muteEvent.tags.some((tag) => Array.isArray(tag) && tag[0] === "p" && tag[1] === target),
|
||||
muteEvent.tags.some((tag) => Array.isArray(tag) && tag[0] === "p" && tag[1] === target),
|
||||
"mute list event should include p-tags for blocked pubkeys",
|
||||
);
|
||||
} finally {
|
||||
@@ -677,7 +688,7 @@ await (async () => {
|
||||
assert.equal(pubkey, actor);
|
||||
assert.equal(
|
||||
plaintext,
|
||||
JSON.stringify({ blockedPubkeys: [blocked] }),
|
||||
JSON.stringify([["p", blocked]]),
|
||||
);
|
||||
return "cipher-nip44";
|
||||
},
|
||||
@@ -763,7 +774,7 @@ await (async () => {
|
||||
assert.equal(pubkey, actor);
|
||||
assert.equal(
|
||||
plaintext,
|
||||
JSON.stringify({ blockedPubkeys: [blocked] }),
|
||||
JSON.stringify([["p", blocked]]),
|
||||
);
|
||||
return "cipher-nip04";
|
||||
},
|
||||
@@ -787,10 +798,10 @@ await (async () => {
|
||||
);
|
||||
assert.equal(encryptCalls.nip04, 1, "nip04Encrypt should handle fallback");
|
||||
const encryptedTags = signedEvents[0].tags.filter((tag) => tag[0] === "encrypted");
|
||||
assert.equal(
|
||||
encryptedTags.length,
|
||||
0,
|
||||
"fallback nip04 encryption should not advertise a nip44 tag",
|
||||
assert.deepEqual(
|
||||
encryptedTags,
|
||||
[["encrypted", "nip04"]],
|
||||
"fallback nip04 encryption should advertise nip04",
|
||||
);
|
||||
assert.equal(publishCalls.length, 1, "event should publish to the available relay");
|
||||
} finally {
|
||||
@@ -834,7 +845,7 @@ await (async () => {
|
||||
v2: {
|
||||
async decrypt(_pubkey, ciphertext) {
|
||||
decryptCalls.nip44 += 1;
|
||||
return JSON.stringify({ blockedPubkeys: [blocked], hint: ciphertext });
|
||||
return JSON.stringify([["p", blocked, ciphertext]]);
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user