nostr 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.editorconfig +1 -1
- data/.rubocop.yml +23 -0
- data/.tool-versions +2 -1
- data/CHANGELOG.md +36 -1
- data/README.md +92 -228
- data/docs/.gitignore +4 -0
- data/docs/.vitepress/config.mjs +112 -0
- data/docs/README.md +44 -0
- data/docs/api-examples.md +49 -0
- data/docs/bun.lockb +0 -0
- data/docs/common-use-cases/bech32-encoding-and-decoding-(NIP-19).md +190 -0
- data/docs/core/client.md +108 -0
- data/docs/core/keys.md +136 -0
- data/docs/core/user.md +43 -0
- data/docs/events/contact-list.md +29 -0
- data/docs/events/encrypted-direct-message.md +28 -0
- data/docs/events/recommend-server.md +32 -0
- data/docs/events/set-metadata.md +20 -0
- data/docs/events/text-note.md +15 -0
- data/docs/events.md +11 -0
- data/docs/getting-started/installation.md +21 -0
- data/docs/getting-started/overview.md +170 -0
- data/docs/implemented-nips.md +9 -0
- data/docs/index.md +44 -0
- data/docs/markdown-examples.md +85 -0
- data/docs/package.json +12 -0
- data/docs/relays/connecting-to-a-relay.md +21 -0
- data/docs/relays/publishing-events.md +29 -0
- data/docs/relays/receiving-events.md +6 -0
- data/docs/subscriptions/creating-a-subscription.md +49 -0
- data/docs/subscriptions/deleting-a-subscription.md +10 -0
- data/docs/subscriptions/filtering-subscription-events.md +115 -0
- data/docs/subscriptions/updating-a-subscription.md +4 -0
- data/lib/nostr/bech32.rb +203 -0
- data/lib/nostr/client.rb +2 -1
- data/lib/nostr/crypto.rb +11 -7
- data/lib/nostr/errors/error.rb +7 -0
- data/lib/nostr/errors/invalid_hrp_error.rb +21 -0
- data/lib/nostr/errors/invalid_key_format_error.rb +20 -0
- data/lib/nostr/errors/invalid_key_length_error.rb +20 -0
- data/lib/nostr/errors/invalid_key_type_error.rb +18 -0
- data/lib/nostr/errors/key_validation_error.rb +6 -0
- data/lib/nostr/errors.rb +8 -0
- data/lib/nostr/event.rb +3 -4
- data/lib/nostr/events/encrypted_direct_message.rb +4 -3
- data/lib/nostr/filter.rb +4 -4
- data/lib/nostr/key.rb +100 -0
- data/lib/nostr/key_pair.rb +30 -6
- data/lib/nostr/keygen.rb +43 -4
- data/lib/nostr/private_key.rb +36 -0
- data/lib/nostr/public_key.rb +36 -0
- data/lib/nostr/relay_message_type.rb +18 -0
- data/lib/nostr/subscription.rb +2 -2
- data/lib/nostr/user.rb +17 -8
- data/lib/nostr/version.rb +1 -1
- data/lib/nostr.rb +6 -0
- data/nostr.gemspec +9 -9
- data/sig/nostr/bech32.rbs +14 -0
- data/sig/nostr/client.rbs +5 -5
- data/sig/nostr/crypto.rbs +5 -5
- data/sig/nostr/errors/error.rbs +4 -0
- data/sig/nostr/errors/invalid_hrb_error.rbs +6 -0
- data/sig/nostr/errors/invalid_key_format_error.rbs +5 -0
- data/sig/nostr/errors/invalid_key_length_error.rbs +5 -0
- data/sig/nostr/errors/invalid_key_type_error.rbs +5 -0
- data/sig/nostr/errors/key_validation_error.rbs +4 -0
- data/sig/nostr/event.rbs +4 -4
- data/sig/nostr/events/encrypted_direct_message.rbs +2 -2
- data/sig/nostr/filter.rbs +3 -12
- data/sig/nostr/key.rbs +16 -0
- data/sig/nostr/key_pair.rbs +7 -3
- data/sig/nostr/keygen.rbs +5 -2
- data/sig/nostr/private_key.rbs +4 -0
- data/sig/nostr/public_key.rbs +4 -0
- data/sig/nostr/relay_message_type.rbs +8 -0
- data/sig/nostr/user.rbs +4 -8
- data/sig/vendor/bech32/nostr/entity.rbs +41 -0
- data/sig/vendor/bech32/nostr/nip19.rbs +20 -0
- data/sig/vendor/bech32/segwit_addr.rbs +21 -0
- data/sig/vendor/bech32.rbs +25 -0
- data/sig/vendor/event_emitter.rbs +10 -3
- data/sig/vendor/event_machine/channel.rbs +1 -1
- data/sig/vendor/faye/websocket/api.rbs +45 -0
- data/sig/vendor/faye/websocket/client.rbs +43 -0
- data/sig/vendor/faye/websocket.rbs +30 -0
- metadata +79 -21
@@ -0,0 +1,21 @@
|
|
1
|
+
# Installation
|
2
|
+
|
3
|
+
Install the gem and add to the application's Gemfile by executing:
|
4
|
+
|
5
|
+
```shell
|
6
|
+
bundle add nostr
|
7
|
+
```
|
8
|
+
|
9
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
10
|
+
|
11
|
+
```shell
|
12
|
+
gem install nostr
|
13
|
+
```
|
14
|
+
|
15
|
+
## Requiring the gem
|
16
|
+
|
17
|
+
All examples in this guide assume that the gem has been required:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
require 'nostr'
|
21
|
+
```
|
@@ -0,0 +1,170 @@
|
|
1
|
+
---
|
2
|
+
editLink: true
|
3
|
+
---
|
4
|
+
|
5
|
+
# Getting started
|
6
|
+
|
7
|
+
This gem abstracts the complexity that you would face when trying to connect to relays web sockets, send and receive
|
8
|
+
events, handle events callbacks and much more.
|
9
|
+
|
10
|
+
## Visual overview
|
11
|
+
|
12
|
+
Begin your journey with an overview of the essential functions. A visual representation below maps out the key
|
13
|
+
components we'll delve into in this section.
|
14
|
+
|
15
|
+
```mermaid
|
16
|
+
classDiagram
|
17
|
+
class Client {
|
18
|
+
connect(relay)
|
19
|
+
publish(event)
|
20
|
+
subscribe(subscription_id, filter)
|
21
|
+
unsubscribe(subscription_id)
|
22
|
+
}
|
23
|
+
class Relay {
|
24
|
+
url
|
25
|
+
name
|
26
|
+
}
|
27
|
+
class Event {
|
28
|
+
pubkey
|
29
|
+
created_at
|
30
|
+
kind
|
31
|
+
tags
|
32
|
+
content
|
33
|
+
add_event_reference(event_id)
|
34
|
+
add_pubkey_reference(pubkey)
|
35
|
+
serialize()
|
36
|
+
to_h()
|
37
|
+
sign(private_key)
|
38
|
+
}
|
39
|
+
class Subscription {
|
40
|
+
id
|
41
|
+
filter
|
42
|
+
}
|
43
|
+
class Filter {
|
44
|
+
ids
|
45
|
+
authors
|
46
|
+
kinds
|
47
|
+
since
|
48
|
+
until
|
49
|
+
limit
|
50
|
+
to_h()
|
51
|
+
}
|
52
|
+
class EventKind {
|
53
|
+
<<Enumeration>>
|
54
|
+
SET_METADATA
|
55
|
+
TEXT_NOTE
|
56
|
+
RECOMMEND_SERVER
|
57
|
+
CONTACT_LIST
|
58
|
+
ENCRYPTED_DIRECT_MESSAGE
|
59
|
+
}
|
60
|
+
class KeyPair {
|
61
|
+
private_key
|
62
|
+
public_key
|
63
|
+
}
|
64
|
+
class Keygen {
|
65
|
+
generate_key_pair()
|
66
|
+
generate_private_key()
|
67
|
+
extract_public_key(private_key)
|
68
|
+
}
|
69
|
+
class User {
|
70
|
+
keypair
|
71
|
+
create_event(event_attributes)
|
72
|
+
}
|
73
|
+
|
74
|
+
Client --> Relay : connects via <br> WebSockets to
|
75
|
+
Client --> Event : uses WebSockets to <br> publish and receive
|
76
|
+
Client --> Subscription : receives Events via
|
77
|
+
Subscription --> Filter : uses
|
78
|
+
Event --> EventKind : is of kind
|
79
|
+
User --> KeyPair : has
|
80
|
+
User --> Event : creates and signs
|
81
|
+
User --> Keygen : uses to generate keys
|
82
|
+
Keygen --> KeyPair : generates
|
83
|
+
```
|
84
|
+
|
85
|
+
## Code overview
|
86
|
+
|
87
|
+
Explore the provided code snippet to learn about initializing the Nostr [client](../core/client.md), generating
|
88
|
+
a [keypair](../core/keys), [publishing](../relays/publishing-events) an event, and
|
89
|
+
efficiently [managing event subscriptions](../subscriptions/creating-a-subscription) (including event reception,
|
90
|
+
filtering, and WebSocket event handling).
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
# Require the gem
|
94
|
+
require 'nostr'
|
95
|
+
|
96
|
+
# Instantiate a client
|
97
|
+
client = Nostr::Client.new
|
98
|
+
|
99
|
+
# a) Use an existing keypair
|
100
|
+
keypair = Nostr::KeyPair.new(
|
101
|
+
private_key: Nostr::PrivateKey.new('your-hex-private-key'),
|
102
|
+
public_key: Nostr::PublicKey.new('your-hex-public-key'),
|
103
|
+
)
|
104
|
+
|
105
|
+
# b) Or build a keypair from a private key
|
106
|
+
keygen = Nostr::Keygen.new
|
107
|
+
keypair = keygen.get_key_pair_from_private_key(
|
108
|
+
Nostr::PrivateKey.new('your-hex-private-key')
|
109
|
+
)
|
110
|
+
|
111
|
+
# c) Or create a new keypair
|
112
|
+
keygen = Nostr::Keygen.new
|
113
|
+
keypair = keygen.generate_keypair
|
114
|
+
|
115
|
+
# Create a user with the keypair
|
116
|
+
user = Nostr::User.new(keypair: keypair)
|
117
|
+
|
118
|
+
# Create a signed event
|
119
|
+
text_note_event = user.create_event(
|
120
|
+
kind: Nostr::EventKind::TEXT_NOTE,
|
121
|
+
content: 'Your feedback is appreciated, now pay $8'
|
122
|
+
)
|
123
|
+
|
124
|
+
# Connect asynchronously to a relay
|
125
|
+
relay = Nostr::Relay.new(url: 'wss://nostr.wine', name: 'Wine')
|
126
|
+
client.connect(relay)
|
127
|
+
|
128
|
+
# Listen asynchronously for the connect event
|
129
|
+
client.on :connect do
|
130
|
+
# Send the event to the Relay
|
131
|
+
client.publish(text_note_event)
|
132
|
+
|
133
|
+
# Create a filter to receive the first 20 text notes
|
134
|
+
# and encrypted direct messages from the relay that
|
135
|
+
# were created in the previous hour
|
136
|
+
filter = Nostr::Filter.new(
|
137
|
+
kinds: [
|
138
|
+
Nostr::EventKind::TEXT_NOTE,
|
139
|
+
Nostr::EventKind::ENCRYPTED_DIRECT_MESSAGE
|
140
|
+
],
|
141
|
+
since: Time.now.to_i - 3600, # 1 hour ago
|
142
|
+
until: Time.now.to_i,
|
143
|
+
limit: 20,
|
144
|
+
)
|
145
|
+
|
146
|
+
# Subscribe to events matching conditions of a filter
|
147
|
+
subscription = client.subscribe(filter: filter)
|
148
|
+
|
149
|
+
# Unsubscribe from events matching the filter above
|
150
|
+
client.unsubscribe(subscription.id)
|
151
|
+
end
|
152
|
+
|
153
|
+
# Listen for incoming messages and print them
|
154
|
+
client.on :message do |message|
|
155
|
+
puts message
|
156
|
+
end
|
157
|
+
|
158
|
+
# Listen for error messages
|
159
|
+
client.on :error do |error_message|
|
160
|
+
# Handle the error
|
161
|
+
end
|
162
|
+
|
163
|
+
# Listen for the close event
|
164
|
+
client.on :close do |code, reason|
|
165
|
+
# You may attempt to reconnect to the relay here
|
166
|
+
end
|
167
|
+
```
|
168
|
+
|
169
|
+
Beyond what's covered here, the Nostr protocol and this gem boast a wealth of additional functionalities. For an
|
170
|
+
in-depth exploration of these capabilities, proceed to the next page.
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# Implemented NIPs
|
2
|
+
|
3
|
+
NIPs stand for Nostr Implementation Possibilities. They exist to document what may be implemented by Nostr-compatible
|
4
|
+
relay and client software.
|
5
|
+
|
6
|
+
- [NIP-01: Basic protocol flow description](https://github.com/nostr-protocol/nips/blob/master/01.md)
|
7
|
+
- [NIP-02: Contact List and Petnames](https://github.com/nostr-protocol/nips/blob/master/02.md)
|
8
|
+
- [NIP-04: Encrypted Direct Message](https://github.com/nostr-protocol/nips/blob/master/04.md)
|
9
|
+
- [NIP-19: Bech32-encoded entities](https://github.com/nostr-protocol/nips/blob/master/19.md)
|
data/docs/index.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
---
|
2
|
+
# https://vitepress.dev/reference/default-theme-home-page
|
3
|
+
layout: home
|
4
|
+
|
5
|
+
hero:
|
6
|
+
name: "Nostr"
|
7
|
+
text: "Ruby"
|
8
|
+
tagline: "The Nostr protocol implemented in a Ruby gem."
|
9
|
+
actions:
|
10
|
+
- theme: brand
|
11
|
+
text: Getting Started
|
12
|
+
link: /getting-started/overview
|
13
|
+
- theme: alt
|
14
|
+
text: View on Github
|
15
|
+
link: https://github.com/wilsonsilva/nostr
|
16
|
+
- theme: alt
|
17
|
+
text: View on RubyDoc
|
18
|
+
link: https://www.rubydoc.info/gems/nostr
|
19
|
+
- theme: alt
|
20
|
+
text: View on RubyGems
|
21
|
+
link: https://rubygems.org/gems/nostr
|
22
|
+
|
23
|
+
features:
|
24
|
+
- title: Asynchronous
|
25
|
+
details: Non-blocking I/O for maximum performance.
|
26
|
+
icon: ⚡
|
27
|
+
- title: Lightweight
|
28
|
+
details: Minimal runtime dependencies.
|
29
|
+
icon: 🪶
|
30
|
+
- title: Intuitive
|
31
|
+
details: The API mirrors the Nostr protocol specification domain language.
|
32
|
+
icon: 💡
|
33
|
+
- title: Fully documented
|
34
|
+
details: All code is documented from both the maintainer's as well as the consumer's perspective.
|
35
|
+
icon: 📚
|
36
|
+
- title: Fully tested
|
37
|
+
details: All code is tested with 100% coverage.
|
38
|
+
icon: 🧪
|
39
|
+
- title: Fully typed
|
40
|
+
details: All code is typed with <a href="https://rubygems.org/gems/rbs" target="_blank">RBS</a> with the help of <a href="https://rubygems.org/gems/typeprof" target="_blank">TypeProf</a>. Type correctness is enforced by <a href="https://rubygems.org/gems/steep" target="_blank">Steep</a>.
|
41
|
+
icon: ✅
|
42
|
+
|
43
|
+
---
|
44
|
+
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# Markdown Extension Examples
|
2
|
+
|
3
|
+
This page demonstrates some of the built-in markdown extensions provided by VitePress.
|
4
|
+
|
5
|
+
## Syntax Highlighting
|
6
|
+
|
7
|
+
VitePress provides Syntax Highlighting powered by [Shiki](https://github.com/shikijs/shiki), with additional features like line-highlighting:
|
8
|
+
|
9
|
+
**Input**
|
10
|
+
|
11
|
+
````
|
12
|
+
```js{4}
|
13
|
+
export default {
|
14
|
+
data () {
|
15
|
+
return {
|
16
|
+
msg: 'Highlighted!'
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}
|
20
|
+
```
|
21
|
+
````
|
22
|
+
|
23
|
+
**Output**
|
24
|
+
|
25
|
+
```js{4}
|
26
|
+
export default {
|
27
|
+
data () {
|
28
|
+
return {
|
29
|
+
msg: 'Highlighted!'
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
```
|
34
|
+
|
35
|
+
## Custom Containers
|
36
|
+
|
37
|
+
**Input**
|
38
|
+
|
39
|
+
```md
|
40
|
+
::: info
|
41
|
+
This is an info box.
|
42
|
+
:::
|
43
|
+
|
44
|
+
::: tip
|
45
|
+
This is a tip.
|
46
|
+
:::
|
47
|
+
|
48
|
+
::: warning
|
49
|
+
This is a warning.
|
50
|
+
:::
|
51
|
+
|
52
|
+
::: danger
|
53
|
+
This is a dangerous warning.
|
54
|
+
:::
|
55
|
+
|
56
|
+
::: details
|
57
|
+
This is a details block.
|
58
|
+
:::
|
59
|
+
```
|
60
|
+
|
61
|
+
**Output**
|
62
|
+
|
63
|
+
::: info
|
64
|
+
This is an info box.
|
65
|
+
:::
|
66
|
+
|
67
|
+
::: tip
|
68
|
+
This is a tip.
|
69
|
+
:::
|
70
|
+
|
71
|
+
::: warning
|
72
|
+
This is a warning.
|
73
|
+
:::
|
74
|
+
|
75
|
+
::: danger
|
76
|
+
This is a dangerous warning.
|
77
|
+
:::
|
78
|
+
|
79
|
+
::: details
|
80
|
+
This is a details block.
|
81
|
+
:::
|
82
|
+
|
83
|
+
## More
|
84
|
+
|
85
|
+
Check out the documentation for the [full list of markdown extensions](https://vitepress.dev/guide/markdown).
|
data/docs/package.json
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Connecting to a Relay
|
2
|
+
|
3
|
+
You must connect your nostr [Client](../core/client) to a relay in order to send and receive [Events](../events).
|
4
|
+
Instantiate a [`Nostr::Client`](https://www.rubydoc.info/gems/nostr/Nostr/Client) and a
|
5
|
+
[`Nostr::Relay`](https://www.rubydoc.info/gems/nostr/Nostr/Relay) giving it the `url` of your relay. The `name`
|
6
|
+
attribute is just descriptive.
|
7
|
+
Calling [`Client#connect`](https://www.rubydoc.info/gems/nostr/Nostr/Client#connect-instance_method) attempts to
|
8
|
+
establish a WebSocket connection between the Client and the Relay.
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
client = Nostr::Client.new
|
12
|
+
relay = Nostr::Relay.new(url: 'wss://relay.damus.io', name: 'Damus')
|
13
|
+
|
14
|
+
# Listen for the connect event
|
15
|
+
client.on :connect do
|
16
|
+
# When this block executes, you're connected to the relay
|
17
|
+
end
|
18
|
+
|
19
|
+
# Connect to a relay asynchronously
|
20
|
+
client.connect(relay)
|
21
|
+
```
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Publishing events
|
2
|
+
|
3
|
+
Create a [signed event](../core/keys) and call the method
|
4
|
+
[`Nostr::Client#publish`](https://www.rubydoc.info/gems/nostr/Nostr/Client#publish-instance_method) to send the
|
5
|
+
event to the relay.
|
6
|
+
|
7
|
+
```ruby{4-8,17}
|
8
|
+
# Create a user with the keypair
|
9
|
+
user = Nostr::User.new(keypair: keypair)
|
10
|
+
|
11
|
+
# Create a signed event
|
12
|
+
text_note_event = user.create_event(
|
13
|
+
kind: Nostr::EventKind::TEXT_NOTE,
|
14
|
+
content: 'Your feedback is appreciated, now pay $8'
|
15
|
+
)
|
16
|
+
|
17
|
+
# Connect asynchronously to a relay
|
18
|
+
relay = Nostr::Relay.new(url: 'wss://nostr.wine', name: 'Wine')
|
19
|
+
client.connect(relay)
|
20
|
+
|
21
|
+
# Listen asynchronously for the connect event
|
22
|
+
client.on :connect do
|
23
|
+
# Send the event to the relay
|
24
|
+
client.publish(text_note_event)
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
The relay will verify the signature of the event with the public key. If the signature is valid, the relay should
|
29
|
+
broadcast the event to all subscribers.
|
@@ -0,0 +1,6 @@
|
|
1
|
+
# Receiving events
|
2
|
+
|
3
|
+
To receive events from Relays, you must create a subscription on the relay. A subscription is a filter that defines the
|
4
|
+
events you want to receive.
|
5
|
+
|
6
|
+
For more information, read the [Subscription](../subscriptions/creating-a-subscription.md) section.
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Creating a subscription
|
2
|
+
|
3
|
+
A client can request events and subscribe to new updates __after__ it has established a connection with the Relay.
|
4
|
+
|
5
|
+
You may use a [`Nostr::Filter`](https://www.rubydoc.info/gems/nostr/Nostr/Filter) instance with as many attributes as
|
6
|
+
you wish:
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
client.on :connect do
|
10
|
+
filter = Nostr::Filter.new(
|
11
|
+
ids: ['8535d5e2d7b9dc07567f676fbe70428133c9884857e1915f5b1cc6514c2fdff8'],
|
12
|
+
authors: ['ae00f88a885ce76afad5cbb2459ef0dcf0df0907adc6e4dac16e1bfbd7074577'],
|
13
|
+
kinds: [Nostr::EventKind::TEXT_NOTE],
|
14
|
+
e: ["f111593a72cc52a7f0978de5ecf29b4653d0cf539f1fa50d2168fc1dc8280e52"],
|
15
|
+
p: ["f1f9b0996d4ff1bf75e79e4cc8577c89eb633e68415c7faf74cf17a07bf80bd8"],
|
16
|
+
since: 1230981305,
|
17
|
+
until: 1292190341,
|
18
|
+
limit: 420,
|
19
|
+
)
|
20
|
+
|
21
|
+
subscription = client.subscribe(subscription_id: 'an-id', filter: filter)
|
22
|
+
end
|
23
|
+
```
|
24
|
+
|
25
|
+
With just a few:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
client.on :connect do
|
29
|
+
filter = Nostr::Filter.new(kinds: [Nostr::EventKind::TEXT_NOTE])
|
30
|
+
subscription = client.subscribe(subscription_id: 'an-id', filter: filter)
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
Or omit the filter:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
client.on :connect do
|
38
|
+
subscription = client.subscribe(subscription_id: 'an-id')
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
Or even omit the subscription id:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
client.on :connect do
|
46
|
+
subscription = client.subscribe(filter: filter)
|
47
|
+
subscription.id # => "13736f08dee8d7b697222ba605c6fab2" (randomly generated)
|
48
|
+
end
|
49
|
+
```
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# Stop previous subscriptions
|
2
|
+
|
3
|
+
You can stop receiving messages from a subscription by calling
|
4
|
+
[`Nostr::Client#unsubscribe`](https://www.rubydoc.info/gems/nostr/Nostr/Client#unsubscribe-instance_method) with the
|
5
|
+
ID of the subscription you want to stop receiving messages from:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
client.unsubscribe('your-subscription-id')
|
9
|
+
client.unsubscribe(subscription.id)
|
10
|
+
```
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# Filtering events
|
2
|
+
|
3
|
+
## Filtering by id
|
4
|
+
|
5
|
+
You can filter events by their ids:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
filter = Nostr::Filter.new(
|
9
|
+
ids: [
|
10
|
+
# matches events with these exact IDs
|
11
|
+
'8535d5e2d7b9dc07567f676fbe70428133c9884857e1915f5b1cc6514c2fdff8',
|
12
|
+
'461544014d87c9eaf3e76e021240007dff2c7afb356319f99c741b45749bf82f',
|
13
|
+
]
|
14
|
+
)
|
15
|
+
subscription = client.subscribe(filter: filter)
|
16
|
+
```
|
17
|
+
|
18
|
+
## Filtering by author
|
19
|
+
|
20
|
+
You can filter events by their author's pubkey:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
filter = Nostr::Filter.new(
|
24
|
+
authors: [
|
25
|
+
# matches events whose (authors) pubkey match these exact IDs
|
26
|
+
'b698043170d580f8ae5bad4ac80b1fdb508e957f0bbffe97f2a8915fa8b34070',
|
27
|
+
'51f853ff4894b062950e46ebed8c1c7015160f8173994414a96dd286f65f0f49',
|
28
|
+
]
|
29
|
+
)
|
30
|
+
subscription = client.subscribe(filter: filter)
|
31
|
+
```
|
32
|
+
|
33
|
+
## Filtering by kind
|
34
|
+
|
35
|
+
You can filter events by their kind:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
filter = Nostr::Filter.new(
|
39
|
+
kinds: [
|
40
|
+
# matches events whose kind is TEXT_NOTE
|
41
|
+
Nostr::EventKind::TEXT_NOTE,
|
42
|
+
# and matches events whose kind is CONTACT_LIST
|
43
|
+
Nostr::EventKind::CONTACT_LIST,
|
44
|
+
]
|
45
|
+
)
|
46
|
+
subscription = client.subscribe(filter: filter)
|
47
|
+
```
|
48
|
+
|
49
|
+
## Filtering by referenced event
|
50
|
+
|
51
|
+
You can filter events by the events they reference (in their `e` tag):
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
filter = Nostr::Filter.new(
|
55
|
+
e: [
|
56
|
+
# matches events that reference other events whose ids match these exact IDs
|
57
|
+
'f111593a72cc52a7f0978de5ecf29b4653d0cf539f1fa50d2168fc1dc8280e52',
|
58
|
+
'f1f9b0996d4ff1bf75e79e4cc8577c89eb633e68415c7faf74cf17a07bf80bd8',
|
59
|
+
]
|
60
|
+
)
|
61
|
+
subscription = client.subscribe(filter: filter)
|
62
|
+
```
|
63
|
+
|
64
|
+
## Filtering by referenced pubkey
|
65
|
+
|
66
|
+
You can filter events by the pubkeys they reference (in their `p` tag):
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
filter = Nostr::Filter.new(
|
70
|
+
p: [
|
71
|
+
# matches events that reference other pubkeys that match these exact IDs
|
72
|
+
'b698043170d580f8ae5bad4ac80b1fdb508e957f0bbffe97f2a8915fa8b34070',
|
73
|
+
'51f853ff4894b062950e46ebed8c1c7015160f8173994414a96dd286f65f0f49',
|
74
|
+
]
|
75
|
+
)
|
76
|
+
subscription = client.subscribe(filter: filter)
|
77
|
+
```
|
78
|
+
|
79
|
+
## Filtering by timestamp
|
80
|
+
|
81
|
+
You can filter events by their timestamp:
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
filter = Nostr::Filter.new(
|
85
|
+
since: 1230981305, # matches events that are newer than this timestamp
|
86
|
+
until: 1292190341, # matches events that are older than this timestamp
|
87
|
+
)
|
88
|
+
subscription = client.subscribe(filter: filter)
|
89
|
+
```
|
90
|
+
|
91
|
+
## Limiting the number of events
|
92
|
+
|
93
|
+
You can limit the number of events received:
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
filter = Nostr::Filter.new(
|
97
|
+
limit: 420, # matches at most 420 events
|
98
|
+
)
|
99
|
+
subscription = client.subscribe(filter: filter)
|
100
|
+
```
|
101
|
+
|
102
|
+
## Combining filters
|
103
|
+
|
104
|
+
You can combine filters. For example, to match `5` text note events that are newer than `1230981305` from the author
|
105
|
+
`ae00f88a885ce76afad5cbb2459ef0dcf0df0907adc6e4dac16e1bfbd7074577`:
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
filter = Nostr::Filter.new(
|
109
|
+
authors: ['ae00f88a885ce76afad5cbb2459ef0dcf0df0907adc6e4dac16e1bfbd7074577'],
|
110
|
+
kinds: [Nostr::EventKind::TEXT_NOTE],
|
111
|
+
since: 1230981305,
|
112
|
+
limit: 5,
|
113
|
+
)
|
114
|
+
subscription = client.subscribe(filter: filter)
|
115
|
+
```
|