nostr 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.editorconfig +1 -1
- data/.rubocop.yml +26 -0
- data/.tool-versions +2 -1
- data/CHANGELOG.md +65 -1
- data/README.md +96 -183
- data/Steepfile +2 -0
- 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 +147 -0
- 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 +157 -12
- data/lib/nostr/event_kind.rb +8 -0
- data/lib/nostr/events/encrypted_direct_message.rb +54 -0
- 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 -36
- data/lib/nostr/version.rb +1 -1
- data/lib/nostr.rb +8 -1
- data/nostr.gemspec +9 -9
- data/sig/nostr/bech32.rbs +14 -0
- data/sig/nostr/client.rbs +5 -5
- data/sig/nostr/crypto.rbs +16 -0
- 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 +24 -9
- data/sig/nostr/event_kind.rbs +1 -0
- data/sig/nostr/events/encrypted_direct_message.rbs +12 -0
- 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 -10
- 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 +83 -23
- data/lib/nostr/event_fragment.rb +0 -111
- data/sig/nostr/event_fragment.rbs +0 -12
@@ -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
|
+
```
|