urbit-api 0.2.0 → 0.4.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: 0a3c9e5915684d444baa066c316ebeafd2cddc0aa731d323b15fec95be932b05
4
- data.tar.gz: 951ddb43e002c92c0490b549de64a2311b42124c09cb499833d58d7c717b088d
3
+ metadata.gz: d45d05923c175955a85dfb0676a63eafc0eed277b656b7d045f8675f586cee7e
4
+ data.tar.gz: e2bc0d8d71d02629b9b3f335ff1672f20686c178e1584540ff1724943d82158c
5
5
  SHA512:
6
- metadata.gz: a677021940189cf5e52a969b01d4f77b418dc544d823b47d1dfaf83832c44f00dbe926692d9957f3a01809a8fdda15ba65177b5a57ecb01f310ec800e09d6e75
7
- data.tar.gz: d10188333e23d83a6abee0a44250bdce9641694264fc81970b5de285a973156f00b7b5a342b88e3b4d476d8a363e350012aabcf727cc940b9a2f0fc50ce59918
6
+ metadata.gz: 86e48b8bae4f5cedfbe9ca0fcb4ac327185973ce73e29c8a26f7644fadb2e8f78850b9f1cca9d62802d22c45afdeb025b8d495e14d54bf642f123f66f986a1c5
7
+ data.tar.gz: 20968fc224c1e4fd6105922a4ddc30b16f45f25a12f2c5e4294eaec33f7d379db8180720b062a3d274755853468c7e61af823401ec2a4f5b3e800be3f1de497f
@@ -0,0 +1,45 @@
1
+
2
+ module Urbit
3
+ class Bucket
4
+ attr_accessor :entries, :name, :setting
5
+
6
+ def initialize(setting:, name:, entries:)
7
+ @setting = setting
8
+ @name = name
9
+ @entries = Hash.new.replace(entries)
10
+ end
11
+
12
+ def [](key:)
13
+ self.entries[key]
14
+ end
15
+
16
+ def []=(key, val)
17
+ msg = {"put-entry": {"desk": "#{@setting.desk}", "bucket-key": "#{self.name}", "entry-key": "#{key[:key]}", "value": val}}
18
+ self.ship.poke(app: 'settings-store', mark: 'settings-event', message: msg)
19
+ nil
20
+ end
21
+
22
+ def remove_entry(key:)
23
+ msg = {"del-entry": {"desk": "#{@setting.desk}", "bucket-key": "#{self.name}", "entry-key": "#{key}"}}
24
+ self.ship.poke(app: 'settings-store', mark: 'settings-event', message: msg)
25
+ nil
26
+ end
27
+
28
+ def ship
29
+ self.setting.ship
30
+ end
31
+
32
+ def to_h
33
+ {name: @name, entries: @entries}
34
+ end
35
+
36
+ def to_s
37
+ "a Bucket(#{self.to_h})"
38
+ end
39
+
40
+ def to_string
41
+ "#{self.name}: #{self.entries.count} entries"
42
+ end
43
+
44
+ end
45
+ end
data/lib/urbit/channel.rb CHANGED
@@ -21,7 +21,6 @@ module Urbit
21
21
  end
22
22
 
23
23
  def close
24
- # puts "closing #{name}"
25
24
  m = Urbit::CloseMessage.new(channel: self)
26
25
  @is_open = !self.send(message: m)
27
26
  end
@@ -35,11 +34,11 @@ module Urbit
35
34
  end
36
35
 
37
36
  #
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.
37
+ # Poke an app with a message using a mark.
38
+ # The message must be a Ruby Hash, not a String.
40
39
  #
41
40
  def poke(app:, mark:, message:)
42
- @is_open = self.send(message: (Urbit::PokeMessage.new(channel: self, app: app, mark: mark, a_string: message)))
41
+ @is_open = self.send(message: (Urbit::PokeMessage.new(channel: self, app: app, mark: mark, a_message_hash: message)))
43
42
  @receiver = Urbit::Receiver.new(channel: self)
44
43
  self
45
44
  end
@@ -84,7 +83,7 @@ module Urbit
84
83
  end
85
84
 
86
85
  def url
87
- "http://localhost:8080/~/channel/#{self.key}"
86
+ "#{self.ship.url}/~/channel/#{self.key}"
88
87
  end
89
88
  end
90
89
  end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Urbit
4
+ module Fact
5
+ class BaseFact
6
+ attr_reader :ack, :channel, :data, :type
7
+
8
+ def initialize(channel:, event:)
9
+ @channel = channel
10
+ @data = event.data
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
+ end
15
+
16
+ def add_ack(ack:)
17
+ @ack = :ack
18
+ end
19
+
20
+ def contents
21
+ JSON.parse(@data)
22
+ end
23
+
24
+ def create_parser
25
+ nil
26
+ end
27
+
28
+ def for_this_ship?
29
+ self.ship == @channel.ship
30
+ end
31
+
32
+ def graph_update?
33
+ false
34
+ end
35
+
36
+ def is_acknowledged?
37
+ !@ack.nil?
38
+ end
39
+
40
+ def raw_json
41
+ nil
42
+ end
43
+
44
+ def ship
45
+ @channel.ship
46
+ end
47
+
48
+ def to_h
49
+ {
50
+ ship: self.ship.to_h,
51
+ acknowleged: self.is_acknowledged?,
52
+ is_graph_update: self.graph_update?
53
+ }
54
+ end
55
+
56
+ def to_s
57
+ "a #{self.class.name}(#{self.to_h})"
58
+ end
59
+ end
60
+
61
+ class EmptyFact < BaseFact
62
+ end
63
+
64
+ class ErrorFact < BaseFact
65
+ def error
66
+ self.contents["err"]
67
+ end
68
+
69
+ def response
70
+ self.contents["response"]
71
+ end
72
+
73
+ def to_h
74
+ super.merge!({
75
+ error: self.error,
76
+ response: self.response,
77
+ })
78
+ end
79
+ end
80
+
81
+ class SuccessFact < BaseFact
82
+ def code
83
+ self.contents["ok"]
84
+ end
85
+
86
+ def response
87
+ self.contents["response"]
88
+ end
89
+
90
+ def to_h
91
+ super.merge!({
92
+ code: self.code,
93
+ response: self.response,
94
+ })
95
+ end
96
+
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Urbit
4
+ module Fact
5
+ class GraphUpdateFact < BaseFact
6
+ def initialize(channel:, event:)
7
+ super channel: channel, event: event
8
+ end
9
+
10
+ #
11
+ # Attach this new fact as a node to its Graph.
12
+ #
13
+ def attach_parser
14
+ # puts "Received a graph update for [#{self.ship.graph(resource: self.resource)}]"
15
+ if self.incoming_graph
16
+ # puts "Received an add_graph event: #{self.raw_json} on #{self.resource}"
17
+ self.create_parser
18
+ end
19
+ end
20
+
21
+ def graph_update?
22
+ true
23
+ end
24
+
25
+ def incoming_graph
26
+ self.ship.graph(resource: self.resource)
27
+ end
28
+
29
+ def resource
30
+ return "~#{self.resource_h["ship"]}/#{self.resource_h["name"]}" unless self.resource_h.nil?
31
+ end
32
+
33
+ def resource_h
34
+ self.raw_json["resource"]
35
+ end
36
+
37
+ def root_h
38
+ self.contents["json"]["graph-update"]
39
+ end
40
+
41
+ def to_h
42
+ super.merge!(resource: self.resource)
43
+ end
44
+ end
45
+
46
+ class AddGraphFact < GraphUpdateFact
47
+ def initialize(channel:, event:)
48
+ super channel: channel, event: event
49
+ end
50
+
51
+ def create_parser
52
+ Urbit::AddGraphParser.new(for_graph: incoming_graph, with_json: self.raw_json).add_nodes
53
+ end
54
+
55
+ def raw_json
56
+ self.root_h["add-graph"]
57
+ end
58
+ end
59
+
60
+ class AddNodesFact < GraphUpdateFact
61
+ def initialize(channel:, event:)
62
+ super channel: channel, event: event
63
+ end
64
+
65
+ def create_parser
66
+ Urbit::AddNodesParser.new(for_graph: incoming_graph, with_json: self.raw_json).add_nodes
67
+ end
68
+
69
+ def raw_json
70
+ self.root_h["add-nodes"]
71
+ end
72
+ end
73
+
74
+ class RemoveGraphFact < GraphUpdateFact
75
+ def initialize(channel:, event:)
76
+ super channel: channel, event: event
77
+ end
78
+
79
+ def create_parser
80
+ Urbit::RemoveGraphParser.new(for_graph: incoming_graph, with_json: self.raw_json)
81
+ end
82
+
83
+ def raw_json
84
+ self.root_h["remove-graph"]
85
+ end
86
+
87
+ def resource_h
88
+ self.raw_json
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'urbit/group'
4
+ require 'urbit/group_parser'
5
+
6
+ module Urbit
7
+ module Fact
8
+ class GroupUpdateFact < BaseFact
9
+ def initialize(channel:, event:)
10
+ super channel: channel, event: event
11
+ end
12
+
13
+ def root_h
14
+ self.contents["json"]["groupUpdate"]
15
+ end
16
+ end
17
+
18
+ class AddGroupFact < GroupUpdateFact
19
+ def initialize(channel:, event:)
20
+ super channel: channel, event: event
21
+ self.channel.ship.groups.add(self.parser.group)
22
+ end
23
+
24
+ def parser
25
+ Urbit::AddGroupParser.new(with_json: self.raw_json)
26
+ end
27
+
28
+ def raw_json
29
+ self.root_h["addGroup"]
30
+ end
31
+ end
32
+
33
+ class AddGroupMemberFact < GroupUpdateFact
34
+ def initialize(channel:, event:)
35
+ super channel: channel, event: event
36
+ self.channel.ship.groups.add_members group_path: self.parser.resource, ships: self.parser.ships
37
+ end
38
+
39
+ def parser
40
+ Urbit::ChangeMemberParser.new(with_json: self.raw_json)
41
+ end
42
+
43
+ def raw_json
44
+ self.root_h["addMembers"]
45
+ end
46
+ end
47
+
48
+ class AddTagFact < GroupUpdateFact
49
+ def initialize(channel:, event:)
50
+ super channel: channel, event: event
51
+ self.channel.ship.groups.add_tag group_path: self.parser.resource, ships: self.parser.ships, tag: self.parser.tag
52
+ end
53
+
54
+ def parser
55
+ Urbit::ChangeTagParser.new(with_json: self.raw_json)
56
+ end
57
+
58
+ def raw_json
59
+ self.root_h["addTag"]
60
+ end
61
+ end
62
+
63
+ class InitialGroupFact < GroupUpdateFact
64
+ def initialize(channel:, event:)
65
+ super channel: channel, event: event
66
+ self.parser.groups.each {|g| self.channel.ship.groups.add(g)}
67
+ end
68
+
69
+ def parser
70
+ Urbit::InitialGroupParser.new(with_json: self.raw_json)
71
+ end
72
+
73
+ def raw_json
74
+ self.root_h["initial"]
75
+ end
76
+ end
77
+
78
+ class InitialGroupGroupFact < GroupUpdateFact
79
+ def initialize(channel:, event:)
80
+ super channel: channel, event: event
81
+ self.channel.ship.groups.add(self.parser.group)
82
+ end
83
+
84
+ def parser
85
+ Urbit::InitialGroupGroupParser.new(with_json: self.raw_json)
86
+ end
87
+
88
+ def raw_json
89
+ self.root_h["initialGroup"]
90
+ end
91
+ end
92
+
93
+ class RemoveGroupMemberFact < GroupUpdateFact
94
+ def initialize(channel:, event:)
95
+ super channel: channel, event: event
96
+ self.channel.ship.groups.remove_members group_path: self.parser.resource, ships: self.parser.ships
97
+ end
98
+
99
+ def parser
100
+ Urbit::ChangeMemberParser.new(with_json: self.raw_json)
101
+ end
102
+
103
+ def raw_json
104
+ self.root_h["removeMembers"]
105
+ end
106
+ end
107
+
108
+ class RemoveTagFact < GroupUpdateFact
109
+ def initialize(channel:, event:)
110
+ super channel: channel, event: event
111
+ self.channel.ship.groups.remove_tag group_path: self.parser.resource, ships: self.parser.ships, tag: self.parser.tag
112
+ end
113
+
114
+ def parser
115
+ Urbit::ChangeTagParser.new(with_json: self.raw_json)
116
+ end
117
+
118
+ def raw_json
119
+ self.root_h["removeTag"]
120
+ end
121
+ end
122
+
123
+ end # Module Fact
124
+ end # Module Urbit
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Urbit
4
+ module Fact
5
+
6
+ class SettingsEventFact < BaseFact
7
+ def initialize(channel:, event:)
8
+ super channel: channel, event: event
9
+ self.accept if self.for_this_ship?
10
+ end
11
+
12
+ def accept
13
+ nil
14
+ end
15
+
16
+ def base_contents
17
+ JSON.parse(@data)["json"]["settings-event"]
18
+ end
19
+
20
+ def bucket
21
+ self.desk[bucket: self.bucket_key]
22
+ end
23
+
24
+ def bucket_key
25
+ self.contents["bucket-key"]
26
+ end
27
+
28
+ def desk
29
+ self.ship.settings[desk: self.desk_name]
30
+ end
31
+
32
+ def desk_name
33
+ self.contents["desk"]
34
+ end
35
+
36
+ def to_h
37
+ super.merge!({
38
+ bucket: self.bucket_key,
39
+ desk: self.desk_name,
40
+ })
41
+ end
42
+ end
43
+
44
+ class SettingsEventDelBucketFact < SettingsEventFact
45
+ def accept
46
+ self.desk.buckets.delete(self.bucket)
47
+ end
48
+
49
+ def contents
50
+ self.base_contents["del-bucket"]
51
+ end
52
+ end
53
+
54
+ class SettingsEventDelEntryFact < SettingsEventFact
55
+ def accept
56
+ self.bucket.entries.delete(self.entry)
57
+ end
58
+
59
+ def contents
60
+ self.base_contents["del-entry"]
61
+ end
62
+
63
+ def entry
64
+ self.contents["entry-key"]
65
+ end
66
+ end
67
+
68
+ class SettingsEventPutBucketFact < SettingsEventFact
69
+ def accept
70
+ # This is a new bucket, add it.
71
+ s = channel.ship.settings[desk: self.desk_name]
72
+ s.buckets << Bucket.new(setting: s, name: self.bucket_key, entries: self.entries)
73
+ nil
74
+ end
75
+
76
+ def contents
77
+ self.base_contents["put-bucket"]
78
+ end
79
+
80
+ def entries
81
+ self.contents["bucket"]
82
+ end
83
+
84
+ def to_h
85
+ super.merge!({
86
+ entries: self.entries
87
+ })
88
+ end
89
+ end
90
+
91
+ class SettingsEventPutEntryFact < SettingsEventFact
92
+ def accept
93
+ # See if we already have this setting, if no add it, if yes update it.
94
+ if (entries = channel.ship.settings[desk: self.desk_name].entries(bucket: self.bucket_key))
95
+ entries[self.entry] = self.value
96
+ end
97
+ end
98
+
99
+ def contents
100
+ self.base_contents["put-entry"]
101
+ end
102
+
103
+ def entry
104
+ self.contents["entry-key"]
105
+ end
106
+
107
+ def to_h
108
+ super.merge!({
109
+ entry: self.entry,
110
+ value: self.value
111
+ })
112
+ end
113
+
114
+ def value
115
+ self.contents["value"]
116
+ end
117
+ end
118
+
119
+ end
120
+ end
data/lib/urbit/fact.rb CHANGED
@@ -1,66 +1,50 @@
1
- require 'urbit/graph'
2
- require 'urbit/node'
3
- require 'urbit/parser'
1
+ # frozen_string_literal: true
4
2
 
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
3
+ require_relative 'fact/base_fact'
4
+ require_relative 'fact/graph_fact'
5
+ require_relative 'fact/group_fact'
6
+ require_relative 'fact/settings_fact'
13
7
 
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
8
+ module Urbit
9
+ module Fact
10
+ class << self
11
+ #
12
+ # This is a Factory method to make the proper Fact subclass from a Channel Event.
13
+ #
14
+ def collect(channel:, event:)
15
+ contents = JSON.parse(event.data)
16
+
17
+ if contents["json"].nil?
18
+ return SuccessFact.new(channel: channel, event: event) if contents["ok"]
19
+ return ErrorFact.new(channel: channel, event: event) if contents["err"]
20
+ return EmptyFact.new(channel: channel, event: event)
21
+ end
22
+
23
+ if contents["json"]["graph-update"]
24
+ return AddGraphFact.new(channel: channel, event: event) if contents["json"]["graph-update"]["add-graph"]
25
+ return AddNodesFact.new(channel: channel, event: event) if contents["json"]["graph-update"]["add-nodes"]
26
+ return RemoveGraphFact.new(channel: channel, event: event) if contents["json"]["graph-update"]["remove-graph"]
27
+ end
28
+
29
+ if (c = contents["json"]["groupUpdate"])
30
+ return AddGroupFact.new(channel: channel, event: event) if c["addGroup"]
31
+ return AddGroupMemberFact.new(channel: channel, event: event) if c["addMembers"]
32
+ return AddTagFact.new(channel: channel, event: event) if c["addTag"]
33
+ return InitialGroupFact.new(channel: channel, event: event) if c["initial"]
34
+ return InitialGroupGroupFact.new(channel: channel, event: event) if c["initialGroup"]
35
+ return RemoveGroupMemberFact.new(channel: channel, event: event) if c["removeMembers"]
36
+ return RemoveTagFact.new(channel: channel, event: event) if c["removeTag"]
37
+ end
38
+
39
+ if (c = contents["json"]["settings-event"])
40
+ return SettingsEventDelBucketFact.new(channel: channel, event: event) if c["del-bucket"]
41
+ return SettingsEventDelEntryFact.new(channel: channel, event: event) if c["del-entry"]
42
+ return SettingsEventPutBucketFact.new(channel: channel, event: event) if c["put-bucket"]
43
+ return SettingsEventPutEntryFact.new(channel: channel, event: event) if c["put-entry"]
44
+ end
45
+
46
+ return BaseFact.new(channel: channel, event: event)
18
47
  end
19
48
  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
49
  end
66
50
  end
data/lib/urbit/graph.rb CHANGED
@@ -14,7 +14,7 @@ module Urbit
14
14
  end
15
15
 
16
16
  def add_node(node:)
17
- @nodes << node
17
+ @nodes << node unless node.deleted?
18
18
  end
19
19
 
20
20
  def host_ship
@@ -56,7 +56,8 @@ module Urbit
56
56
  def newest_nodes(count: 10)
57
57
  count = 1 if count < 1
58
58
  return self.fetch_newest_nodes(count) if @nodes.empty? || @nodes.count < count
59
- self.nodes.reverse[0..(count - 1)]
59
+ last_node = self.nodes.count - 1
60
+ self.nodes[(last_node - count)..last_node]
60
61
  end
61
62
 
62
63
  def oldest_nodes(count: 10)