urbit-api 0.2.1 → 0.5.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: 466e396f78dad90e05ab4b1010f8c6638ab79468f9adf47f6704ab91f39c4a29
4
- data.tar.gz: cf2ca6d9f02d70f0a2cd421cc3b1a28d95ba612842ee5a8b6faea6738d3e8e1c
3
+ metadata.gz: a306b64d165415e7a680fd82a20b75de6840ca80d9482be6ceacbd13fd2b4a9f
4
+ data.tar.gz: 81ce508aee55fd9cdee15bb56774adf5f226b7f5620d9430f4be8de73cb307f9
5
5
  SHA512:
6
- metadata.gz: c8012c2739134932ec79654cd9a33edb993dcb88304195574d890bad04bc82e2c6e47ca0f46cae5e3fc288deae7766f173ed7ee25c5f9f9e86fad6a66588cdae
7
- data.tar.gz: 402992b7ee1782c62025f75d9c1c537ad267db4397346bb04961988c2cfde0d1dc6f233a44f3c8067e0023c22b07c215f9a633d0f33d5325fea4dc6a9650c7dd
6
+ metadata.gz: 1cfffd8c6a8f82d701ace0b49266036f17bc481ea75d799d871e7d785899771686d6682a5444a1a20d3b167d7b5415ef4d05b18baa2dc1553000719055b5ca58
7
+ data.tar.gz: 561e7976cf6d5b5c07e224079e53f6a6102214d317050fd16d1eb5639befb41b020f88ff50b18a94ffda31eaf85515408e5e85bbf38b3610d59e141c02dfb3de
@@ -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,97 @@
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
+ end
13
+
14
+ def add_ack(ack:)
15
+ @ack = :ack
16
+ end
17
+
18
+ def contents
19
+ JSON.parse(@data)
20
+ end
21
+
22
+ def create_parser
23
+ nil
24
+ end
25
+
26
+ def for_this_ship?
27
+ self.ship == @channel.ship
28
+ end
29
+
30
+ def graph_update?
31
+ false
32
+ end
33
+
34
+ def is_acknowledged?
35
+ !@ack.nil?
36
+ end
37
+
38
+ def raw_json
39
+ nil
40
+ end
41
+
42
+ def ship
43
+ @channel.ship
44
+ end
45
+
46
+ def to_h
47
+ {
48
+ ship: self.ship.to_h,
49
+ acknowleged: self.is_acknowledged?,
50
+ is_graph_update: self.graph_update?
51
+ }
52
+ end
53
+
54
+ def to_s
55
+ "a #{self.class.name}(#{self.to_h})"
56
+ end
57
+ end
58
+
59
+ class EmptyFact < BaseFact
60
+ end
61
+
62
+ class ErrorFact < BaseFact
63
+ def error
64
+ self.contents["err"]
65
+ end
66
+
67
+ def response
68
+ self.contents["response"]
69
+ end
70
+
71
+ def to_h
72
+ super.merge!({
73
+ error: self.error,
74
+ response: self.response,
75
+ })
76
+ end
77
+ end
78
+
79
+ class SuccessFact < BaseFact
80
+ def code
81
+ self.contents["ok"]
82
+ end
83
+
84
+ def response
85
+ self.contents["response"]
86
+ end
87
+
88
+ def to_h
89
+ super.merge!({
90
+ code: self.code,
91
+ response: self.response,
92
+ })
93
+ end
94
+
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,90 @@
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
+ if self.incoming_graph
15
+ self.create_parser
16
+ end
17
+ end
18
+
19
+ def graph_update?
20
+ true
21
+ end
22
+
23
+ def incoming_graph
24
+ self.ship.graph(resource: self.resource)
25
+ end
26
+
27
+ def resource
28
+ return "~#{self.resource_h["ship"]}/#{self.resource_h["name"]}" unless self.resource_h.nil?
29
+ end
30
+
31
+ def resource_h
32
+ self.raw_json["resource"]
33
+ end
34
+
35
+ def root_h
36
+ self.contents["json"]["graph-update"]
37
+ end
38
+
39
+ def to_h
40
+ super.merge!(resource: self.resource)
41
+ end
42
+ end
43
+
44
+ class AddGraphFact < GraphUpdateFact
45
+ def initialize(channel:, event:)
46
+ super channel: channel, event: event
47
+ end
48
+
49
+ def create_parser
50
+ Urbit::AddGraphParser.new(for_graph: self.incoming_graph, with_json: self.raw_json).add_nodes
51
+ end
52
+
53
+ def raw_json
54
+ self.root_h["add-graph"]
55
+ end
56
+ end
57
+
58
+ class AddNodesFact < GraphUpdateFact
59
+ def initialize(channel:, event:)
60
+ super channel: channel, event: event
61
+ end
62
+
63
+ def create_parser
64
+ Urbit::AddNodesParser.new(for_graph: self.incoming_graph, with_json: self.raw_json).add_nodes
65
+ end
66
+
67
+ def raw_json
68
+ self.root_h["add-nodes"]
69
+ end
70
+ end
71
+
72
+ class RemoveGraphFact < GraphUpdateFact
73
+ def initialize(channel:, event:)
74
+ super channel: channel, event: event
75
+ end
76
+
77
+ def create_parser
78
+ Urbit::RemoveGraphParser.new(for_graph: self.incoming_graph, with_json: self.raw_json)
79
+ end
80
+
81
+ def raw_json
82
+ self.root_h["remove-graph"]
83
+ end
84
+
85
+ def resource_h
86
+ self.raw_json
87
+ end
88
+ end
89
+ end
90
+ 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,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
@@ -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,55 @@
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/metadata_fact'
7
+ require_relative 'fact/settings_fact'
13
8
 
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
9
+ module Urbit
10
+ module Fact
11
+ class << self
12
+ #
13
+ # This is a Factory method to make the proper Fact subclass from a Channel Event.
14
+ #
15
+ def collect(channel:, event:)
16
+ contents = JSON.parse(event.data)
17
+
18
+ if contents["json"].nil?
19
+ return SuccessFact.new(channel: channel, event: event) if contents["ok"]
20
+ return ErrorFact.new(channel: channel, event: event) if contents["err"]
21
+ return EmptyFact.new(channel: channel, event: event)
22
+ end
23
+
24
+ if contents["json"]["graph-update"]
25
+ return AddGraphFact.new(channel: channel, event: event) if contents["json"]["graph-update"]["add-graph"]
26
+ return AddNodesFact.new(channel: channel, event: event) if contents["json"]["graph-update"]["add-nodes"]
27
+ return RemoveGraphFact.new(channel: channel, event: event) if contents["json"]["graph-update"]["remove-graph"]
28
+ end
29
+
30
+ if (c = contents["json"]["groupUpdate"])
31
+ return AddGroupFact.new(channel: channel, event: event) if c["addGroup"]
32
+ return AddGroupMemberFact.new(channel: channel, event: event) if c["addMembers"]
33
+ return AddTagFact.new(channel: channel, event: event) if c["addTag"]
34
+ return InitialGroupFact.new(channel: channel, event: event) if c["initial"]
35
+ return InitialGroupGroupFact.new(channel: channel, event: event) if c["initialGroup"]
36
+ return RemoveGroupMemberFact.new(channel: channel, event: event) if c["removeMembers"]
37
+ return RemoveTagFact.new(channel: channel, event: event) if c["removeTag"]
38
+ end
39
+
40
+ if (c = contents["json"]["metadata-update"])
41
+ return MetadataUpdateFact.new(channel: channel, event: event) if contents["json"]["metadata-update"]
42
+ end
43
+
44
+ if (c = contents["json"]["settings-event"])
45
+ return SettingsEventDelBucketFact.new(channel: channel, event: event) if c["del-bucket"]
46
+ return SettingsEventDelEntryFact.new(channel: channel, event: event) if c["del-entry"]
47
+ return SettingsEventPutBucketFact.new(channel: channel, event: event) if c["put-bucket"]
48
+ return SettingsEventPutEntryFact.new(channel: channel, event: event) if c["put-entry"]
49
+ end
50
+
51
+ return BaseFact.new(channel: channel, event: event)
18
52
  end
19
53
  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
54
  end
66
55
  end