urbit-api 0.4.0 → 0.6.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: d45d05923c175955a85dfb0676a63eafc0eed277b656b7d045f8675f586cee7e
4
- data.tar.gz: e2bc0d8d71d02629b9b3f335ff1672f20686c178e1584540ff1724943d82158c
3
+ metadata.gz: b57a15f5dfda9e19e863a4fb4760279b98c9d2af55f9865a470be3f6cb23520a
4
+ data.tar.gz: a5442c3e68b634372791bd4ecee3a8a84de201dbe708d94709ddff7fdf20827e
5
5
  SHA512:
6
- metadata.gz: 86e48b8bae4f5cedfbe9ca0fcb4ac327185973ce73e29c8a26f7644fadb2e8f78850b9f1cca9d62802d22c45afdeb025b8d495e14d54bf642f123f66f986a1c5
7
- data.tar.gz: 20968fc224c1e4fd6105922a4ddc30b16f45f25a12f2c5e4294eaec33f7d379db8180720b062a3d274755853468c7e61af823401ec2a4f5b3e800be3f1de497f
6
+ metadata.gz: 3e1f0ba98b3ad9cfea824c2b48da18a0123d1a83df844809dcde1bda5e301871477f6c30064e47351c3a0302402482886d709324409e74420078b8c98ecb5e73
7
+ data.tar.gz: 49077ec0705dcbecbe1f758911d982e0101f20c07e2d3638bb99729e57dcbc9e331ee048dcd255f1f729cc1ab6129043a0b79dd1269c350924c3b86a95b8508c
@@ -9,8 +9,6 @@ module Urbit
9
9
  @channel = channel
10
10
  @data = event.data
11
11
  @type = event.type
12
- # TODO: Remove this debugging once Facts are finalized. DJR 2/3/2022
13
- # puts "Received a #{self.class.name.split('::').last} for [#{channel}] -- [#{@type}] -- [#{@data}]"
14
12
  end
15
13
 
16
14
  def add_ack(ack:)
@@ -11,9 +11,7 @@ module Urbit
11
11
  # Attach this new fact as a node to its Graph.
12
12
  #
13
13
  def attach_parser
14
- # puts "Received a graph update for [#{self.ship.graph(resource: self.resource)}]"
15
14
  if self.incoming_graph
16
- # puts "Received an add_graph event: #{self.raw_json} on #{self.resource}"
17
15
  self.create_parser
18
16
  end
19
17
  end
@@ -49,7 +47,7 @@ module Urbit
49
47
  end
50
48
 
51
49
  def create_parser
52
- Urbit::AddGraphParser.new(for_graph: incoming_graph, with_json: self.raw_json).add_nodes
50
+ Urbit::AddGraphParser.new(for_graph: self.incoming_graph, with_json: self.raw_json).add_nodes
53
51
  end
54
52
 
55
53
  def raw_json
@@ -63,7 +61,7 @@ module Urbit
63
61
  end
64
62
 
65
63
  def create_parser
66
- Urbit::AddNodesParser.new(for_graph: incoming_graph, with_json: self.raw_json).add_nodes
64
+ Urbit::AddNodesParser.new(for_graph: self.incoming_graph, with_json: self.raw_json).add_nodes
67
65
  end
68
66
 
69
67
  def raw_json
@@ -77,7 +75,7 @@ module Urbit
77
75
  end
78
76
 
79
77
  def create_parser
80
- Urbit::RemoveGraphParser.new(for_graph: incoming_graph, with_json: self.raw_json)
78
+ Urbit::RemoveGraphParser.new(for_graph: self.incoming_graph, with_json: self.raw_json)
81
79
  end
82
80
 
83
81
  def raw_json
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../link.rb'
4
+
5
+ module Urbit
6
+ module Fact
7
+ class MetadataUpdateFact < BaseFact
8
+ def initialize(channel:, event:)
9
+ super channel: channel, event: event
10
+ unless self.is_remove
11
+ self.accept if self.for_this_ship?
12
+ end
13
+ # TODO: Remove this debugging once Facts are finalized. DJR 2/3/2022
14
+ # puts "Received a #{self.class.name.split('::').last} for [#{channel}] -- [#{@type}] -- [#{@data}]"
15
+ end
16
+
17
+ def accept
18
+ links = self.channel.ship.links
19
+ if self.add_root.nil?
20
+ # This is an new incoming Link, add it. If its a dupe, the Links Set will filter it.
21
+ self.associations.each do |k, v|
22
+ links << Link.new(chain: links, path: k, data: v)
23
+ end
24
+ else
25
+ g = self.add_root["group"]
26
+ links << Link.new(chain: links, path: "#{g}/groups#{g}", data: self.add_root)
27
+ end
28
+ nil
29
+ end
30
+
31
+ def add_root
32
+ self.root_h["add"]
33
+ end
34
+
35
+ def associations
36
+ # An ugly hacks around the fact that when you first join a group there is another
37
+ # useless "initial-update" enclosing hash.
38
+ unless (a = self.root_h["associations"])
39
+ return self.root_h["initial-group"]["associations"]
40
+ end
41
+ a
42
+ end
43
+
44
+ def is_remove
45
+ self.root_h["remove"]
46
+ end
47
+
48
+ def root_h
49
+ self.contents["json"]["metadata-update"]
50
+ end
51
+
52
+ def to_h
53
+ super.merge!(resource: self.resource)
54
+ end
55
+ end
56
+ end
57
+ end
data/lib/urbit/fact.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require_relative 'fact/base_fact'
4
4
  require_relative 'fact/graph_fact'
5
5
  require_relative 'fact/group_fact'
6
+ require_relative 'fact/metadata_fact'
6
7
  require_relative 'fact/settings_fact'
7
8
 
8
9
  module Urbit
@@ -36,6 +37,10 @@ module Urbit
36
37
  return RemoveTagFact.new(channel: channel, event: event) if c["removeTag"]
37
38
  end
38
39
 
40
+ if (c = contents["json"]["metadata-update"])
41
+ return MetadataUpdateFact.new(channel: channel, event: event) if contents["json"]["metadata-update"]
42
+ end
43
+
39
44
  if (c = contents["json"]["settings-event"])
40
45
  return SettingsEventDelBucketFact.new(channel: channel, event: event) if c["del-bucket"]
41
46
  return SettingsEventDelEntryFact.new(channel: channel, event: event) if c["del-entry"]
data/lib/urbit/graph.rb CHANGED
@@ -4,12 +4,13 @@ require 'urbit/parser'
4
4
 
5
5
  module Urbit
6
6
  class Graph
7
- attr_reader :host_ship_name, :name, :ship
7
+ attr_reader :host_ship_name, :name, :ship
8
8
 
9
9
  def initialize(ship:, graph_name:, host_ship_name:)
10
10
  @ship = ship
11
- @name = graph_name
11
+ @group = nil
12
12
  @host_ship_name = host_ship_name
13
+ @name = graph_name
13
14
  @nodes = SortedSet.new
14
15
  end
15
16
 
@@ -17,6 +18,33 @@ module Urbit
17
18
  @nodes << node unless node.deleted?
18
19
  end
19
20
 
21
+ def creator
22
+ self.fetch_link if @creator.nil?
23
+ @creator
24
+ end
25
+
26
+ def delete
27
+ resp = self.ship.spider(mark_in: 'graph-view-action', mark_out: 'json', thread: 'graph-delete', data: self.delete_graph_json, args: ["NO_RESPONSE"])
28
+ @persistent = !(200 == resp[:status])
29
+ end
30
+
31
+ def description
32
+ self.fetch_link if @description.nil?
33
+ @description
34
+ end
35
+
36
+ def group
37
+ if @group.nil?
38
+ @link = self.fetch_link
39
+ @group = @link.group unless @link.nil?
40
+ end
41
+ @group
42
+ end
43
+
44
+ def group=(a_group)
45
+ @group = a_group
46
+ end
47
+
20
48
  def host_ship
21
49
  "~#{@host_ship_name}"
22
50
  end
@@ -29,6 +57,19 @@ module Urbit
29
57
  # r = self.ship.scry(app: 'graph-store', path: "/graph/#{self.to_s}/mark")
30
58
  # end
31
59
 
60
+ #
61
+ # Transform this Graph into a PublishGraph.
62
+ #
63
+ # TODO: This is a very crude way to do this since we don't get the type of graph back from
64
+ # our initial call to retrieve the graphs, only later with the metadata.
65
+ #
66
+ # This will need some more thought.
67
+ #
68
+ def molt
69
+ return PublishGraph.new(ship: self.ship, graph_name: self.name, title: self.title, description: self.description, persistent: true) if 'publish' == self.type
70
+ self
71
+ end
72
+
32
73
  #
33
74
  # Finds a single node in this graph by its index.
34
75
  # The index here should be the atom representation (as returned by Node#index).
@@ -84,18 +125,39 @@ module Urbit
84
125
  self.fetch_sibling_nodes(node, :older, count)[0..(count - 1)]
85
126
  end
86
127
 
128
+ def title
129
+ self.fetch_link if @title.nil?
130
+ @title
131
+ end
132
+
133
+ def type
134
+ self.fetch_link if @type.nil?
135
+ @type
136
+ end
137
+
87
138
  #
88
139
  # the canonical printed representation of a Graph
89
140
  def to_s
90
- "a Graph(#{self.resource})"
141
+ "a #{self.class.name.split('::').last}(#{self.resource})"
91
142
  end
92
143
 
93
144
  private
94
145
 
146
+ def delete_graph_json
147
+ %Q({"delete": {"resource": {"ship": "#{self.ship.name}", "name": "#{self.name}"}}})
148
+ end
149
+
95
150
  def fetch_all_nodes
96
- self.fetch_nodes("#{self.graph_resource}/",
97
- AddGraphParser,
98
- "add-graph")
151
+ self.fetch_nodes("#{self.graph_resource}/", AddGraphParser, "add-graph")
152
+ end
153
+
154
+ def fetch_link
155
+ @link = self.ship.links.find_graph(resource: self.resource)
156
+ @creator = @link.metadata['creator']
157
+ @description = @link.metadata['description']
158
+ @title = @link.metadata['title']
159
+ @type = @link.metadata['config']['graph']
160
+ @link
99
161
  end
100
162
 
101
163
  def fetch_newest_nodes(count)
@@ -140,4 +202,75 @@ module Urbit
140
202
  "/graph/#{self.resource}"
141
203
  end
142
204
  end
205
+
206
+ class PublishGraph < Graph
207
+
208
+ attr_accessor :description, :title
209
+
210
+ def initialize(ship:, graph_name:, title:, description:, persistent: false)
211
+ super ship: ship, graph_name: graph_name, host_ship_name: ship.untilded_name
212
+ @persistent = persistent
213
+ @title = title
214
+ @description = description
215
+ end
216
+
217
+ def add_post(author:, title:, body:)
218
+ j = self.create_post_json(author, title, body)
219
+ resp = self.ship.spider(mark_in: 'graph-update-3', mark_out: 'graph-view-action', thread: 'graph-add-nodes', data: j)
220
+ (200 == resp[:status])
221
+ end
222
+
223
+ def persist
224
+ # PublishGraph, persist thyself in urbit...
225
+ resp = self.ship.spider(mark_in: 'graph-view-action', mark_out: 'json', thread: 'graph-create', data: self.create_graph_json)
226
+ @persistent = (200 == resp[:status])
227
+ end
228
+
229
+ def persistent?
230
+ @persistent
231
+ end
232
+
233
+ private
234
+
235
+ def create_graph_json
236
+ %Q({"create": {"resource" : {"ship": "#{self.ship.name}", "name": "#{self.name}"},
237
+ "title" : "#{self.title}",
238
+ "description": "#{self.description}",
239
+ "associated" : {"policy": {"invite": {"pending": []}}},
240
+ "module" : "publish",
241
+ "mark" : "graph-validator-publish"
242
+ }
243
+ })
244
+ end
245
+
246
+ def create_post_json(author, title, body)
247
+ time = Time.now.to_i
248
+ index = Urbit::Node.unix_to_da(time)
249
+ %Q({
250
+ "add-nodes": {
251
+ "resource": {"ship": "#{self.host_ship}", "name": "#{self.name}"},
252
+ "nodes": {
253
+ "/#{index}": {
254
+ "post": {"author": "#{author}", "index": "/#{index}", "time-sent": #{time}, "contents": [], "hash": null, "signatures": []},
255
+ "children": {
256
+ "1": {
257
+ "post": { "author": "#{author}", "index": "/#{index}/1", "time-sent": #{time}, "contents": [], "hash": null, "signatures": []},
258
+ "children": {
259
+ "1": {
260
+ "post": {"author": "#{author}", "index": "/#{index}/1/1", "time-sent": #{time}, "contents": [{"text": "#{title}"}, {"text": "#{body}"}], "hash": null, "signatures": []},
261
+ "children": null
262
+ }
263
+ }
264
+ },
265
+ "2": {
266
+ "post": {"author": "#{author}", "index": "/#{index}/2", "time-sent": #{time}, "contents": [], "hash": null, "signatures": []},
267
+ "children": null
268
+ }
269
+ }
270
+ }
271
+ }
272
+ }
273
+ })
274
+ end
275
+ end
143
276
  end
data/lib/urbit/group.rb CHANGED
@@ -2,10 +2,11 @@
2
2
 
3
3
  module Urbit
4
4
  class Group
5
- attr_accessor :manager, :members, :tags
5
+ attr_accessor :graphs, :manager, :members, :tags, :title
6
6
  attr_reader :hidden, :path, :policy
7
7
 
8
8
  def initialize(path:, members:, policy:, tags:, hidden:)
9
+ @graphs = Set.new
9
10
  @hidden = hidden
10
11
  @manager = nil
11
12
  @members = Set.new(members)
@@ -22,6 +23,16 @@ module Urbit
22
23
  self.path <=> another_group.path
23
24
  end
24
25
 
26
+ def creator
27
+ self.fetch_link if @creator.nil?
28
+ @creator
29
+ end
30
+
31
+ def description
32
+ self.fetch_link if @description.nil?
33
+ @description
34
+ end
35
+
25
36
  #
26
37
  # This is the action labeled as "Archive" in the Landscape UI.
27
38
  # As of now, you can only do this to groups on your own ship.
@@ -39,6 +50,13 @@ module Urbit
39
50
  another_group.path == self.path
40
51
  end
41
52
 
53
+ def graphs
54
+ if @graphs.empty?
55
+ self.graph_links.each {|gl| @graphs << gl.graph}
56
+ end
57
+ @graphs
58
+ end
59
+
42
60
  def host
43
61
  self.path_tokens[0]
44
62
  end
@@ -82,8 +100,20 @@ module Urbit
82
100
  '?'
83
101
  end
84
102
 
103
+ def picture
104
+ self.fetch_link if @picture.nil?
105
+ @picture
106
+ end
107
+
108
+ def title
109
+ self.fetch_link if @title.nil?
110
+ @title
111
+ end
112
+
85
113
  def to_h
86
114
  {
115
+ title: self.title,
116
+ description: self.description,
87
117
  host: self.host,
88
118
  key: self.key,
89
119
  member_count: self.members.count,
@@ -92,12 +122,37 @@ module Urbit
92
122
  }
93
123
  end
94
124
 
125
+ def to_list
126
+ self.title || "Untitled - #{self.path}"
127
+ end
128
+
95
129
  def to_s
96
130
  "a Group(#{self.to_h})"
97
131
  end
98
132
 
99
133
  private
100
134
 
135
+ def fetch_link
136
+ @group_link = self.manager.ship.links.find_group(path: self.path)
137
+ unless @group_link.nil?
138
+ @creator = @group_link.metadata['creator']
139
+ @description = @group_link.metadata['description']
140
+ @picture = @group_link.metadata['picture']
141
+ @title = @group_link.metadata['title']
142
+ end
143
+ end
144
+
145
+ def graph_links
146
+ self.group_link.graph_links
147
+ end
148
+
149
+ def group_link
150
+ if @group_link.nil?
151
+ self.fetch_link
152
+ end
153
+ @group_link
154
+ end
155
+
101
156
  def parse_tags(tags)
102
157
  h = {}
103
158
  return h if tags.empty?
@@ -1,29 +1,45 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Urbit
4
- class GroupManager
5
- attr_accessor :groups, :ship
4
+ class Groups < Set
5
+ attr_accessor :ship
6
6
 
7
7
  def initialize(ship:)
8
8
  @ship = ship
9
- @groups = []
9
+ @hash = {}
10
+ end
11
+
12
+ def [](path: nil, title: nil)
13
+ if title.nil?
14
+ if (g = self.select {|g| g.path == path}.first)
15
+ g.manager = self
16
+ return g
17
+ end
18
+ else
19
+ if (g = self.select {|g| g.title == title}.first)
20
+ g.manager = self
21
+ return g
22
+ end
23
+ end
24
+ nil
10
25
  end
11
26
 
12
27
  #
13
28
  # Adds a Group to this Manager's groups collection
14
29
  #
15
30
  def add(a_group)
16
- @groups << a_group
31
+ a_group.manager = self
32
+ self << a_group
17
33
  end
18
34
 
19
35
  def add_members(group_path:, ships:)
20
- if (group = self.find(path: group_path))
36
+ if (group = self[path: group_path])
21
37
  group.members += ships
22
38
  end
23
39
  end
24
40
 
25
41
  def add_tag(group_path:, ships:, tag:)
26
- if (group = self.find(path: group_path))
42
+ if (group = self[path: group_path])
27
43
  if (group.tags.include? tag)
28
44
  group.tags[tag] += ships
29
45
  end
@@ -35,23 +51,7 @@ module Urbit
35
51
  end
36
52
 
37
53
  def empty?
38
- self.groups.empty?
39
- end
40
-
41
- #
42
- # Answers the Group uniquely keyed by path:, if it exists
43
- #
44
- def find(path:)
45
- if (g = self.groups.select {|g| g.path == path}.first)
46
- g.manager = self
47
- g
48
- end
49
- end
50
-
51
- def first
52
- g = self.groups.first
53
- g.manager = self
54
- g
54
+ self.empty?
55
55
  end
56
56
 
57
57
  def join(host:, name:, share_contact: false, auto_join: false)
@@ -61,21 +61,21 @@ module Urbit
61
61
  end
62
62
 
63
63
  def list
64
- self.groups.map {|g| g.path}.join("\n")
64
+ self.map {|g| g.to_list}.join("\n")
65
65
  end
66
66
 
67
67
  def remove(group)
68
- @groups = self.groups.filter {|g| g != group}
68
+ self.delete(group)
69
69
  end
70
70
 
71
71
  def remove_members(group_path:, ships:)
72
- if (group = self.find(path: group_path))
72
+ if (group = self[path: group_path])
73
73
  group.members -= ships
74
74
  end
75
75
  end
76
76
 
77
77
  def remove_tag(group_path:, ships:, tag:)
78
- if (group = self.find(path: group_path))
78
+ if (group = self[path: group_path])
79
79
  if (group.tags.include? tag)
80
80
  group.tags[tag] -= ships
81
81
  end
@@ -94,7 +94,7 @@ module Urbit
94
94
  end
95
95
 
96
96
  def to_s
97
- self.groups.sort.each {|g| puts g}
97
+ self.sort.each {|g| puts g}
98
98
  end
99
99
  end
100
100
  end
data/lib/urbit/link.rb ADDED
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Urbit
4
+ class Link
5
+ attr_reader :path, :data
6
+
7
+ def initialize(chain:, path:, data:)
8
+ @chain = chain
9
+ @graph = nil
10
+ @group = nil
11
+ @path = path
12
+ @data = data
13
+ end
14
+
15
+ def ==(another)
16
+ another.path == self.path
17
+ end
18
+
19
+ def <=>(another)
20
+ self.path <=> another.path
21
+ end
22
+
23
+ def eql?(another)
24
+ another.path == self.path
25
+ end
26
+
27
+ def graph
28
+ if @graph.nil?
29
+ @graph = self.ship.graph(resource: self.graph_resource)
30
+ end
31
+ @graph
32
+ end
33
+
34
+ def graph_links
35
+ @chain.find_graph_links_for_group(path: self.group_path)
36
+ end
37
+
38
+ def graph_resource
39
+ @data['resource'].sub('/ship/', '')
40
+ end
41
+
42
+ def group
43
+ if @group.nil?
44
+ @group = self.ship.groups[path: self.group_path]
45
+ end
46
+ @group
47
+ end
48
+
49
+ def group_path
50
+ @data['group'].sub('/ship/', '')
51
+ end
52
+
53
+ def metadata
54
+ @data['metadata']
55
+ end
56
+
57
+ def ship
58
+ @chain.ship
59
+ end
60
+
61
+ def to_list
62
+ @path
63
+ end
64
+
65
+ def type
66
+ @data['app-name']
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Urbit
4
+ class Links < Set
5
+ attr_reader :ship
6
+
7
+ def initialize
8
+ @hash = {}
9
+ @ship = nil
10
+ end
11
+
12
+ def [](path:)
13
+ self.select {|l| path == l.path}.first
14
+ end
15
+
16
+ def find_graph(resource:)
17
+ self.select{|l| l.type == 'graph' && resource == l.graph_resource}.first
18
+ end
19
+
20
+ def find_graph_links_for_group(path:)
21
+ self.select{|l| l.type == 'graph' && path == l.group_path}
22
+ end
23
+
24
+ def find_group(path:)
25
+ self.select{|l| l.type == 'groups' && path == l.group_path}.first
26
+ end
27
+
28
+ def list
29
+ self.sort.each {|l| puts l.to_list}
30
+ nil
31
+ end
32
+
33
+ def load(ship:)
34
+ ship.subscribe(app: 'metadata-store', path: '/all')
35
+ @ship = ship
36
+ nil
37
+ end
38
+ end
39
+ end
data/lib/urbit/node.rb CHANGED
@@ -98,6 +98,10 @@ module Urbit
98
98
  @graph.newer_sibling_nodes(node: self, count: count)
99
99
  end
100
100
 
101
+ def parent?
102
+ !self.children.empty?
103
+ end
104
+
101
105
  #
102
106
  # Answers the previous {count} Nodes relative to this Node.
103
107
  # Defaults to the next Node if no {count} is passed.
@@ -124,7 +128,7 @@ module Urbit
124
128
  author: self.author,
125
129
  sent: self.datetime_sent,
126
130
  contents: self.contents,
127
- is_parent: !self.children.empty?,
131
+ is_parent: self.parent?,
128
132
  child_count: self.children.count
129
133
  }
130
134
  end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'urbit/bucket'
4
+
5
+ module Urbit
6
+ class Setting
7
+ attr_accessor :buckets
8
+ attr_reader :desk, :ship
9
+
10
+ def initialize(ship:, desk:, buckets:)
11
+ @ship = ship
12
+ @desk = desk
13
+ @buckets = Set.new
14
+ buckets.each {|k, v| @buckets << Bucket.new(setting: self, name: k, entries: v)}
15
+ end
16
+
17
+ def ==(another_group)
18
+ another_setting.desk == self.desk
19
+ end
20
+
21
+ def <=>(another_group)
22
+ self.desk <=> another_group.desk
23
+ end
24
+
25
+ def [](bucket:)
26
+ self.buckets.select {|b| bucket == b.name}.first
27
+ end
28
+
29
+ def add_bucket(name:, entries:)
30
+ msg = {
31
+ "put-bucket": {
32
+ "bucket-key": "#{name}",
33
+ "desk": "#{self.desk}",
34
+ "bucket": entries
35
+ }
36
+ }
37
+ self.ship.poke(app: 'settings-store', mark: 'settings-event', message: msg)
38
+ nil
39
+ end
40
+
41
+ def entries(bucket:)
42
+ self[bucket: bucket].entries
43
+ end
44
+
45
+ def remove_bucket(name:)
46
+ msg = {
47
+ "del-bucket": {
48
+ "bucket-key": "#{name}",
49
+ "desk": "#{self.desk}"
50
+ }
51
+ }
52
+ self.ship.poke(app: 'settings-store', mark: 'settings-event', message: msg)
53
+ nil
54
+ end
55
+
56
+ def to_h
57
+ {
58
+ desk: @desk,
59
+ buckets: self.buckets,
60
+ }
61
+ end
62
+
63
+ def to_s
64
+ "a Setting(#{self.to_h})"
65
+ end
66
+
67
+ def to_string
68
+ "desk: #{self.desk}\n buckets: #{self.buckets.collect {|b| b.to_string}}"
69
+ end
70
+ end
71
+ end
@@ -1,74 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'urbit/bucket'
3
+ require 'urbit/setting'
4
4
 
5
5
  module Urbit
6
- class Setting
7
- attr_accessor :buckets
8
- attr_reader :desk, :ship
9
-
10
- def initialize(ship:, desk:, buckets:)
11
- @ship = ship
12
- @desk = desk
13
- @buckets = Set.new
14
- buckets.each {|k, v| @buckets << Bucket.new(setting: self, name: k, entries: v)}
15
- end
16
-
17
- def ==(another_group)
18
- another_setting.desk == self.desk
19
- end
20
-
21
- def <=>(another_group)
22
- self.desk <=> another_group.desk
23
- end
24
-
25
- def [](bucket:)
26
- self.buckets.select {|b| bucket == b.name}.first
27
- end
28
-
29
- def add_bucket(name:, entries:)
30
- msg = {
31
- "put-bucket": {
32
- "bucket-key": "#{name}",
33
- "desk": "#{self.desk}",
34
- "bucket": entries
35
- }
36
- }
37
- self.ship.poke(app: 'settings-store', mark: 'settings-event', message: msg)
38
- nil
39
- end
40
-
41
- def entries(bucket:)
42
- self[bucket: bucket].entries
43
- end
44
-
45
- def remove_bucket(name:)
46
- msg = {
47
- "del-bucket": {
48
- "bucket-key": "#{name}",
49
- "desk": "#{self.desk}"
50
- }
51
- }
52
- self.ship.poke(app: 'settings-store', mark: 'settings-event', message: msg)
53
- nil
54
- end
55
-
56
- def to_h
57
- {
58
- desk: @desk,
59
- buckets: self.buckets,
60
- }
61
- end
62
-
63
- def to_s
64
- "a Setting(#{self.to_h})"
65
- end
66
-
67
- def to_string
68
- "desk: #{self.desk}\n buckets: #{self.buckets.collect {|b| b.to_string}}"
69
- end
70
- end
71
-
72
6
  class Settings < Set
73
7
  class << self
74
8
  def load(ship:)
@@ -99,5 +33,4 @@ module Urbit
99
33
  nil
100
34
  end
101
35
  end
102
-
103
36
  end
data/lib/urbit/ship.rb CHANGED
@@ -3,20 +3,22 @@ require 'faraday'
3
3
  require 'urbit/channel'
4
4
  require 'urbit/config'
5
5
  require 'urbit/graph'
6
- require 'urbit/group_manager'
6
+ require 'urbit/groups'
7
+ require 'urbit/links'
7
8
  require 'urbit/settings'
8
9
 
9
10
  module Urbit
10
11
  class Ship
11
12
  attr_accessor :logged_in
12
- attr_reader :auth_cookie, :channels, :config, :group_mgr
13
+ attr_reader :auth_cookie, :channels, :config
13
14
 
14
15
  def initialize(config: Config.new)
15
16
  @auth_cookie = nil
16
17
  @channels = []
17
18
  @config = config
18
19
  @graphs = []
19
- @group_mgr = GroupManager.new ship: self
20
+ @groups = Groups.new ship: self
21
+ @links = Links.new
20
22
  @settings = nil # Use lazy initialization here
21
23
  @logged_in = false
22
24
  end
@@ -41,7 +43,7 @@ module Urbit
41
43
  # Answers a collection of all the top-level graphs on this ship.
42
44
  # This collection is cached and will need to be invalidated to discover new graphs.
43
45
  #
44
- def graphs(flush_cache: false)
46
+ def graphs(flush_cache: true)
45
47
  @graphs = [] if flush_cache
46
48
  if @graphs.empty?
47
49
  if self.logged_in?
@@ -64,19 +66,16 @@ module Urbit
64
66
  self.graphs.collect {|g| g.resource}
65
67
  end
66
68
 
67
- #
68
- # Answers the Group uniquely keyed by path:, if it exists
69
- #
70
- def group(path:)
71
- @group_mgr.find_by_path(path)
72
- end
73
-
74
69
  #
75
70
  # Answers the object managing the Groups on this ship.
76
71
  # This object provides all the helper methods to list, join, leave, &c. a Group
77
72
  #
78
73
  def groups
79
- @group_mgr
74
+ @groups
75
+ end
76
+
77
+ def links
78
+ @links
80
79
  end
81
80
 
82
81
  def login
@@ -85,7 +84,14 @@ module Urbit
85
84
  ensure_connections_closed
86
85
  response = Faraday.post(login_url, "password=#{config.code}")
87
86
  parse_cookie(response)
88
- @group_mgr.load
87
+ @groups.load
88
+
89
+ # For now we will require a subscription to all metadata. it's the glue between %graphs and %groups.
90
+ # A key issue that arose is that these are both async %subscribe calls and so there are sync issues
91
+ # if we try to directly link the groups and the graphs. Instead we need to just store the links
92
+ # and lazy-instatiate the metadata _if_ we have received it.
93
+ @links.load ship: self
94
+
89
95
  self
90
96
  end
91
97
 
data/lib/urbit/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Urbit
4
- VERSION = "0.4.0"
4
+ VERSION = "0.6.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: urbit-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daryl Richter
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-03-18 00:00:00.000000000 Z
11
+ date: 2022-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -99,16 +99,20 @@ files:
99
99
  - lib/urbit/fact/base_fact.rb
100
100
  - lib/urbit/fact/graph_fact.rb
101
101
  - lib/urbit/fact/group_fact.rb
102
+ - lib/urbit/fact/metadata_fact.rb
102
103
  - lib/urbit/fact/settings_fact.rb
103
104
  - lib/urbit/graph.rb
104
105
  - lib/urbit/group.rb
105
- - lib/urbit/group_manager.rb
106
106
  - lib/urbit/group_parser.rb
107
+ - lib/urbit/groups.rb
108
+ - lib/urbit/link.rb
109
+ - lib/urbit/links.rb
107
110
  - lib/urbit/message.rb
108
111
  - lib/urbit/node.rb
109
112
  - lib/urbit/parser.rb
110
113
  - lib/urbit/poke_message.rb
111
114
  - lib/urbit/receiver.rb
115
+ - lib/urbit/setting.rb
112
116
  - lib/urbit/settings.rb
113
117
  - lib/urbit/ship.rb
114
118
  - lib/urbit/subscribe_message.rb
@@ -121,7 +125,7 @@ metadata:
121
125
  homepage_uri: https://www.ngzax.com
122
126
  source_code_uri: https://github.com/Zaxonomy/urbit-ruby
123
127
  changelog_uri: https://github.com/Zaxonomy/urbit-ruby/CHANGELOG.md
124
- post_install_message:
128
+ post_install_message:
125
129
  rdoc_options: []
126
130
  require_paths:
127
131
  - lib
@@ -136,8 +140,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
136
140
  - !ruby/object:Gem::Version
137
141
  version: '0'
138
142
  requirements: []
139
- rubygems_version: 3.1.6
140
- signing_key:
143
+ rubygems_version: 3.0.3.1
144
+ signing_key:
141
145
  specification_version: 4
142
146
  summary: The Ruby interface to the Urbit HTTP API
143
147
  test_files: []