urbit-api 0.1.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 +7 -0
- data/.gitignore +25 -0
- data/.rspec +1 -0
- data/CHANGELOG.md +1 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.gem.md +4 -0
- data/README.md +107 -0
- data/Rakefile +10 -0
- data/_config.yml +2 -0
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/bin/test +2 -0
- data/lib/urbit/ack_message.rb +18 -0
- data/lib/urbit/api.rb +26 -0
- data/lib/urbit/api/version.rb +5 -0
- data/lib/urbit/channel.rb +79 -0
- data/lib/urbit/config.rb +36 -0
- data/lib/urbit/message.rb +72 -0
- data/lib/urbit/receiver.rb +27 -0
- data/lib/urbit/ship.rb +88 -0
- data/lib/urbit/subscribe_message.rb +19 -0
- data/lib/urbit/urbit.rb +24 -0
- data/urbit-api.gemspec +37 -0
- metadata +126 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 626e3718491acdc2cd451fc847e489bac5bb4eb1490797bf6417fb9352c8b17b
|
|
4
|
+
data.tar.gz: a744f2e30e52b901d1e681bdb8a2109f48facd9bcdc45cfc9148a11a0f32d059
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 31738b651665457fb50113b26e6f3fe319473bc8112c01ba9fedc58f27c474a62a40a1619ee0c1c765dbf70582f61c54885521a3b53c91bcd30b963ff6ca0d5b
|
|
7
|
+
data.tar.gz: 36f2bcab1490c8dfe2b83cd875dba0d9571f53f65e7760d0cdfd38ccd8b5eb21753cf039cda46d11cff9f493d9cf4d818397ec36a8b66ea334e79459f8cf3d1c
|
data/.gitignore
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
_config-*.yml
|
|
2
|
+
*.gem
|
|
3
|
+
*.rbc
|
|
4
|
+
/coverage/
|
|
5
|
+
/pkg/
|
|
6
|
+
/test/tmp/
|
|
7
|
+
/test/version_tmp/
|
|
8
|
+
/tmp/
|
|
9
|
+
|
|
10
|
+
## Documentation cache and generated files:
|
|
11
|
+
/.yardoc/
|
|
12
|
+
/_yardoc/
|
|
13
|
+
/doc/
|
|
14
|
+
/rdoc/
|
|
15
|
+
|
|
16
|
+
## Environment normalization:
|
|
17
|
+
/.bundle/
|
|
18
|
+
/vendor/bundle
|
|
19
|
+
/lib/bundler/man/
|
|
20
|
+
|
|
21
|
+
# for a library or gem, you might want to ignore these files since the code is
|
|
22
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
23
|
+
Gemfile.lock
|
|
24
|
+
.ruby-version
|
|
25
|
+
# .ruby-gemset
|
data/.rspec
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--require spec_helper
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Nothing to see here.
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 Daryl Richter
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.gem.md
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
|
|
2
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/urbit/ruby`. To experiment with that code, run `bin/console` for an interactive prompt.
|
|
3
|
+
|
|
4
|
+
TODO: Delete this and the text above, and describe your gem
|
data/README.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Urbit::Api
|
|
2
|
+
## The Ruby interface to the Urbit HTTP API
|
|
3
|
+
|
|
4
|
+
This library wraps the Urbit ship http interface exposing it as a Ruby gem.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
Add this line to your application's Gemfile:
|
|
9
|
+
|
|
10
|
+
```ruby
|
|
11
|
+
gem 'urbit-api'
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
And then execute:
|
|
15
|
+
|
|
16
|
+
$ bundle install
|
|
17
|
+
|
|
18
|
+
Or install it yourself as:
|
|
19
|
+
|
|
20
|
+
$ gem install urbit-api
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```rb
|
|
25
|
+
# TODO: fix namespacing :)
|
|
26
|
+
require 'urbit/urbit'
|
|
27
|
+
|
|
28
|
+
# This will instantiate a ship that connects to the fake `~zod` dev server by default
|
|
29
|
+
# See Urbit docs for more info: https://urbit.org/using/develop/
|
|
30
|
+
ship = Urbit.new
|
|
31
|
+
# => #<Urbit::Ship:0x00007fa74b87f920 ...
|
|
32
|
+
|
|
33
|
+
ship.logged_in?
|
|
34
|
+
# => false
|
|
35
|
+
|
|
36
|
+
ship.login
|
|
37
|
+
# => #<Urbit::Ship:0x00007fa74b87f920 ...
|
|
38
|
+
|
|
39
|
+
ship.logged_in?
|
|
40
|
+
# => true
|
|
41
|
+
|
|
42
|
+
channel = ship.open_channel('my-channel')
|
|
43
|
+
# => #<Urbit::Channel:0x00007fa74b291e50 ...
|
|
44
|
+
|
|
45
|
+
channel.key
|
|
46
|
+
# => "16142890875c348d"
|
|
47
|
+
|
|
48
|
+
ship.channels.first.key
|
|
49
|
+
# => "16142890875c348d"
|
|
50
|
+
|
|
51
|
+
receiver = channel.subscribe(app: 'graph-store', path: '/updates')
|
|
52
|
+
# => #<Urbit::Receiver:0x00007fd3928eba58
|
|
53
|
+
|
|
54
|
+
# This receiver will now be listening on the app and path you specified. Each time an event is sent in it will be stored in the receiver's events collection.
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Configuration
|
|
58
|
+
|
|
59
|
+
Configure your ship using a config file or constructor keyword arguments. Either or both can be used; the keyword args will override any values set via config file.
|
|
60
|
+
|
|
61
|
+
Supported keys:
|
|
62
|
+
- `code` - the auth code
|
|
63
|
+
- `host` - the ship's host (e.g., 'localhost' or 'myship.net')
|
|
64
|
+
- `name` - the ship's name (e.g, '~zod')
|
|
65
|
+
- `port` - the open www port on your ship ('80' by default)
|
|
66
|
+
|
|
67
|
+
#### Config File
|
|
68
|
+
|
|
69
|
+
See [`_config.yml`](_config.yml) for an example config file. This will connect to a local fake zod, see creation instructions below.
|
|
70
|
+
|
|
71
|
+
```rb
|
|
72
|
+
ship = Urbit.new(config_file: 'my-moon.yml')
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
#### Constructor Keyword Arguments
|
|
76
|
+
|
|
77
|
+
```rb
|
|
78
|
+
ship = Urbit.new(host: '127.0.0.1', port: '8080')
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Testing
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
bin/test
|
|
85
|
+
```
|
|
86
|
+
### ~zod
|
|
87
|
+
|
|
88
|
+
Tests assume that an instance of a ["fake" development Urbit ship](https://urbit.org/using/develop/) (one not connected to the live network) will be running, available at `http://localhost:8080`.
|
|
89
|
+
|
|
90
|
+
To create a development ship:
|
|
91
|
+
```sh
|
|
92
|
+
./urbit -F zod
|
|
93
|
+
```
|
|
94
|
+
## Development
|
|
95
|
+
|
|
96
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
97
|
+
|
|
98
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
99
|
+
|
|
100
|
+
## Contributing
|
|
101
|
+
|
|
102
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/urbit-api.
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
## License
|
|
106
|
+
|
|
107
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/_config.yml
ADDED
data/bin/console
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "bundler/setup"
|
|
4
|
+
require "pry"
|
|
5
|
+
require "urbit/urbit"
|
|
6
|
+
|
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
9
|
+
|
|
10
|
+
puts "e.g., ship = Urbit.new(config_file: 'my_config.yml')"
|
|
11
|
+
Pry.start
|
data/bin/setup
ADDED
data/bin/test
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
require 'urbit/message'
|
|
4
|
+
|
|
5
|
+
module Urbit
|
|
6
|
+
class AckMessage < Message
|
|
7
|
+
def initialize(channel, sse_message_id)
|
|
8
|
+
@action = 'ack'
|
|
9
|
+
@channel = channel
|
|
10
|
+
@id = 0
|
|
11
|
+
@ack_id = sse_message_id
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def to_h
|
|
15
|
+
{'id' => id, 'action' => action, 'event-id' => @ack_id}
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
data/lib/urbit/api.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require "urbit/api/version"
|
|
2
|
+
|
|
3
|
+
module Urbit
|
|
4
|
+
module Api
|
|
5
|
+
class Config
|
|
6
|
+
def initialize
|
|
7
|
+
require 'yaml'
|
|
8
|
+
config_file = YAML.load_file('_config.yml.example')
|
|
9
|
+
@ship_code = config_file['code']
|
|
10
|
+
@ship_name = config_file['ship']
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def ship_code
|
|
14
|
+
@ship_code
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def ship_name
|
|
18
|
+
@ship_name
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class Error < StandardError;
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require 'faraday'
|
|
2
|
+
require 'securerandom'
|
|
3
|
+
|
|
4
|
+
require 'urbit/message'
|
|
5
|
+
require 'urbit/receiver'
|
|
6
|
+
require 'urbit/subscribe_message'
|
|
7
|
+
|
|
8
|
+
module Urbit
|
|
9
|
+
class Channel
|
|
10
|
+
attr_accessor :messages
|
|
11
|
+
attr_reader :key, :name, :ship
|
|
12
|
+
|
|
13
|
+
def initialize(ship, name)
|
|
14
|
+
@ship = ship
|
|
15
|
+
@key = "#{Time.now.to_i}#{SecureRandom.hex(3)}"
|
|
16
|
+
@messages = []
|
|
17
|
+
@name = name
|
|
18
|
+
@is_open = false
|
|
19
|
+
@is_subscribed = false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def close
|
|
23
|
+
# puts "closing #{name}"
|
|
24
|
+
m = Urbit::CloseMessage.new(self)
|
|
25
|
+
@is_open = !self.send_message(m)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def closed?
|
|
29
|
+
!@is_open
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def open(a_message_string)
|
|
33
|
+
m = Urbit::Message.new(self, "poke", "hood", "helm-hi", a_message_string)
|
|
34
|
+
@is_open = self.send_message(m)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def open?
|
|
38
|
+
@is_open
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def queue_message(a_message)
|
|
42
|
+
a_message.id = self.sent_messages.size + 1
|
|
43
|
+
@messages << a_message
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Answers true if message was successfully sent.
|
|
47
|
+
def send_message(a_message)
|
|
48
|
+
self.queue_message(a_message)
|
|
49
|
+
resp = a_message.transmit
|
|
50
|
+
resp.reason_phrase == "ok"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def sent_messages
|
|
54
|
+
@messages
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def status
|
|
58
|
+
self.open? ? "Open" : "Closed"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def subscribe(app, path)
|
|
62
|
+
m = Urbit::SubscribeMessage.new(self, app, path)
|
|
63
|
+
@is_subscribed = self.send_message(m)
|
|
64
|
+
receiver = Urbit::Receiver.new(self)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def subscribed?
|
|
68
|
+
@is_subscribed
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def to_s
|
|
72
|
+
"a Channel (#{self.status}) on #{self.ship.name}(name: '#{self.name}', key: '#{self.key}')"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def url
|
|
76
|
+
"http://localhost:8080/~/channel/#{self.key}"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
data/lib/urbit/config.rb
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
|
|
3
|
+
module Urbit
|
|
4
|
+
# Injected into a Ship to provide configuration
|
|
5
|
+
class Config
|
|
6
|
+
attr_reader :code, :config_file, :host, :port, :name
|
|
7
|
+
|
|
8
|
+
DEFAULT_CODE = 'lidlut-tabwed-pillex-ridrup'.freeze
|
|
9
|
+
DEFAULT_CONFIG_FILE = '_config.yml'.freeze
|
|
10
|
+
DEFAULT_HOST = 'http://localhost'.freeze
|
|
11
|
+
DEFAULT_PORT = '8080'.freeze
|
|
12
|
+
DEFAULT_NAME = '~zod'.freeze
|
|
13
|
+
|
|
14
|
+
def initialize(code: nil, config_file: nil, host: nil, name: nil, port: nil)
|
|
15
|
+
@config_file = config_file || DEFAULT_CONFIG_FILE
|
|
16
|
+
@code = code || loaded_config['code'] || DEFAULT_CODE
|
|
17
|
+
@host = host || loaded_config['host'] || DEFAULT_HOST
|
|
18
|
+
@name = name || loaded_config['ship'] || DEFAULT_NAME
|
|
19
|
+
@port = port || loaded_config['port'] || DEFAULT_PORT
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def api_base_url
|
|
23
|
+
@api_base_url ||= "#{host}:#{port}"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def loaded_config
|
|
29
|
+
@loaded_config ||= begin
|
|
30
|
+
return {} unless File.exist?(config_file)
|
|
31
|
+
|
|
32
|
+
YAML.load_file(config_file)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
module Urbit
|
|
4
|
+
class Message
|
|
5
|
+
attr_accessor :id
|
|
6
|
+
attr_reader :action, :app, :channel, :json, :mark
|
|
7
|
+
|
|
8
|
+
def initialize(channel, action, app, mark, json)
|
|
9
|
+
@action = action
|
|
10
|
+
@app = app
|
|
11
|
+
@channel = channel
|
|
12
|
+
@id = 0
|
|
13
|
+
@json = json
|
|
14
|
+
@mark = mark
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def channel_url
|
|
18
|
+
"#{self.ship.config.api_base_url}/~/channel/#{self.channel.key}"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def request_body
|
|
22
|
+
self.to_a.to_json
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def ship
|
|
26
|
+
self.channel.ship
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def to_a
|
|
30
|
+
[self.to_h]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def to_h
|
|
34
|
+
{
|
|
35
|
+
action: action,
|
|
36
|
+
app: app,
|
|
37
|
+
id: id,
|
|
38
|
+
json: json,
|
|
39
|
+
mark: mark,
|
|
40
|
+
ship: ship.untilded_name
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def to_s
|
|
45
|
+
"a Message(#{self.to_h})"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def transmit
|
|
49
|
+
response = Faraday.put(channel_url) do |req|
|
|
50
|
+
req.headers['Cookie'] = self.ship.cookie
|
|
51
|
+
req.headers['Content-Type'] = 'application/json'
|
|
52
|
+
req.body = request_body
|
|
53
|
+
# puts req.body.to_s
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# TODO: handle_error if response.status != 204
|
|
57
|
+
response
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
class CloseMessage < Message
|
|
62
|
+
def initialize(channel)
|
|
63
|
+
@action = 'delete'
|
|
64
|
+
@channel = channel
|
|
65
|
+
@id = 0
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def to_h
|
|
69
|
+
{id: id, action: action}
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'ld-eventsource'
|
|
2
|
+
|
|
3
|
+
require 'urbit/ack_message'
|
|
4
|
+
|
|
5
|
+
module Urbit
|
|
6
|
+
class Receiver < SSE::Client
|
|
7
|
+
attr_accessor :events
|
|
8
|
+
|
|
9
|
+
def initialize(channel)
|
|
10
|
+
@events = []
|
|
11
|
+
@headers = {'cookie' => channel.ship.cookie}
|
|
12
|
+
super(channel.url, {headers: @headers}) do |rec|
|
|
13
|
+
rec.on_event do |event|
|
|
14
|
+
typ = event.type
|
|
15
|
+
dat = JSON.parse(event.data)
|
|
16
|
+
self.events << {typ => dat}
|
|
17
|
+
channel.send_message(AckMessage.new(channel, event.id))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
rec.on_error do |error|
|
|
21
|
+
self.events += ["I received an error: #{error.class}"]
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
end
|
data/lib/urbit/ship.rb
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require 'faraday'
|
|
2
|
+
|
|
3
|
+
require 'urbit/channel'
|
|
4
|
+
require 'urbit/config'
|
|
5
|
+
|
|
6
|
+
module Urbit
|
|
7
|
+
class Ship
|
|
8
|
+
attr_accessor :logged_in
|
|
9
|
+
attr_reader :auth_cookie, :channels, :config
|
|
10
|
+
|
|
11
|
+
def initialize(config: Config.new)
|
|
12
|
+
@auth_cookie = nil
|
|
13
|
+
@channels = []
|
|
14
|
+
@config = config
|
|
15
|
+
@logged_in = false
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.finalize(channels)
|
|
19
|
+
proc { channels.each { |c| c.close } }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def logged_in?
|
|
23
|
+
logged_in
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def cookie
|
|
27
|
+
auth_cookie
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def login
|
|
31
|
+
return self if logged_in?
|
|
32
|
+
|
|
33
|
+
ensure_connections_closed
|
|
34
|
+
response = Faraday.post(login_url, "password=#{config.code}")
|
|
35
|
+
parse_cookie(response)
|
|
36
|
+
self
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def name
|
|
40
|
+
config.name
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def untilded_name
|
|
44
|
+
name.gsub('~', '')
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def pat_p
|
|
48
|
+
config.name
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Opening a channel always creates a new channel which will
|
|
52
|
+
# remain open until this ship is disconnected at which point it
|
|
53
|
+
# will be closed.
|
|
54
|
+
def open_channel(a_name)
|
|
55
|
+
login
|
|
56
|
+
(c = Channel.new self, a_name).open("Opening Airlock")
|
|
57
|
+
self.channels << c
|
|
58
|
+
c
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def open_channels
|
|
62
|
+
@channels.select {|c| c.open?}
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def to_s
|
|
66
|
+
"a Ship(name: '#{self.pat_p}', host: '#{self.config.host}', port: '#{self.config.port}')"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def ensure_connections_closed
|
|
72
|
+
# Make sure all our created channels are closed by the GC
|
|
73
|
+
ObjectSpace.define_finalizer( self, self.class.finalize(channels) )
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def parse_cookie(resp)
|
|
77
|
+
cookie = resp.headers['set-cookie']
|
|
78
|
+
return unless cookie
|
|
79
|
+
|
|
80
|
+
@auth_cookie, @path, @max_age = cookie.split(';')
|
|
81
|
+
self.logged_in = true if @auth_cookie
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def login_url
|
|
85
|
+
"#{config.api_base_url}/~/login"
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
module Urbit
|
|
4
|
+
class SubscribeMessage < Message
|
|
5
|
+
attr_reader :path
|
|
6
|
+
|
|
7
|
+
def initialize(channel, app, path)
|
|
8
|
+
@action = 'subscribe'
|
|
9
|
+
@app = app
|
|
10
|
+
@channel = channel
|
|
11
|
+
@id = 0
|
|
12
|
+
@path = path
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_h
|
|
16
|
+
{action: action, app: app, id: id, path: path, ship: ship.untilded_name}
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
data/lib/urbit/urbit.rb
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require_relative './config'
|
|
2
|
+
require_relative './ship'
|
|
3
|
+
|
|
4
|
+
# This is the main namespace for Urbit.
|
|
5
|
+
#
|
|
6
|
+
# It provides a method to create {Urbit::Ship} objects.
|
|
7
|
+
#
|
|
8
|
+
# @example Helpful class method `.new` to create {Urbit::Ship} objects.
|
|
9
|
+
# ship = Urbit.new(port: 80)
|
|
10
|
+
# conn.get '/'
|
|
11
|
+
module Urbit
|
|
12
|
+
class << self
|
|
13
|
+
def connect(**config_options)
|
|
14
|
+
config = Urbit::Config.new(**config_options)
|
|
15
|
+
ship = Urbit::Ship.new(config: config)
|
|
16
|
+
ship.login
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def new(**config_options)
|
|
20
|
+
config = Urbit::Config.new(**config_options)
|
|
21
|
+
Urbit::Ship.new(config: config)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
data/urbit-api.gemspec
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require_relative 'lib/urbit/api/version'
|
|
2
|
+
|
|
3
|
+
Gem::Specification.new do |spec|
|
|
4
|
+
spec.name = "urbit-api"
|
|
5
|
+
spec.version = Urbit::Api::VERSION
|
|
6
|
+
spec.authors = ["Daryl Richter"]
|
|
7
|
+
spec.email = ["daryl@deliverycircle.com"]
|
|
8
|
+
|
|
9
|
+
spec.summary = %q{The Ruby interface to the Urbit HTTP API}
|
|
10
|
+
spec.description = %q{Access your urbit ship the ruby way. It's a Martian gem.}
|
|
11
|
+
spec.homepage = "https://www.ngzax.com"
|
|
12
|
+
spec.license = "MIT"
|
|
13
|
+
|
|
14
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.7.2")
|
|
15
|
+
|
|
16
|
+
# spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
|
17
|
+
|
|
18
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
19
|
+
spec.metadata["source_code_uri"] = "https://github.com/Zaxonomy/urbit-ruby"
|
|
20
|
+
spec.metadata["changelog_uri"] = "https://github.com/Zaxonomy/urbit-ruby/CHANGELOG.md"
|
|
21
|
+
|
|
22
|
+
# Specify which files should be added to the gem when it is released.
|
|
23
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
24
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
|
25
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
spec.bindir = "exe"
|
|
29
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
30
|
+
spec.require_paths = ["lib"]
|
|
31
|
+
|
|
32
|
+
spec.add_dependency "faraday", "~> 1.3.0"
|
|
33
|
+
spec.add_dependency "ld-eventsource", "~> 2.0.0"
|
|
34
|
+
|
|
35
|
+
spec.add_development_dependency "pry", "~> 0.13"
|
|
36
|
+
spec.add_development_dependency "rspec", "~> 3.10"
|
|
37
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: urbit-api
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Daryl Richter
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2021-02-26 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: faraday
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 1.3.0
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 1.3.0
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: ld-eventsource
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 2.0.0
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: 2.0.0
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: pry
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0.13'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0.13'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rspec
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '3.10'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '3.10'
|
|
69
|
+
description: Access your urbit ship the ruby way. It's a Martian gem.
|
|
70
|
+
email:
|
|
71
|
+
- daryl@deliverycircle.com
|
|
72
|
+
executables: []
|
|
73
|
+
extensions: []
|
|
74
|
+
extra_rdoc_files: []
|
|
75
|
+
files:
|
|
76
|
+
- ".gitignore"
|
|
77
|
+
- ".rspec"
|
|
78
|
+
- ".ruby-version"
|
|
79
|
+
- CHANGELOG.md
|
|
80
|
+
- Gemfile
|
|
81
|
+
- LICENSE.txt
|
|
82
|
+
- README.gem.md
|
|
83
|
+
- README.md
|
|
84
|
+
- Rakefile
|
|
85
|
+
- _config.yml
|
|
86
|
+
- bin/console
|
|
87
|
+
- bin/setup
|
|
88
|
+
- bin/test
|
|
89
|
+
- lib/urbit/ack_message.rb
|
|
90
|
+
- lib/urbit/api.rb
|
|
91
|
+
- lib/urbit/api/version.rb
|
|
92
|
+
- lib/urbit/channel.rb
|
|
93
|
+
- lib/urbit/config.rb
|
|
94
|
+
- lib/urbit/message.rb
|
|
95
|
+
- lib/urbit/receiver.rb
|
|
96
|
+
- lib/urbit/ship.rb
|
|
97
|
+
- lib/urbit/subscribe_message.rb
|
|
98
|
+
- lib/urbit/urbit.rb
|
|
99
|
+
- urbit-api.gemspec
|
|
100
|
+
homepage: https://www.ngzax.com
|
|
101
|
+
licenses:
|
|
102
|
+
- MIT
|
|
103
|
+
metadata:
|
|
104
|
+
homepage_uri: https://www.ngzax.com
|
|
105
|
+
source_code_uri: https://github.com/Zaxonomy/urbit-ruby
|
|
106
|
+
changelog_uri: https://github.com/Zaxonomy/urbit-ruby/CHANGELOG.md
|
|
107
|
+
post_install_message:
|
|
108
|
+
rdoc_options: []
|
|
109
|
+
require_paths:
|
|
110
|
+
- lib
|
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
112
|
+
requirements:
|
|
113
|
+
- - ">="
|
|
114
|
+
- !ruby/object:Gem::Version
|
|
115
|
+
version: 2.7.2
|
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
117
|
+
requirements:
|
|
118
|
+
- - ">="
|
|
119
|
+
- !ruby/object:Gem::Version
|
|
120
|
+
version: '0'
|
|
121
|
+
requirements: []
|
|
122
|
+
rubygems_version: 3.1.4
|
|
123
|
+
signing_key:
|
|
124
|
+
specification_version: 4
|
|
125
|
+
summary: The Ruby interface to the Urbit HTTP API
|
|
126
|
+
test_files: []
|