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 +4 -4
- data/lib/urbit/bucket.rb +45 -0
- data/lib/urbit/channel.rb +4 -5
- data/lib/urbit/fact/base_fact.rb +99 -0
- data/lib/urbit/fact/graph_fact.rb +92 -0
- data/lib/urbit/fact/group_fact.rb +124 -0
- data/lib/urbit/fact/settings_fact.rb +120 -0
- data/lib/urbit/fact.rb +44 -60
- data/lib/urbit/graph.rb +3 -2
- data/lib/urbit/group.rb +109 -0
- data/lib/urbit/group_manager.rb +100 -0
- data/lib/urbit/group_parser.rb +71 -0
- data/lib/urbit/message.rb +2 -2
- data/lib/urbit/node.rb +45 -5
- data/lib/urbit/parser.rb +23 -3
- data/lib/urbit/poke_message.rb +2 -2
- data/lib/urbit/receiver.rb +15 -5
- data/lib/urbit/settings.rb +103 -0
- data/lib/urbit/ship.rb +63 -28
- data/lib/urbit/version.rb +5 -0
- data/lib/{urbit/urbit.rb → urbit.rb} +3 -2
- data/urbit-api.gemspec +8 -9
- metadata +33 -30
- data/.gitignore +0 -25
- data/.rspec +0 -1
- data/.ruby-version +0 -1
- data/CHANGELOG.md +0 -1
- data/Gemfile +0 -6
- data/LICENSE.txt +0 -21
- data/README.gem.md +0 -4
- data/README.md +0 -237
- data/Rakefile +0 -10
- data/_config.yml +0 -2
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/bin/test +0 -2
- data/lib/urbit/api/version.rb +0 -5
- data/misc/graph-store_graph +0 -51
- data/misc/graph-store_keys +0 -15
- data/misc/graph-store_node +0 -34
- data/misc/graph-store_update +0 -76
- data/misc/graph-update_add-graph +0 -20
- data/misc/graph-update_add-nodes +0 -75
- data/misc/post +0 -12
    
        data/lib/urbit/group.rb
    ADDED
    
    | @@ -0,0 +1,109 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Urbit
         | 
| 4 | 
            +
              class Group
         | 
| 5 | 
            +
                 attr_accessor :manager, :members, :tags
         | 
| 6 | 
            +
                 attr_reader :hidden, :path, :policy
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                def initialize(path:, members:, policy:, tags:, hidden:)
         | 
| 9 | 
            +
                  @hidden  = hidden
         | 
| 10 | 
            +
                  @manager = nil
         | 
| 11 | 
            +
                  @members = Set.new(members)
         | 
| 12 | 
            +
                  @path    = path
         | 
| 13 | 
            +
                  @policy  = policy
         | 
| 14 | 
            +
                  @tags    = self.parse_tags(tags)
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def ==(another_group)
         | 
| 18 | 
            +
                  another_group.path == self.path
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def <=>(another_group)
         | 
| 22 | 
            +
                  self.path <=> another_group.path
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                #
         | 
| 26 | 
            +
                # This is the action labeled as "Archive" in the Landscape UI.
         | 
| 27 | 
            +
                # As of now, you can only do this to groups on your own ship.
         | 
| 28 | 
            +
                #
         | 
| 29 | 
            +
                def delete
         | 
| 30 | 
            +
                  if (self.host == self.manager.ship.name)
         | 
| 31 | 
            +
                    spdr = self.manager.spider('group-delete', %Q({"remove": {"ship": "#{self.host}", "name": "#{self.key}"}}))
         | 
| 32 | 
            +
                    self.manager.remove(self) if 200 == spdr[:status]
         | 
| 33 | 
            +
                    return spdr
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                  {status: 400, code: 'bad_request', body: 'Can only delete Groups on your own ship.'}
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                def eql?(another_group)
         | 
| 39 | 
            +
                  another_group.path == self.path
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                def host
         | 
| 43 | 
            +
                  self.path_tokens[0]
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                def invite(ship_names:, message:)
         | 
| 47 | 
            +
                  data = %Q({
         | 
| 48 | 
            +
                    "invite": {
         | 
| 49 | 
            +
                      "resource": {
         | 
| 50 | 
            +
                        "ship": "#{self.host}",
         | 
| 51 | 
            +
                        "name": "#{self.key}"
         | 
| 52 | 
            +
                      },
         | 
| 53 | 
            +
                      "ships": [
         | 
| 54 | 
            +
                        "#{ship_names.join(',')}"
         | 
| 55 | 
            +
                      ],
         | 
| 56 | 
            +
                      "description": "#{message}"
         | 
| 57 | 
            +
                    }
         | 
| 58 | 
            +
                  })
         | 
| 59 | 
            +
                  self.manager.spider('group-invite', data)
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                def key
         | 
| 63 | 
            +
                  self.path_tokens[1]
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                def leave
         | 
| 67 | 
            +
                  spdr = self.manager.spider('group-leave', %Q({"leave": {"ship": "#{self.host}", "name": "#{self.key}"}}))
         | 
| 68 | 
            +
                  self.manager.remove(self) if 200 == spdr[:status]
         | 
| 69 | 
            +
                  spdr
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                def path_tokens
         | 
| 73 | 
            +
                  self.path.split('/')
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                def pending_invites
         | 
| 77 | 
            +
                  if (i = @policy["invite"])
         | 
| 78 | 
            +
                    if (p = i["pending"])
         | 
| 79 | 
            +
                      return p.count
         | 
| 80 | 
            +
                    end
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
                  '?'
         | 
| 83 | 
            +
                end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                def to_h
         | 
| 86 | 
            +
                {
         | 
| 87 | 
            +
                    host:            self.host,
         | 
| 88 | 
            +
                    key:             self.key,
         | 
| 89 | 
            +
                    member_count:    self.members.count,
         | 
| 90 | 
            +
                    pending_invites: self.pending_invites,
         | 
| 91 | 
            +
                    hidden:          self.hidden
         | 
| 92 | 
            +
                  }
         | 
| 93 | 
            +
                end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                def to_s
         | 
| 96 | 
            +
                  "a Group(#{self.to_h})"
         | 
| 97 | 
            +
                end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                private
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                def parse_tags(tags)
         | 
| 102 | 
            +
                  h = {}
         | 
| 103 | 
            +
                  return h if tags.empty?
         | 
| 104 | 
            +
                  tags.each {|k, v| h[k] = Set.new(v)}
         | 
| 105 | 
            +
                  tags.replace(h)
         | 
| 106 | 
            +
                end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
              end
         | 
| 109 | 
            +
            end
         | 
| @@ -0,0 +1,100 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Urbit
         | 
| 4 | 
            +
              class GroupManager
         | 
| 5 | 
            +
                attr_accessor :groups, :ship
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def initialize(ship:)
         | 
| 8 | 
            +
                  @ship   = ship
         | 
| 9 | 
            +
                  @groups = []
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                #
         | 
| 13 | 
            +
                # Adds a Group to this Manager's groups collection
         | 
| 14 | 
            +
                #
         | 
| 15 | 
            +
                def add(a_group)
         | 
| 16 | 
            +
                  @groups << a_group
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def add_members(group_path:, ships:)
         | 
| 20 | 
            +
                  if (group = self.find(path: group_path))
         | 
| 21 | 
            +
                    group.members += ships
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def add_tag(group_path:, ships:, tag:)
         | 
| 26 | 
            +
                  if (group = self.find(path: group_path))
         | 
| 27 | 
            +
                    if (group.tags.include? tag)
         | 
| 28 | 
            +
                      group.tags[tag] += ships
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                def create(name:, title:, description:)
         | 
| 34 | 
            +
                  self.spider('group-create', %Q({"create": {"name": "#{name}", "title": "#{title}", "description": "#{description}", "policy": {"open": {"banRanks": [], "banned": []}}}}))
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                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
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                def join(host:, name:, share_contact: false, auto_join: false)
         | 
| 58 | 
            +
                  data = {join: {resource: {ship: "#{host}", name: "#{name}"}, ship: "#{host}", shareContact: share_contact, app: "groups", autojoin: auto_join}}
         | 
| 59 | 
            +
                  self.ship.poke(app: 'group-view', mark: 'group-view-action', message: data)
         | 
| 60 | 
            +
                  nil
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                def list
         | 
| 64 | 
            +
                  self.groups.map {|g| g.path}.join("\n")
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                def remove(group)
         | 
| 68 | 
            +
                  @groups = self.groups.filter {|g| g != group}
         | 
| 69 | 
            +
                end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                def remove_members(group_path:, ships:)
         | 
| 72 | 
            +
                  if (group = self.find(path: group_path))
         | 
| 73 | 
            +
                    group.members -= ships
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                def remove_tag(group_path:, ships:, tag:)
         | 
| 78 | 
            +
                  if (group = self.find(path: group_path))
         | 
| 79 | 
            +
                    if (group.tags.include? tag)
         | 
| 80 | 
            +
                      group.tags[tag] -= ships
         | 
| 81 | 
            +
                    end
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
                end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                def load
         | 
| 86 | 
            +
                  if self.ship.logged_in?
         | 
| 87 | 
            +
                    self.ship.subscribe(app: 'group-store', path: '/groups')
         | 
| 88 | 
            +
                  end
         | 
| 89 | 
            +
                  nil
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                def spider(thread, data)
         | 
| 93 | 
            +
                  self.ship.spider(mark_in: 'group-view-action', mark_out: 'json', thread: thread, data: data)
         | 
| 94 | 
            +
                end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                def to_s
         | 
| 97 | 
            +
                  self.groups.sort.each {|g| puts g}
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
              end
         | 
| 100 | 
            +
            end
         | 
| @@ -0,0 +1,71 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'urbit/parser'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Urbit
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              class GroupParser < Parser
         | 
| 8 | 
            +
                def resource
         | 
| 9 | 
            +
                  "~#{self.resource_hash["ship"]}/#{self.resource_hash["name"]}"
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def resource_hash
         | 
| 13 | 
            +
                  @j["resource"]
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              class AddGroupParser < GroupParser
         | 
| 18 | 
            +
                def group
         | 
| 19 | 
            +
                  Urbit::Group.new(path:    self.resource,
         | 
| 20 | 
            +
                                   members: [],
         | 
| 21 | 
            +
                                   policy:  @j["policy"],
         | 
| 22 | 
            +
                                   tags:    [],
         | 
| 23 | 
            +
                                   hidden:  @j["hidden"])
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              class ChangeTagParser < GroupParser
         | 
| 28 | 
            +
                def ships
         | 
| 29 | 
            +
                  @j["ships"]
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def tag
         | 
| 33 | 
            +
                  @j["tag"]["tag"]
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              class ChangeMemberParser < GroupParser
         | 
| 38 | 
            +
                def ships
         | 
| 39 | 
            +
                  @j["ships"]
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              class InitialGroupParser < Parser
         | 
| 44 | 
            +
                def groups
         | 
| 45 | 
            +
                  self.group_hashes.collect {|k, v| Group.new(path:    k.sub('/ship/', ''),
         | 
| 46 | 
            +
                                                              members: v["members"],
         | 
| 47 | 
            +
                                                              policy:  v["policy"],
         | 
| 48 | 
            +
                                                              tags:    v["tags"],
         | 
| 49 | 
            +
                                                              hidden:  v["hidden"])}
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                def group_hashes
         | 
| 53 | 
            +
                  @j
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
              class InitialGroupGroupParser < GroupParser
         | 
| 58 | 
            +
                def group
         | 
| 59 | 
            +
                  Urbit::Group.new(path:    self.resource,
         | 
| 60 | 
            +
                                   members: self.group_hash["members"],
         | 
| 61 | 
            +
                                   policy:  self.group_hash["policy"],
         | 
| 62 | 
            +
                                   tags:    self.group_hash["tags"],
         | 
| 63 | 
            +
                                   hidden:  self.group_hash["hidden"])
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                def group_hash
         | 
| 67 | 
            +
                  @j["group"]
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
            end
         | 
    
        data/lib/urbit/message.rb
    CHANGED
    
    | @@ -22,11 +22,11 @@ module Urbit | |
| 22 22 | 
             
                end
         | 
| 23 23 |  | 
| 24 24 | 
             
                def channel_url
         | 
| 25 | 
            -
                  "#{self.ship. | 
| 25 | 
            +
                  "#{self.ship.url}/~/channel/#{self.channel.key}"
         | 
| 26 26 | 
             
                end
         | 
| 27 27 |  | 
| 28 28 | 
             
                def request_body
         | 
| 29 | 
            -
                  self.to_a | 
| 29 | 
            +
                  JSON.generate(self.to_a)
         | 
| 30 30 | 
             
                end
         | 
| 31 31 |  | 
| 32 32 | 
             
                def ship
         | 
    
        data/lib/urbit/node.rb
    CHANGED
    
    | @@ -11,8 +11,30 @@ module Urbit | |
| 11 11 | 
             
                  @index      = nil
         | 
| 12 12 | 
             
                end
         | 
| 13 13 |  | 
| 14 | 
            +
                #
         | 
| 15 | 
            +
                # Given a bigint representing an urbit date, returns a unix timestamp.
         | 
| 16 | 
            +
                #
         | 
| 17 | 
            +
                def self.da_to_unix(da)
         | 
| 18 | 
            +
                  # ported from urbit lib.ts which in turn was ported from +time:enjs:format in hoon.hoon
         | 
| 19 | 
            +
                  da_second = 18446744073709551616
         | 
| 20 | 
            +
                  da_unix_epoch = 170141184475152167957503069145530368000
         | 
| 21 | 
            +
                  offset = da_second / 2000
         | 
| 22 | 
            +
                  epoch_adjusted = offset + (da - da_unix_epoch)
         | 
| 23 | 
            +
                  return (epoch_adjusted * 1000) / da_second
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                #
         | 
| 27 | 
            +
                # Given a unix timestamp, returns a bigint representing an urbit date
         | 
| 28 | 
            +
                #
         | 
| 29 | 
            +
                def self.unix_to_da(unix)
         | 
| 30 | 
            +
                  da_second = 18446744073709551616
         | 
| 31 | 
            +
                  da_unix_epoch = 170141184475152167957503069145530368000
         | 
| 32 | 
            +
                  time_since_epoch =  (unix * da_second) / 1000
         | 
| 33 | 
            +
                  return da_unix_epoch + time_since_epoch;
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 14 36 | 
             
                def ==(another_node)
         | 
| 15 | 
            -
                  another_node. | 
| 37 | 
            +
                  another_node.index == self.index
         | 
| 16 38 | 
             
                end
         | 
| 17 39 |  | 
| 18 40 | 
             
                def <=>(another_node)
         | 
| @@ -20,11 +42,16 @@ module Urbit | |
| 20 42 | 
             
                end
         | 
| 21 43 |  | 
| 22 44 | 
             
                def eql?(another_node)
         | 
| 23 | 
            -
                  another_node. | 
| 45 | 
            +
                  another_node.index == self.index
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                def deleted?
         | 
| 49 | 
            +
                  # This is a "deleted" node. Not sure what to do yet, but for now don't create a Node.
         | 
| 50 | 
            +
                  @post_h["index"].nil?
         | 
| 24 51 | 
             
                end
         | 
| 25 52 |  | 
| 26 53 | 
             
                def hash
         | 
| 27 | 
            -
                  self. | 
| 54 | 
            +
                  self.index.hash
         | 
| 28 55 | 
             
                end
         | 
| 29 56 |  | 
| 30 57 | 
             
                def author
         | 
| @@ -47,6 +74,10 @@ module Urbit | |
| 47 74 | 
             
                  @post_h['contents']
         | 
| 48 75 | 
             
                end
         | 
| 49 76 |  | 
| 77 | 
            +
                def datetime_sent
         | 
| 78 | 
            +
                  Time.at(self.time_sent / 1000).to_datetime
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
             | 
| 50 81 | 
             
                def persistent?
         | 
| 51 82 | 
             
                  @persistent
         | 
| 52 83 | 
             
                end
         | 
| @@ -76,9 +107,13 @@ module Urbit | |
| 76 107 | 
             
                end
         | 
| 77 108 |  | 
| 78 109 | 
             
                def raw_index
         | 
| 79 | 
            -
                  @post_h["index"].delete_prefix('/')
         | 
| 110 | 
            +
                  return @post_h["index"].delete_prefix('/') unless self.deleted?
         | 
| 111 | 
            +
                  (Node.unix_to_da(Time.now.to_i)).to_s
         | 
| 80 112 | 
             
                end
         | 
| 81 113 |  | 
| 114 | 
            +
                #
         | 
| 115 | 
            +
                # This is the time sent as recorded by urbit in unix extended format.
         | 
| 116 | 
            +
                #
         | 
| 82 117 | 
             
                def time_sent
         | 
| 83 118 | 
             
                  @post_h['time-sent']
         | 
| 84 119 | 
             
                end
         | 
| @@ -87,13 +122,17 @@ module Urbit | |
| 87 122 | 
             
                  {
         | 
| 88 123 | 
             
                    index: self.index,
         | 
| 89 124 | 
             
                    author: self.author,
         | 
| 125 | 
            +
                    sent: self.datetime_sent,
         | 
| 90 126 | 
             
                    contents: self.contents,
         | 
| 91 | 
            -
                    time_sent: self.time_sent,
         | 
| 92 127 | 
             
                    is_parent: !self.children.empty?,
         | 
| 93 128 | 
             
                    child_count: self.children.count
         | 
| 94 129 | 
             
                  }
         | 
| 95 130 | 
             
                end
         | 
| 96 131 |  | 
| 132 | 
            +
                def to_pretty_array
         | 
| 133 | 
            +
                  self.to_h.each.map {|k, v| "#{k}#{(' ' * (12 - k.length))}#{v}"}
         | 
| 134 | 
            +
                end
         | 
| 135 | 
            +
             | 
| 97 136 | 
             
                def to_s
         | 
| 98 137 | 
             
                  "a Node(#{self.to_h})"
         | 
| 99 138 | 
             
                end
         | 
| @@ -108,5 +147,6 @@ module Urbit | |
| 108 147 | 
             
                  end
         | 
| 109 148 | 
             
                  subatoms.join('/')
         | 
| 110 149 | 
             
                end
         | 
| 150 | 
            +
             | 
| 111 151 | 
             
              end
         | 
| 112 152 | 
             
            end
         | 
    
        data/lib/urbit/parser.rb
    CHANGED
    
    | @@ -3,9 +3,15 @@ require 'urbit/node' | |
| 3 3 |  | 
| 4 4 | 
             
            module Urbit
         | 
| 5 5 | 
             
              class Parser
         | 
| 6 | 
            +
                def initialize(with_json:)
         | 
| 7 | 
            +
                  @j = with_json
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              class GraphParser < Parser
         | 
| 6 12 | 
             
                def initialize(for_graph:, with_json:)
         | 
| 13 | 
            +
                  super(with_json: with_json)
         | 
| 7 14 | 
             
                  @g = for_graph
         | 
| 8 | 
            -
                  @j = with_json
         | 
| 9 15 | 
             
                end
         | 
| 10 16 |  | 
| 11 17 | 
             
                #
         | 
| @@ -33,16 +39,30 @@ module Urbit | |
| 33 39 | 
             
                end
         | 
| 34 40 | 
             
              end
         | 
| 35 41 |  | 
| 36 | 
            -
              class AddGraphParser <  | 
| 42 | 
            +
              class AddGraphParser < GraphParser
         | 
| 37 43 | 
             
                def nodes_hash
         | 
| 38 44 | 
             
                  @j["graph"]
         | 
| 39 45 | 
             
                end
         | 
| 40 46 |  | 
| 47 | 
            +
                def resource_hash
         | 
| 48 | 
            +
                  @j["resource"]
         | 
| 49 | 
            +
                end
         | 
| 41 50 | 
             
              end
         | 
| 42 51 |  | 
| 43 | 
            -
              class AddNodesParser <  | 
| 52 | 
            +
              class AddNodesParser < GraphParser
         | 
| 44 53 | 
             
                def nodes_hash
         | 
| 45 54 | 
             
                  @j["nodes"]
         | 
| 46 55 | 
             
                end
         | 
| 47 56 | 
             
              end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
              class RemoveGraphParser < GraphParser
         | 
| 59 | 
            +
                def nodes_hash
         | 
| 60 | 
            +
                  nil
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                def resource_hash
         | 
| 64 | 
            +
                  @j["resource"]
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
              end
         | 
| 67 | 
            +
             | 
| 48 68 | 
             
            end
         | 
    
        data/lib/urbit/poke_message.rb
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            module Urbit
         | 
| 2 2 | 
             
              class PokeMessage < Message
         | 
| 3 | 
            -
                def initialize(channel:, app:, mark:,  | 
| 4 | 
            -
                  super(channel: channel, app: app, mark: mark, contents:  | 
| 3 | 
            +
                def initialize(channel:, app:, mark:, a_message_hash:)
         | 
| 4 | 
            +
                  super(channel: channel, app: app, mark: mark, contents: a_message_hash)
         | 
| 5 5 | 
             
                end
         | 
| 6 6 | 
             
              end
         | 
| 7 7 | 
             
            end
         | 
    
        data/lib/urbit/receiver.rb
    CHANGED
    
    | @@ -1,19 +1,19 @@ | |
| 1 1 | 
             
            require 'ld-eventsource'
         | 
| 2 | 
            +
            require "logger"
         | 
| 2 3 |  | 
| 3 4 | 
             
            require 'urbit/ack_message'
         | 
| 4 5 | 
             
            require 'urbit/fact'
         | 
| 5 6 |  | 
| 6 7 | 
             
            module Urbit
         | 
| 7 8 | 
             
              class Receiver < SSE::Client
         | 
| 8 | 
            -
                attr_accessor :facts
         | 
| 9 | 
            +
                attr_accessor :errors, :facts
         | 
| 9 10 |  | 
| 10 11 | 
             
                def initialize(channel:)
         | 
| 11 | 
            -
                   | 
| 12 | 
            -
                  super(channel.url, {headers: self.headers(channel)}) do |rec|
         | 
| 12 | 
            +
                  super(channel.url, headers: self.headers(channel), logger: self.default_logger) do |rec|
         | 
| 13 13 | 
             
                    # We are now listening on a socket for SSE::Events. This block will be called for each one.
         | 
| 14 14 | 
             
                    rec.on_event do |event|
         | 
| 15 15 | 
             
                      # Wrap the returned event in a Fact.
         | 
| 16 | 
            -
                      @facts << (f = Fact. | 
| 16 | 
            +
                      @facts << (f = Fact.collect(channel: channel, event: event))
         | 
| 17 17 |  | 
| 18 18 | 
             
                      # We need to acknowlege each message or urbit will eventually disconnect us.
         | 
| 19 19 | 
             
                      # We record the ack with the Fact itself.
         | 
| @@ -22,12 +22,22 @@ module Urbit | |
| 22 22 | 
             
                    end
         | 
| 23 23 |  | 
| 24 24 | 
             
                    rec.on_error do |error|
         | 
| 25 | 
            -
                      self. | 
| 25 | 
            +
                      self.errors << ["I received an error fact: #{error.class}"]
         | 
| 26 26 | 
             
                    end
         | 
| 27 27 | 
             
                  end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  @errors   = []
         | 
| 30 | 
            +
                  @facts   = []
         | 
| 28 31 | 
             
                  @is_open = true
         | 
| 29 32 | 
             
                end
         | 
| 30 33 |  | 
| 34 | 
            +
                def default_logger
         | 
| 35 | 
            +
                  log           = ::Logger.new($stdout)
         | 
| 36 | 
            +
                  log.level     = ::Logger::WARN
         | 
| 37 | 
            +
                  log.progname  = 'ld-eventsource'
         | 
| 38 | 
            +
                  log
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 31 41 | 
             
                def open?
         | 
| 32 42 | 
             
                  @is_open
         | 
| 33 43 | 
             
                end
         | 
| @@ -0,0 +1,103 @@ | |
| 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 | 
            +
             | 
| 72 | 
            +
              class Settings < Set
         | 
| 73 | 
            +
                class << self
         | 
| 74 | 
            +
                  def load(ship:)
         | 
| 75 | 
            +
                    ship.subscribe(app: 'settings-store', path: '/all')
         | 
| 76 | 
            +
                    scry = ship.scry(app: "settings-store", path: "/all", mark: "json")
         | 
| 77 | 
            +
                    # scry = self.scry(app: "settings-store", path: "/desk/#{desk}", mark: "json")
         | 
| 78 | 
            +
                    s = Settings.new
         | 
| 79 | 
            +
                    if scry[:body]
         | 
| 80 | 
            +
                      body = JSON.parse scry[:body]
         | 
| 81 | 
            +
                      body["all"].each do |k, v|  # At this level the keys are the desks and the values are the buckets
         | 
| 82 | 
            +
                        s << Setting.new(ship: ship, desk: k, buckets: v)
         | 
| 83 | 
            +
                      end
         | 
| 84 | 
            +
                    end
         | 
| 85 | 
            +
                    s
         | 
| 86 | 
            +
                  end
         | 
| 87 | 
            +
                end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                def initialize
         | 
| 90 | 
            +
                  @hash    = {}
         | 
| 91 | 
            +
                end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                def [](desk:)
         | 
| 94 | 
            +
                  self.select {|s| desk == s.desk}.first
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                def list
         | 
| 98 | 
            +
                  self.each {|s| puts s.to_string}
         | 
| 99 | 
            +
                  nil
         | 
| 100 | 
            +
                end
         | 
| 101 | 
            +
              end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
            end
         |