diff --git a/fixtures/events/kind-0-black.json b/fixtures/events/kind-0-black.json new file mode 100644 index 0000000..3080af1 --- /dev/null +++ b/fixtures/events/kind-0-black.json @@ -0,0 +1,9 @@ +{ + "id": "5f2236e745f47116ee8d869658ebc732a8a35fdeb30a876f46c8c0fef9ae0309", + "pubkey": "32b8276794dec3934fd7ddd2a97b5ee10ecef493441a55e83d838ccd98c58b7a", + "created_at": 1713966213, + "kind": 0, + "tags": [], + "content": "{\"name\":\"black\",\"about\":\"\",\"nip05\":\"\"}", + "sig": "bab454ca68332663c4c17591eb8ea993f78be7787da9e0c5ed140b21059e9fe3c12a5998fcefa94b1129934f798a649bac222b6051a9ea1ce8a01f9620c825e0" +} diff --git a/fixtures/events/kind-10000-black-blocks-user-me.json b/fixtures/events/kind-10000-black-blocks-user-me.json new file mode 100644 index 0000000..35a0d2e --- /dev/null +++ b/fixtures/events/kind-10000-black-blocks-user-me.json @@ -0,0 +1,14 @@ +{ + "id": "4aa67b0b7829d555a42b1f57f8033e6f0cda87a63b5bf5a0d5e10fbb9e7ab107", + "pubkey": "32b8276794dec3934fd7ddd2a97b5ee10ecef493441a55e83d838ccd98c58b7a", + "created_at": 1713997559, + "kind": 10000, + "tags": [ + [ + "p", + "2894578b2c8570825f48dc647e746e690f83f92d19446b3051f59cd0196a7991" + ] + ], + "content": "", + "sig": "9fa697cf5353cc82a7d1b3304c3d41e51e30547035a4c8fb25d3f5c9f378d43a30935b523c0a9671a2c61d36eff530f3f3fcfbb77440589649e5f2aa306df039" +} diff --git a/src/storages/UserStore.test.ts b/src/storages/UserStore.test.ts new file mode 100644 index 0000000..85cca61 --- /dev/null +++ b/src/storages/UserStore.test.ts @@ -0,0 +1,25 @@ +import userBlack from '~/fixtures/events/kind-0-black.json' with { type: 'json' }; +import userMe from '~/fixtures/events/event-0-makes-repost-with-quote-repost.json' with { type: 'json' }; +import blockEvent from '~/fixtures/events/kind-10000-black-blocks-user-me.json' with { type: 'json' }; +import event1authorUserMe from '~/fixtures/events/event-1-quote-repost-will-be-reposted.json' with { type: 'json' }; +import { NCache } from 'jsr:@nostrify/nostrify'; +import { UserStore } from '@/storages/UserStore.ts'; +import { assertEquals } from '@/deps-test.ts'; + +Deno.test('query events of users that are not blocked', async () => { + const userBlackCopy = structuredClone(userBlack); + const userMeCopy = structuredClone(userMe); + const blockEventCopy = structuredClone(blockEvent); + const event1authorUserMeCopy = structuredClone(event1authorUserMe); + + const db = new NCache({ max: 100 }); + + const store = new UserStore(userBlackCopy.pubkey, db); + + await store.event(blockEventCopy); + await store.event(userBlackCopy); + await store.event(userMeCopy); + await store.event(event1authorUserMeCopy); + + assertEquals(await store.query([{ kinds: [1] }], { limit: 1 }), []); +}); diff --git a/src/storages/UserStore.ts b/src/storages/UserStore.ts new file mode 100644 index 0000000..615e2af --- /dev/null +++ b/src/storages/UserStore.ts @@ -0,0 +1,40 @@ +import { NostrEvent, NostrFilter, NStore } from '@nostrify/nostrify'; +import { DittoEvent } from '@/interfaces/DittoEvent.ts'; +import { getTagSet } from '@/tags.ts'; + +export class UserStore implements NStore { + private store: NStore; + private pubkey: string; + + constructor(pubkey: string, store: NStore) { + this.pubkey = pubkey; + this.store = store; + } + + async event(event: NostrEvent, opts?: { signal?: AbortSignal }): Promise { + return await this.store.event(event, opts); + } + + /** + * Query events that `pubkey` did not block + * https://github.com/nostr-protocol/nips/blob/master/51.md#standard-lists + */ + async query(filters: NostrFilter[], opts: { signal?: AbortSignal; limit?: number } = {}): Promise { + const allEvents = await this.store.query(filters, opts); + + const mutedPubkeysEvent = await this.getMuteList(); + if (!mutedPubkeysEvent) { + return allEvents; + } + const mutedPubkeys = getTagSet(mutedPubkeysEvent.tags, 'p'); + + return allEvents.filter((event) => { + mutedPubkeys.has(event.pubkey) === false; + }); + } + + private async getMuteList(): Promise { + const [muteList] = await this.store.query([{ authors: [this.pubkey], kinds: [10000], limit: 1 }]); + return muteList; + } +}