From cc0147cb180bd65d5a5349744713feca554427b0 Mon Sep 17 00:00:00 2001 From: Mynima <62206239+RydalWater@users.noreply.github.com> Date: Fri, 8 Nov 2024 15:32:10 +0000 Subject: [PATCH] book: add filters JavaScript examples - Updated index.js - Added filters.js with example code - Updated 05_01_01-filter.md to include examples in book --- book/snippets/nostr/js/index.js | 2 + .../snippets/nostr/js/src/messages/filters.js | 157 ++++++++++++++++++ book/src/nostr/05_01_01-filter.md | 72 +++++++- 3 files changed, 227 insertions(+), 4 deletions(-) create mode 100644 book/snippets/nostr/js/src/messages/filters.js diff --git a/book/snippets/nostr/js/index.js b/book/snippets/nostr/js/index.js index 66b01484a..c132db2a7 100644 --- a/book/snippets/nostr/js/index.js +++ b/book/snippets/nostr/js/index.js @@ -1,6 +1,7 @@ const keys = require("./src/keys"); const eventJson = require("./src/event/json"); const eventBuilder = require("./src/event/builder"); +const filters = require("./src/messages/filters"); const relayMessages = require("./src/messages/relay"); const nip01 = require("./src/nip01"); const nip05 = require("./src/nip05"); @@ -21,6 +22,7 @@ async function main() { eventBuilder.eventBuilder(); await relayMessages.run(); + await filters.run(); nip01.run(); await nip05.run(); diff --git a/book/snippets/nostr/js/src/messages/filters.js b/book/snippets/nostr/js/src/messages/filters.js new file mode 100644 index 000000000..dcb43618d --- /dev/null +++ b/book/snippets/nostr/js/src/messages/filters.js @@ -0,0 +1,157 @@ +const { Filter, Keys, Kind, EventBuilder, Timestamp, Tag, loadWasmSync } = require('@rust-nostr/nostr'); + +async function run() { + loadWasmSync(); + + // Generate keys and Events + const keys = Keys.generate(); + const keys2 = Keys.generate(); + + const kind0 = new Kind(0); + const kind1 = new Kind(1); + const kind4 = new Kind(4); + + const event = EventBuilder.textNote("Hello World!", []).toEvent(keys); + const event2 = new EventBuilder(kind0, "Goodbye World!", [Tag.identifier("Identification D Tag")]).toEvent(keys2); + + console.log(); + console.log("Creating Filters:"); + + // ANCHOR: create-filter-id + // Filter for specific ID + console.log(" Filter for specific Event ID:"); + let f = new Filter().id(event.id); + console.log(` ${f.asJson()}`); + // ANCHOR_END: create-filter-id + + console.log(); + // ANCHOR: create-filter-author + // Filter for specific Author + console.log(" Filter for specific Author:"); + f = new Filter().author(keys.publicKey); + console.log(` ${f.asJson()}`); + // ANCHOR_END: create-filter-author + + console.log(); + // ANCHOR: create-filter-kind-pk + // Filter by PK and Kinds + console.log(" Filter with PK and Kinds:"); + f = new Filter() + .pubkey(keys.publicKey) + .kind(kind1); + console.log(` ${f.asJson()}`); + // ANCHOR_END: create-filter-kind-pk + + console.log(); + // ANCHOR: create-filter-search + // Filter for specific string + console.log(" Filter for specific search string:"); + f = new Filter().search("Ask Nostr Anything"); + console.log(` ${f.asJson()}`); + // ANCHOR_END: create-filter-search + + console.log(); + // ANCHOR: create-filter-timeframe + console.log(" Filter for events from specific public key within given timeframe:"); + // Create timestamps + const date = new Date(2009, 1, 3, 0, 0); + const timestamp = Math.floor(date.getTime() / 1000); + const sinceTs = Timestamp.fromSecs(timestamp); + const untilTs = Timestamp.now(); + + // Filter with timeframe + f = new Filter() + .pubkey(keys.publicKey) + .since(sinceTs) + .until(untilTs); + console.log(` ${f.asJson()}`); + // ANCHOR_END: create-filter-timeframe + + console.log(); + // ANCHOR: create-filter-limit + // Filter for specific PK with limit + console.log(" Filter for specific Author, limited to 10 Events:"); + f = new Filter() + .author(keys.publicKey) + .limit(10); + console.log(` ${f.asJson()}`); + // ANCHOR_END: create-filter-limit + + console.log(); + // ANCHOR: create-filter-hashtag + // Filter for Hashtags + console.log(" Filter for a list of Hashtags:"); + f = new Filter().hashtags(["#Bitcoin", "#AskNostr", "#Meme"]); + console.log(` ${f.asJson()}`); + // ANCHOR_END: create-filter-hashtag + + console.log(); + // ANCHOR: create-filter-reference + // Filter for Reference + console.log(" Filter for a Reference:"); + f = new Filter().reference("This is my NIP-12 Reference"); + console.log(` ${f.asJson()}`); + // ANCHOR_END: create-filter-reference + + console.log(); + // ANCHOR: create-filter-identifier + // Filter for Identifier + console.log(" Filter for a Identifier:"); + f = new Filter().identifier("This is my NIP-12 Identifier"); + console.log(` ${f.asJson()}`); + // ANCHOR_END: create-filter-identifier + + console.log(); + console.log("Modifying Filters:"); + // ANCHOR: modify-filter + // Modifying Filters (adding/removing) + f = new Filter() + .pubkeys([keys.publicKey, keys2.publicKey]) + .ids([event.id, event2.id]) + .kinds([kind0, kind1]) + .author(keys.publicKey); + + // Add an additional Kind to existing filter + f = f.kinds([kind4]); + + // Print Results + console.log(" Before:"); + console.log(` ${f.asJson()}`); + console.log(); + + // Remove PKs, Kinds and IDs from filter + f = f.removePubkeys([keys2.publicKey]); + console.log(" After (remove pubkeys):"); + console.log(` ${f.asJson()}`); + kind_rem0 = new Kind(0); + kind_rem4 = new Kind(4); + f = f.removeKinds([kind_rem0, kind_rem4]); + console.log(" After (remove kinds):"); + console.log(` ${f.asJson()}`); + + f = f.removeIds([event2.id]); + console.log(" After (remove IDs):"); + console.log(` ${f.asJson()}`); + // ANCHOR_END: modify-filter + + console.log(); + console.log("Other Filter Operations:"); + // ANCHOR: other-parse + // Parse filter + console.log(" Parse Filter from Json:"); + const fJson = f.asJson(); + f = Filter.fromJson(fJson); + console.log(` ${f.asJson()}`); + // ANCHOR_END: other-parse + + console.log(); + // ANCHOR: other-match + console.log(" Logical tests:"); + kind_match = new Kind(1); + f = new Filter().author(keys.publicKey).kind(kind_match); + console.log(` Event match for filter: ${f.matchEvent(event)}`); + console.log(` Event2 match for filter: ${f.matchEvent(event2)}`); + // ANCHOR_END: other-match +} + +module.exports.run = run; \ No newline at end of file diff --git a/book/src/nostr/05_01_01-filter.md b/book/src/nostr/05_01_01-filter.md index 638238e18..2f99a08d2 100644 --- a/book/src/nostr/05_01_01-filter.md +++ b/book/src/nostr/05_01_01-filter.md @@ -37,7 +37,7 @@ Filtering events by author using `author()`. {{#include ../../snippets/nostr/python/src/messages/filters.py:create-filter-author}} ``` -Filtering events based on multiple criteria. In this case, by public key using `public_key()` and kind using `kind()`. +Filtering events based on multiple criteria. In this case, by public key using `pubkey()` and kind using `kind()`. ```python,ignore {{#include ../../snippets/nostr/python/src/messages/filters.py:create-filter-kind-pk}} @@ -78,7 +78,55 @@ Finally, filtering using hashtags (`hashtag()`), NIP-12 reference tags (`referen
JavaScript
-TODO +The following code examples all utilise the `Filters()` along with associated methods to create filter objects and print these in JSON format using the `asJson()` method. + +Filtering events based on a specific event ID using `id()`. + +```javascript,ignore +{{#include ../../snippets/nostr/js/src/messages/filters.js:create-filter-id}} +``` + +Filtering events by author using `author()`. + +```javascript,ignore +{{#include ../../snippets/nostr/js/src/messages/filters.js:create-filter-author}} +``` + +Filtering events based on multiple criteria. In this case, by public key using `pubkey()` and kind using `kind()`. + +```javascript,ignore +{{#include ../../snippets/nostr/js/src/messages/filters.js:create-filter-kind-pk}} +``` + +Filtering for specific text strings using `search()`. + +```javascript,ignore +{{#include ../../snippets/nostr/js/src/messages/filters.js:create-filter-search}} +``` + +Restricting query results to specific timeframes (using `since()` and `until()`), as well as limiting search results to a maximum of 10 records using `limit()`. + +```javascript,ignore +{{#include ../../snippets/nostr/js/src/messages/filters.js:create-filter-timeframe}} +``` + +```javascript,ignore +{{#include ../../snippets/nostr/js/src/messages/filters.js:create-filter-limit}} +``` + +Finally, filtering using hashtags (`hashtags()`), NIP-12 reference tags (`reference()`) and identifiers (`identifiers()`), respectively. + +```javascript,ignore +{{#include ../../snippets/nostr/js/src/messages/filters.js:create-filter-hashtag}} +``` + +```javascript,ignore +{{#include ../../snippets/nostr/js/src/messages/filters.js:create-filter-reference}} +``` + +```javascript,ignore +{{#include ../../snippets/nostr/js/src/messages/filters.js:create-filter-identifier}} +```
@@ -125,8 +173,14 @@ Similarly, the range of 'remove' methods (e.g. `remove_kinds()`) allow us to tak
JavaScript
-TODO +Adding more conditions to existing objects can be done by simply calling the relevant method on the instance of the object. +In this example we create a initial filter with `pubkeys()`, `ids()`, `kinds()` and a single `author()` then modify the object further to include another kind (4) to the existing list of kinds (0, 1). + +Similarly, the range of 'remove' methods (e.g. `removekinds()`) allow us to take an existing filter and remove unwanted conditions without needed to reconstruct the filter object from scratch. +```javascript,ignore +{{#include ../../snippets/nostr/js/src/messages/filters.js:modify-filter}} +```
Kotlin
@@ -181,7 +235,17 @@ To perform a logical test and determine if a given event object matches existing
JavaScript
-TODO +We can parse existing filter JSON object using the `fromJson()` method when instantiating a filter object. + +```javascript,ignore +{{#include ../../snippets/nostr/js/src/messages/filters.js:other-parse}} +``` + +To perform a logical test and determine if a given event object matches existing filter conditions the `matchEvent()` method can be used. + +```javascript,ignore +{{#include ../../snippets/nostr/js/src/messages/filters.js:other-match}} +```