urbit-api 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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