urbit-api 0.4.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/urbit/fact/base_fact.rb +0 -2
- data/lib/urbit/fact/graph_fact.rb +3 -5
- data/lib/urbit/fact/metadata_fact.rb +57 -0
- data/lib/urbit/fact.rb +5 -0
- data/lib/urbit/graph.rb +139 -6
- data/lib/urbit/group.rb +56 -1
- data/lib/urbit/{group_manager.rb → groups.rb} +28 -28
- data/lib/urbit/link.rb +69 -0
- data/lib/urbit/links.rb +39 -0
- data/lib/urbit/node.rb +5 -1
- data/lib/urbit/setting.rb +71 -0
- data/lib/urbit/settings.rb +1 -68
- data/lib/urbit/ship.rb +19 -13
- data/lib/urbit/version.rb +1 -1
- metadata +11 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b57a15f5dfda9e19e863a4fb4760279b98c9d2af55f9865a470be3f6cb23520a
|
4
|
+
data.tar.gz: a5442c3e68b634372791bd4ecee3a8a84de201dbe708d94709ddff7fdf20827e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e1f0ba98b3ad9cfea824c2b48da18a0123d1a83df844809dcde1bda5e301871477f6c30064e47351c3a0302402482886d709324409e74420078b8c98ecb5e73
|
7
|
+
data.tar.gz: 49077ec0705dcbecbe1f758911d982e0101f20c07e2d3638bb99729e57dcbc9e331ee048dcd255f1f729cc1ab6129043a0b79dd1269c350924c3b86a95b8508c
|
data/lib/urbit/fact/base_fact.rb
CHANGED
@@ -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
|
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
|
-
@
|
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
|
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
|
-
|
98
|
-
|
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
|
5
|
-
attr_accessor :
|
4
|
+
class Groups < Set
|
5
|
+
attr_accessor :ship
|
6
6
|
|
7
7
|
def initialize(ship:)
|
8
8
|
@ship = ship
|
9
|
-
@
|
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
|
-
|
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
|
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
|
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.
|
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.
|
64
|
+
self.map {|g| g.to_list}.join("\n")
|
65
65
|
end
|
66
66
|
|
67
67
|
def remove(group)
|
68
|
-
|
68
|
+
self.delete(group)
|
69
69
|
end
|
70
70
|
|
71
71
|
def remove_members(group_path:, ships:)
|
72
|
-
if (group = self
|
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
|
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.
|
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
|
data/lib/urbit/links.rb
ADDED
@@ -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:
|
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
|
data/lib/urbit/settings.rb
CHANGED
@@ -1,74 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'urbit/
|
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/
|
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
|
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
|
-
@
|
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:
|
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
|
-
@
|
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
|
-
@
|
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
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
|
+
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-
|
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
|
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: []
|