urbit-api 0.2.1 → 0.5.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: 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