8 changed files with 174 additions and 45 deletions
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
import { describe, expect, it } from 'vitest' |
||||
import { kinds } from 'nostr-tools' |
||||
import { filterEventsExcludingMutedAuthors } from './mute-set' |
||||
|
||||
describe('filterEventsExcludingMutedAuthors', () => { |
||||
it('drops events from muted pubkeys', () => { |
||||
const muted = 'a'.repeat(64) |
||||
const other = 'b'.repeat(64) |
||||
const events = [ |
||||
{ kind: kinds.ShortTextNote, pubkey: muted, id: '1'.repeat(64), sig: 's', tags: [], content: '', created_at: 1 }, |
||||
{ kind: kinds.ShortTextNote, pubkey: other, id: '2'.repeat(64), sig: 's', tags: [], content: '', created_at: 1 } |
||||
] |
||||
const out = filterEventsExcludingMutedAuthors(events, new Set([muted])) |
||||
expect(out).toHaveLength(1) |
||||
expect(out[0]?.pubkey).toBe(other) |
||||
}) |
||||
}) |
||||
@ -1,7 +1,24 @@
@@ -1,7 +1,24 @@
|
||||
import type { Event } from 'nostr-tools' |
||||
|
||||
/** |
||||
* Mute pubkey sets use lowercase hex so lookups match Nostr events and `p` tags regardless of casing. |
||||
*/ |
||||
export function muteSetHas(mutePubkeySet: Set<string>, pubkey: string | undefined | null): boolean { |
||||
export function muteSetHas(mutePubkeySet: ReadonlySet<string>, pubkey: string | undefined | null): boolean { |
||||
if (!pubkey) return false |
||||
return mutePubkeySet.has(pubkey.toLowerCase()) |
||||
} |
||||
|
||||
/** Drop notes whose author is in the viewer's public or private mute list. */ |
||||
export function filterEventsExcludingMutedAuthors( |
||||
events: readonly Event[], |
||||
mutePubkeySet: ReadonlySet<string> |
||||
): Event[] { |
||||
if (mutePubkeySet.size === 0) return [...events] |
||||
return events.filter((ev) => !muteSetHas(mutePubkeySet, ev.pubkey)) |
||||
} |
||||
|
||||
/** Stable SETTINGS / cache segment when mute lists change. */ |
||||
export function mutePubkeySetFingerprint(mutePubkeySet: ReadonlySet<string>): string { |
||||
if (mutePubkeySet.size === 0) return '0' |
||||
return [...mutePubkeySet].sort().join('\n') |
||||
} |
||||
|
||||
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
import { describe, expect, it } from 'vitest' |
||||
import { kinds } from 'nostr-tools' |
||||
import { mergeInteractionEvents } from './ProfileInteractionsMap' |
||||
|
||||
function interaction(pubkey: string, pTags: string[]) { |
||||
return { |
||||
kind: kinds.ShortTextNote, |
||||
pubkey, |
||||
tags: pTags.map((p) => ['p', p]), |
||||
content: '', |
||||
id: `${pubkey.slice(0, 8)}${'c'.repeat(56)}`, |
||||
sig: 's'.repeat(128), |
||||
created_at: 1_700_000_000 |
||||
} |
||||
} |
||||
|
||||
describe('mergeInteractionEvents', () => { |
||||
it('excludes muted partners and events authored by muted pubkeys', () => { |
||||
const profile = 'a'.repeat(64) |
||||
const partner = 'b'.repeat(64) |
||||
const muted = 'f'.repeat(64) |
||||
const cards = mergeInteractionEvents( |
||||
profile, |
||||
[ |
||||
interaction(profile, [partner]), |
||||
interaction(profile, [muted]), |
||||
interaction(muted, [profile]), |
||||
interaction(partner, [profile]) |
||||
], |
||||
new Set([muted]) |
||||
) |
||||
expect(cards.map((c) => c.pubkey)).toEqual([partner]) |
||||
expect(cards[0]?.score).toBe(2) |
||||
}) |
||||
}) |
||||
Loading…
Reference in new issue