From 6c292b8da47f1b606a47798573b0e026ddcc1f00 Mon Sep 17 00:00:00 2001 From: "P. Reis" Date: Thu, 25 Apr 2024 16:41:40 -0300 Subject: [PATCH 1/6] feat: create UserStore class --- src/storages/UserStore.ts | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/storages/UserStore.ts diff --git a/src/storages/UserStore.ts b/src/storages/UserStore.ts new file mode 100644 index 00000000..02a3b03e --- /dev/null +++ b/src/storages/UserStore.ts @@ -0,0 +1,38 @@ +import { NostrEvent, NostrFilter, NStore } from '@nostrify/nostrify'; +import { DittoEvent } from '@/interfaces/DittoEvent.ts'; +import { getTagSet } from '@/tags.ts'; + +export class UserStore implements NStore { + store: NStore; + pubkey: string; + #muteList: Promise; + + constructor(pubkey: string, store: NStore) { + this.pubkey = pubkey; + this.store = store; + this.#muteList = this.#getMuteList(); + } + + async event(event: NostrEvent, opts?: { signal?: AbortSignal }): Promise { + return await this.store.event(event, opts); + } + + /** Query events that `pubkey` did not block */ + async query(filters: NostrFilter[], opts: { signal?: AbortSignal; limit?: number } = {}): Promise { + const allEvents = await this.store.query(filters, opts); + + const blockedUsers = getTagSet((await this.#muteList).tags, 'p'); + + return allEvents.filter((event) => { + blockedUsers.has(event.pubkey) === false; + }); + } + + async #getMuteList(): Promise { + const [muteList] = await this.query([{ authors: [this.pubkey], kinds: [10000], limit: 1 }], { + signal: AbortSignal.timeout(5000), + limit: 1, + }); + return muteList; + } +} From ddc84bf47af4b14672a891dc4f12ff926cba7915 Mon Sep 17 00:00:00 2001 From: "P. Reis" Date: Thu, 25 Apr 2024 18:43:12 -0300 Subject: [PATCH 2/6] refactor(UserStore): change fields to private & handle in case of muteList undefined --- src/storages/UserStore.ts | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/storages/UserStore.ts b/src/storages/UserStore.ts index 02a3b03e..f9cc068d 100644 --- a/src/storages/UserStore.ts +++ b/src/storages/UserStore.ts @@ -3,32 +3,39 @@ import { DittoEvent } from '@/interfaces/DittoEvent.ts'; import { getTagSet } from '@/tags.ts'; export class UserStore implements NStore { - store: NStore; - pubkey: string; - #muteList: Promise; + private store: NStore; + private pubkey: string; + private muteList: Promise; constructor(pubkey: string, store: NStore) { this.pubkey = pubkey; this.store = store; - this.#muteList = this.#getMuteList(); + this.muteList = this.getMuteList(); } async event(event: NostrEvent, opts?: { signal?: AbortSignal }): Promise { return await this.store.event(event, opts); } - /** Query events that `pubkey` did not block */ + /** + * 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 blockedUsers = getTagSet((await this.#muteList).tags, 'p'); + const mutedPubkeysEvent = await this.muteList; + if (!mutedPubkeysEvent) { + return allEvents; + } + const mutedPubkeys = getTagSet(mutedPubkeysEvent.tags, 'p'); return allEvents.filter((event) => { - blockedUsers.has(event.pubkey) === false; + mutedPubkeys.has(event.pubkey) === false; }); } - async #getMuteList(): Promise { + private async getMuteList(): Promise { const [muteList] = await this.query([{ authors: [this.pubkey], kinds: [10000], limit: 1 }], { signal: AbortSignal.timeout(5000), limit: 1, From c87db6d1f8bca1137aa6394ab9a433ad44231290 Mon Sep 17 00:00:00 2001 From: "P. Reis" Date: Fri, 26 Apr 2024 16:05:53 -0300 Subject: [PATCH 3/6] refactor: remove muteList as a field --- src/storages/UserStore.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/storages/UserStore.ts b/src/storages/UserStore.ts index f9cc068d..615e2afd 100644 --- a/src/storages/UserStore.ts +++ b/src/storages/UserStore.ts @@ -5,12 +5,10 @@ import { getTagSet } from '@/tags.ts'; export class UserStore implements NStore { private store: NStore; private pubkey: string; - private muteList: Promise; constructor(pubkey: string, store: NStore) { this.pubkey = pubkey; this.store = store; - this.muteList = this.getMuteList(); } async event(event: NostrEvent, opts?: { signal?: AbortSignal }): Promise { @@ -24,7 +22,7 @@ export class UserStore implements NStore { async query(filters: NostrFilter[], opts: { signal?: AbortSignal; limit?: number } = {}): Promise { const allEvents = await this.store.query(filters, opts); - const mutedPubkeysEvent = await this.muteList; + const mutedPubkeysEvent = await this.getMuteList(); if (!mutedPubkeysEvent) { return allEvents; } @@ -36,10 +34,7 @@ export class UserStore implements NStore { } private async getMuteList(): Promise { - const [muteList] = await this.query([{ authors: [this.pubkey], kinds: [10000], limit: 1 }], { - signal: AbortSignal.timeout(5000), - limit: 1, - }); + const [muteList] = await this.store.query([{ authors: [this.pubkey], kinds: [10000], limit: 1 }]); return muteList; } } From ad928eec9b42bc68a03d32bcdc7ef11ad001edbe Mon Sep 17 00:00:00 2001 From: "P. Reis" Date: Fri, 26 Apr 2024 16:09:56 -0300 Subject: [PATCH 4/6] test: kind 0 (user 'black') fixture --- fixtures/events/kind-0-black.json | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 fixtures/events/kind-0-black.json diff --git a/fixtures/events/kind-0-black.json b/fixtures/events/kind-0-black.json new file mode 100644 index 00000000..3080af1e --- /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" +} From 2d9db61debfb7b2b6724416dbda380e1ebccc9c0 Mon Sep 17 00:00:00 2001 From: "P. Reis" Date: Fri, 26 Apr 2024 16:12:13 -0300 Subject: [PATCH 5/6] test: kind 10000 ('black' blocks 'me') fixture --- .../events/kind-10000-black-blocks-user-me.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 fixtures/events/kind-10000-black-blocks-user-me.json 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 00000000..35a0d2ed --- /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" +} From 8a460d6bc57e4a7019d09b21e560fff4a8e4d146 Mon Sep 17 00:00:00 2001 From: "P. Reis" Date: Fri, 26 Apr 2024 16:23:10 -0300 Subject: [PATCH 6/6] test: create rough tests for UserStore --- src/storages/UserStore.test.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/storages/UserStore.test.ts diff --git a/src/storages/UserStore.test.ts b/src/storages/UserStore.test.ts new file mode 100644 index 00000000..85cca61d --- /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 }), []); +});