urbit-api 0.1.2 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8ffd645b7c5236244e5c081587835863586b11d035d3197e7e286fa223bc3c0f
4
- data.tar.gz: 19e8360fbdf96a1149a99dc7218bd835ac3af5338f5ff0b0cfc0c907ea383f27
3
+ metadata.gz: 0a3c9e5915684d444baa066c316ebeafd2cddc0aa731d323b15fec95be932b05
4
+ data.tar.gz: 951ddb43e002c92c0490b549de64a2311b42124c09cb499833d58d7c717b088d
5
5
  SHA512:
6
- metadata.gz: 84a0d8b5144e08a43080f3d4b0caaecba73e9fd5a74f2d5f1c04f66f1577dc64ebdf44e2fb91716c2ce746b4c96062e0615a24c5a54d760fd1a0ae9ec8b9af36
7
- data.tar.gz: 41e5ffab8a9b67bce7c1373ee932ab17834e5684da3de41bb6bc19fa44b115e0fea4472e78e672b4ddd7c74c4e970ba0a20cf9123f27db1d5b763d67ca1f2185
6
+ metadata.gz: a677021940189cf5e52a969b01d4f77b418dc544d823b47d1dfaf83832c44f00dbe926692d9957f3a01809a8fdda15ba65177b5a57ecb01f310ec800e09d6e75
7
+ data.tar.gz: d10188333e23d83a6abee0a44250bdce9641694264fc81970b5de285a973156f00b7b5a342b88e3b4d476d8a363e350012aabcf727cc940b9a2f0fc50ce59918
data/README.md CHANGED
@@ -29,85 +29,44 @@ Or install it yourself as:
29
29
  # This will instantiate a ship that connects to the fake `~zod` dev server by default
30
30
  # See Urbit docs for more info: https://urbit.org/using/develop/
31
31
  [1] pry(main)> ship = Urbit.new
32
- # => #<Urbit::Ship:0x00007fa74b87f920 ...
32
+ => #<Urbit::Ship:0x00007fa74b87f920 ...
33
33
 
34
34
  OR... with config file...
35
35
  > ship = Urbit.connect(config_file: '_config-barsyr-latreb.yml')
36
36
 
37
37
  > ship.logged_in?
38
- # => false
38
+ => false
39
39
 
40
40
  > ship.login
41
- # => #<Urbit::Ship:0x00007fa74b87f920 ...
41
+ => #<Urbit::Ship:0x00007fa74b87f920 ...
42
42
 
43
43
  > ship.logged_in?
44
- # => true
44
+ => true
45
45
 
46
46
  > ship.to_s
47
- # => "a Ship(name: '~barsyr-latreb', host: 'http://localhost', port: '8080')"
47
+ => "a Ship(name: '~barsyr-latreb', host: 'http://localhost', port: '8080')"
48
48
 
49
- > receiver = ship.subscribe('graph-store', '/updates')
50
- # => #<Urbit::Receiver:0x00007fd3928eba58
49
+ > channel = ship.subscribe(app: 'graph-store', path: '/updates')
50
+ => a Channel (Open) on ~barsyr-latreb(name: 'Channel-0', key: '1622836437b540b4')
51
51
 
52
52
  # Subscribing works by opening a Channel. Your ships has a collection of all it's open Channels.
53
53
  > channel = ship.open_channels.first
54
- # => #<Urbit::Channel:0x00007fa74b291e50 ...
54
+ => a Channel (Open) on ~barsyr-latreb(name: 'Channel-0', key: '1622836437b540b4')
55
+
56
+ # Notice that it's the same one.
55
57
 
56
58
  # Every Channel has a unique key to identify it.
57
59
  > channel.key
58
- # => "16142890875c348d"
60
+ => "16142890875c348d"
59
61
 
60
- # The receiver will now be listening on the app and path you specified. Each time an event is sent in it will be stored in the receiver's facts collection.
61
- > receiver.facts.count
62
+ # The Channel has a Receiver that will now be listening on the app and path you specified. Each time an event is sent in it will be stored in the receiver's facts collection.
63
+ > channel.receiver.facts.count
62
64
  => 12
63
65
 
64
- > receiver.facts.last
65
- => {:message=>
66
- {"json"=>
67
- {"graph-update"=>
68
- {"add-nodes"=>
69
- {"resource"=>{"name"=>"test0-996", "ship"=>"barsyr-latreb"},
70
- "nodes"=>
71
- {"/170141184504954066298369929365830487769"=>
72
- {"post"=>
73
- {"index"=>"/170141184504954066298369929365830487769",
74
- "author"=>"barsyr-latreb",
75
- "time-sent"=>1615564146267,
76
- "signatures"=>[],
77
- "contents"=>[],
78
- "hash"=>"0x92b0.c976.58f0.3035.c126.64a0.3043.b962"},
79
- "children"=>
80
- {"2"=>
81
- {"post"=>
82
- {"index"=>"/170141184504954066298369929365830487769/2",
83
- "author"=>"barsyr-latreb",
84
- "time-sent"=>1615564146267,
85
- "signatures"=>[],
86
- "contents"=>[],
87
- "hash"=>"0x2ffe.3ca7.20eb.11af.51f8.fbab.2b88.9f48"},
88
- "children"=>nil},
89
- "1"=>
90
- {"post"=>
91
- {"index"=>"/170141184504954066298369929365830487769/1",
92
- "author"=>"barsyr-latreb",
93
- "time-sent"=>1615564146267,
94
- "signatures"=>[],
95
- "contents"=>[],
96
- "hash"=>"0x2ffe.3ca7.20eb.11af.51f8.fbab.2b88.9f48"},
97
- "children"=>
98
- {"1"=>
99
- {"post"=>
100
- {"index"=>"/170141184504954066298369929365830487769/1/1",
101
- "author"=>"barsyr-latreb",
102
- "time-sent"=>1615564146267,
103
- "signatures"=>[],
104
- "contents"=>[{"text"=>"Test 0.8"}, {"text"=>"Test 0.8"}],
105
- "hash"=>"0x9516.25fc.ca7a.5bb9.356b.2fce.b29a.f372"},
106
- "children"=>nil}}}}}}}}},
107
- "id"=>2,
108
- "response"=>"diff"
109
- }
110
- }
66
+ # Perform any action through landscape that would initiate an update into %graph-store...
67
+ # In this case I have added a comment to a local notebook.
68
+ > channel.receiver.facts.last
69
+ => a Fact({:ship=>{:name=>"~barsyr-latreb", :host=>"http://localhost", :port=>"8080"}, :resource=>"~barsyr-latreb/test0-996", :acknowleged=>true, :is_graph_update=>true})
111
70
 
112
71
  # Your ship keeps a collection of all the messages sent to urbit:
113
72
  > channel.sent_messages.collect {|m| m.to_s}
@@ -119,10 +78,112 @@ OR... with config file...
119
78
  "a Message({"id"=>5, "action"=>"ack", "event-id"=>"2"})"
120
79
  ]
121
80
 
81
+ #
82
+ # --------------------------------------------------------------------
83
+ # Poke
84
+ # --------------------------------------------------------------------
85
+ #
86
+ > ship.poke(app: 'hood', mark: 'helm-hi', message: 'Opening Airlock')
87
+ => a Channel (Open) on ~barsyr-latreb(name: 'Channel-0', key: '1630355920a717e1')
88
+
89
+ #
90
+ # --------------------------------------------------------------------
91
+ # Scry
92
+ # --------------------------------------------------------------------
93
+ #
122
94
  # Retrieving your ship's base hash using scry....
123
- > ship.scry('file-server', '/clay/base/hash', 'json')
95
+ > ship.scry(app: 'file-server', path: '/clay/base/hash')
96
+ # => {:status=>200, :code=>"ok", :body=>"\"e75k5\""}
97
+
98
+ #
99
+ # --------------------------------------------------------------------
100
+ # Spider
101
+ # --------------------------------------------------------------------
102
+ #
103
+ # Creating a new Notebook in "My Channels" using %spider....
104
+ > create_json = %Q(
105
+ {"create": {"resource": { "ship": "~zod", "name": "random_name"},
106
+ "title": "Testing",
107
+ "description": "Testing Un-Managed Graph Creation",
108
+ "associated" : {"policy": {"invite": {"pending": []}}},
109
+ "module": "publish", "mark": "graph-validator-publish"}}
110
+ )
111
+ > ship.spider(mark_in: 'graph-view-action', mark_out: 'json', thread: 'graph-create', data: create_json)
124
112
  # => {:status=>200, :code=>"ok", :body=>"\"e75k5\""}
125
113
 
114
+ #
115
+ # --------------------------------------------------------------------
116
+ # %graph-store
117
+ # --------------------------------------------------------------------
118
+ #
119
+ > puts ship.graph_names
120
+ ~barsyr-latreb/dm-inbox
121
+ ~darlur/announce
122
+ ~bitbet-bolbel/urbit-community-5.963
123
+ ~winter-paches/top-shelf-6391
124
+ ~winter-paches/the-great-north-7.579
125
+ ~barsyr-latreb/test0-996
126
+ ~fabled-faster/test-chat-a-5919
127
+ ~barsyr-latreb/test1-4287
128
+ ~darrux-landes/welcome-to-urbit-community
129
+ ~millyt-dorsen/finance-2.962
130
+ ~fabled-faster/interface-testing-facility-683
131
+ ~darlur/help-desk-4556
132
+ =>
133
+
134
+ # Reference a graph by name and return a single node.
135
+ > puts ship.graph(resource: '~winter-paches/top-shelf-6391').node(index: "170.141.184.505.207.751.870.046.689.877.378.990.080")
136
+ a Node({:index=>"170.141.184.505.207.751.870.046.689.877.378.990.080", :author=>"witfyl-ravped", :contents=>[{"text"=>"the patches don't really bother me though tbh"}], :time_sent=>1629316468195, :is_parent=>false, :child_count=>0})
137
+ =>
138
+
139
+ # You can also reference a graph by its index in the graphs collection.
140
+ > puts ship.graphs[3].node(index: "170.141.184.505.207.751.870.046.689.877.378.990.080")
141
+ a Node({:index=>"170.141.184.505.207.751.870.046.689.877.378.990.080", :author=>"witfyl-ravped", :contents=>[{"text"=>"the patches don't really bother me though tbh"}], :time_sent=>1629316468195, :is_parent=>false, :child_count=>0})
142
+ =>
143
+
144
+ # Return the contents of the 5 oldest nodes of a graph
145
+ > graph = ship.graph(resource: '~winter-paches/top-shelf-6391')
146
+ > graph.oldest_nodes(count: 5).sort.each {|n| p n.contents};nil
147
+ [{"text"=>"watching the 2020 stanley cup finals (tampa (sigh) just went up 2-0 in game 3) and i thought: \"the great north has to have a hockey chat, eh?\""}]
148
+ [{"text"=>"we'll see if this has legs. ;)"}]
149
+ [{"text"=>"shortie! now 2-1 tampa."}]
150
+ [{"text"=>"looks like tampa's going to go up 2-1. as a canadian this geographically depresses me. :/"}]
151
+ [{"text"=>"anyone in the stands?"}]
152
+ =>
153
+
154
+ # A single Node. In this case, the 3rd oldest node in the graph.
155
+ > puts graph.nodes[2].contents
156
+ {"text"=>"shortie! now 2-1 tampa."}
157
+ =>
158
+
159
+ # Getting the next newer Node. Remember that it always returns an Array, hence the '#first'.
160
+ > puts graph.nodes[2].next.first.contents
161
+ {"text"=>"looks like tampa's going to go up 2-1. as a canadian this geographically depresses me. :/"}
162
+ =>
163
+
164
+ # Return the indexes of the newest 5 nodes of a graph
165
+ > ship.graph(resource: '~winter-paches/top-shelf-6391').newest_nodes(count: 5).sort.each {|n| p n.index};nil
166
+ "170.141.184.505.209.257.330.601.508.862.548.770.816"
167
+ "170.141.184.505.209.375.247.350.471.711.992.578.048"
168
+ "170.141.184.505.209.545.972.004.310.065.795.301.376"
169
+ "170.141.184.505.209.627.337.970.761.265.544.429.568"
170
+ "170.141.184.505.209.644.102.846.398.558.514.446.336"
171
+ =>
172
+
173
+ # Fetching nodes older relative to another node. (See indexes above)
174
+ > puts (node = ship.graph(resource: '~winter-paches/top-shelf-6391').node(index: "170.141.184.505.209.644.102.846.398.558.514.446.336"))
175
+ a Node({:index=>"170.141.184.505.209.644.102.846.398.558.514.446.336", :author=>"winter-paches", :contents=>[{"text"=>"yep. that's how i did it as a kid. harry caray was the white sox announcer before he turned traitor and went to the cubs."}], :time_sent=>1629419046028, :is_parent=>false, :child_count=>0})
176
+ =>
177
+
178
+ > puts node.previous
179
+ a Node({:index=>"170.141.184.505.209.627.337.970.761.265.544.429.568", :author=>"pathus-hiddyn", :contents=>[{"text"=>"Lol oh man I haven’t listened to a baseball game on the radio in forever. It is great isn’t it. "}], :time_sent=>1629418137668, :is_parent=>false, :child_count=>0})
180
+ =>
181
+
182
+ > node.previous(count: 4).each {|n| p n.index};nil
183
+ "170.141.184.505.209.257.330.601.508.862.548.770.816"
184
+ "170.141.184.505.209.375.247.350.471.711.992.578.048"
185
+ "170.141.184.505.209.545.972.004.310.065.795.301.376"
186
+ "170.141.184.505.209.627.337.970.761.265.544.429.568"
126
187
  ```
127
188
  ### Configuration
128
189
 
@@ -153,11 +214,10 @@ ship = Urbit.new(host: '127.0.0.1', port: '8080')
153
214
  ```sh
154
215
  bin/test
155
216
  ```
156
- ### ~zod
157
-
158
217
  Tests assume that an instance of a ["fake" development Urbit ship](https://urbit.org/using/develop/) (one not connected to the live network) will be running, available at `http://localhost:8080`.
218
+ ### "fake" ~zod
159
219
 
160
- To create a development ship:
220
+ To create this development ship:
161
221
  ```sh
162
222
  ./urbit -F zod
163
223
  ```
@@ -165,7 +225,7 @@ To create a development ship:
165
225
 
166
226
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
167
227
 
168
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
228
+ To install this gem onto your local machine, run `bundle exec rake install`.
169
229
 
170
230
  ## Contributing
171
231
 
data/bin/console CHANGED
@@ -4,8 +4,11 @@ require "bundler/setup"
4
4
  require "pry"
5
5
  require "urbit/urbit"
6
6
 
7
- # You can add fixtures and/or initialization code here to make experimenting
8
- # with your gem easier. You can also use a different console, if you like.
9
-
7
+ puts "Welcome! This is an interactive environment to explore your Urbit ship."
8
+ puts "You create a config file with connection details for your ship and off you go."
9
+ puts ""
10
10
  puts "e.g., ship = Urbit.new(config_file: 'my_config.yml')"
11
+ puts "=> a Ship(name: '~barsyr-latreb', host: 'http://localhost', port: '8080')"
12
+
13
+ Pry.config.print = proc { |output, value| output.puts "=> #{value}" }
11
14
  Pry.start
@@ -2,14 +2,22 @@ module Urbit
2
2
  class AckMessage < Message
3
3
  attr_reader :ack_id
4
4
 
5
- def initialize(channel, sse_message_id)
6
- super(channel, 'ack')
5
+ def initialize(channel:, sse_message_id:)
6
+ super(channel: channel)
7
7
  @ack_id = sse_message_id
8
8
  end
9
9
 
10
+ def action
11
+ "ack"
12
+ end
13
+
10
14
  def to_h
11
15
  # Need to use the older hash style due to the key having a dash.
12
16
  {'id' => self.id, 'action' => self.action, 'event-id' => self.ack_id}
13
17
  end
18
+
19
+ def to_s
20
+ "an AckMessage(#{self.to_h})"
21
+ end
14
22
  end
15
23
  end
@@ -1,5 +1,5 @@
1
1
  module Urbit
2
2
  module Api
3
- VERSION = "0.1.2"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
data/lib/urbit/channel.rb CHANGED
@@ -9,48 +9,50 @@ require 'urbit/subscribe_message'
9
9
  module Urbit
10
10
  class Channel
11
11
  attr_accessor :messages
12
- attr_reader :key, :name, :ship
12
+ attr_reader :key, :name, :receiver, :ship
13
13
 
14
- def initialize(ship, name)
14
+ def initialize(ship:, name:)
15
15
  @ship = ship
16
16
  @key = "#{Time.now.to_i}#{SecureRandom.hex(3)}"
17
17
  @messages = []
18
18
  @name = name
19
+ @receiver = nil
19
20
  @is_open = false
20
- @is_subscribed = false
21
21
  end
22
22
 
23
23
  def close
24
24
  # puts "closing #{name}"
25
- m = Urbit::CloseMessage.new(self)
26
- @is_open = !self.send_message(m)
25
+ m = Urbit::CloseMessage.new(channel: self)
26
+ @is_open = !self.send(message: m)
27
27
  end
28
28
 
29
29
  def closed?
30
30
  !@is_open
31
31
  end
32
32
 
33
- #
34
- # We open a channel by "poking" the urbit app 'hood' using the mark 'helm-hi'
35
- #
36
- def open(a_message_string)
37
- m = Urbit::PokeMessage.new(self, "hood", "helm-hi", a_message_string)
38
- @is_open = self.send_message(m)
39
- end
40
-
41
33
  def open?
42
34
  @is_open
43
35
  end
44
36
 
45
- def queue_message(a_message)
46
- a_message.id = self.sent_messages.size + 1
47
- @messages << a_message
37
+ #
38
+ # One way to open a channel by "poking" an urbit app with a mark and a (json) message.
39
+ # A typical example of this is poking the 'hood' app using the mark 'helm-hi' to start a DM chat.
40
+ #
41
+ def poke(app:, mark:, message:)
42
+ @is_open = self.send(message: (Urbit::PokeMessage.new(channel: self, app: app, mark: mark, a_string: message)))
43
+ @receiver = Urbit::Receiver.new(channel: self)
44
+ self
45
+ end
46
+
47
+ def queue(message:)
48
+ message.id = self.sent_messages.size + 1
49
+ @messages << message
48
50
  end
49
51
 
50
52
  # Answers true if message was successfully sent.
51
- def send_message(a_message)
52
- self.queue_message(a_message)
53
- resp = a_message.transmit
53
+ def send(message:)
54
+ self.queue(message: message)
55
+ resp = message.transmit
54
56
  resp.reason_phrase == "ok"
55
57
  end
56
58
 
@@ -66,14 +68,15 @@ module Urbit
66
68
  # Subscribe to an app at a path.
67
69
  # Returns a Receiver which will begin to get back a stream of facts... which is a... Dictionary? Encyclopedia?
68
70
  #
69
- def subscribe(app, path)
70
- m = Urbit::SubscribeMessage.new(self, app, path)
71
- @is_subscribed = self.send_message(m)
72
- receiver = Urbit::Receiver.new(self)
71
+ def subscribe(app:, path:)
72
+ m = Urbit::SubscribeMessage.new(channel: self, app: app, path: path)
73
+ @is_open = self.send(message: m)
74
+ @receiver = Urbit::Receiver.new(channel: self)
75
+ self
73
76
  end
74
77
 
75
78
  def subscribed?
76
- @is_subscribed
79
+ @is_open
77
80
  end
78
81
 
79
82
  def to_s
@@ -0,0 +1,22 @@
1
+ require 'securerandom'
2
+
3
+ require 'urbit/message'
4
+ require 'urbit/receiver'
5
+ require 'urbit/close_message'
6
+ require 'urbit/poke_message'
7
+ require 'urbit/subscribe_message'
8
+
9
+ module Urbit
10
+ class ChatChannel < Channel
11
+ # def messages
12
+ # self.fetch_all_nodes if @nodes.empty?
13
+ # @nodes
14
+ # end
15
+
16
+ # def newest_messages(count = 100)
17
+ # self.fetch_newest_nodes(count) if @nodes.empty?
18
+ # self.nodes
19
+ # end
20
+
21
+ end
22
+ end
@@ -1,7 +1,11 @@
1
1
  module Urbit
2
2
  class CloseMessage < Message
3
- def initialize(channel)
4
- super(channel, 'delete')
3
+ def initialize(channel:)
4
+ super(channel: channel)
5
+ end
6
+
7
+ def action
8
+ "delete"
5
9
  end
6
10
 
7
11
  def to_h
data/lib/urbit/fact.rb ADDED
@@ -0,0 +1,66 @@
1
+ require 'urbit/graph'
2
+ require 'urbit/node'
3
+ require 'urbit/parser'
4
+
5
+ module Urbit
6
+ class Fact
7
+ attr_reader :ack
8
+
9
+ def initialize(channel:, event:)
10
+ @channel = channel
11
+ @data = event.data
12
+ @type = event.type
13
+
14
+ # Attach this new fact as a node to its Graph.
15
+ if self.graph_update?
16
+ puts self.add_nodes_json
17
+ Urbit::AddNodesParser.new(for_graph: (self.ship.graph(resource: self.resource)), with_json: self.add_nodes_json).add_nodes
18
+ end
19
+ end
20
+
21
+ def add_ack(ack:)
22
+ @ack = :ack
23
+ end
24
+
25
+ def add_nodes_json
26
+ return nil unless self.graph_update?
27
+ self.contents["json"]["graph-update"]["add-nodes"]
28
+ end
29
+
30
+ def contents
31
+ JSON.parse(@data)
32
+ end
33
+
34
+ def graph_update?
35
+ !self.contents["json"].nil? && !self.contents["json"]["graph-update"].nil?
36
+ end
37
+
38
+ def is_acknowledged?
39
+ !@ack.nil?
40
+ end
41
+
42
+ def resource
43
+ return nil unless self.graph_update?
44
+ r = self.contents["json"]["graph-update"]["add-nodes"]["resource"]
45
+ "~#{r["ship"]}/#{r["name"]}"
46
+ end
47
+
48
+ def ship
49
+ @channel.ship
50
+ end
51
+
52
+ def to_h
53
+ {
54
+ ship: self.ship.to_h,
55
+ resource: self.resource,
56
+ acknowleged: self.is_acknowledged?,
57
+ is_graph_update: self.graph_update?
58
+ # contents: self.contents
59
+ }
60
+ end
61
+
62
+ def to_s
63
+ "a Fact(#{self.to_h})"
64
+ end
65
+ end
66
+ end