skynet_ruby 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 +5 -0
- data/.rspec +3 -0
- data/.rubocop.yml +19 -0
- data/.travis.yml +6 -0
- data/Gemfile +24 -0
- data/Gemfile.lock +93 -0
- data/LICENSE.txt +21 -0
- data/README.md +83 -0
- data/Rakefile +8 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/skynet.rb +10 -0
- data/lib/skynet/client.rb +245 -0
- data/lib/skynet/version.rb +5 -0
- data/sia_skynet.gemspec +31 -0
- metadata +61 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: f090c4c97ad8488468ba123da7dca5c76a1d58f0cac3b8a0b4c87a11d4bcde9f
|
|
4
|
+
data.tar.gz: 0e6e21eb7d267053fe89620c4357ea627e93d77c2864421f0eedb0bdb6a94538
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 0cad41376522ac2e360d83a054e82bed619c8e07b201d0099837caf752d11c757be897fb991986341fdb1d962640f63467c25757a975db72283b122805ce8de2
|
|
7
|
+
data.tar.gz: 8461824f5cdfeb5d6bc78043a615a179619d659e25e2523a59a5452b75d683ef9e9946af4f4e7f5d8c2fbd439461a52b6f6ec367fa8a52759e121c3195b29f33
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# This is the configuration used to check the rubocop source code.
|
|
2
|
+
require:
|
|
3
|
+
- rubocop-rspec
|
|
4
|
+
|
|
5
|
+
AllCops:
|
|
6
|
+
NewCops: enable
|
|
7
|
+
Exclude:
|
|
8
|
+
- 'vendor/**/*'
|
|
9
|
+
- 'spec/fixtures/**/*'
|
|
10
|
+
- 'tmp/**/*'
|
|
11
|
+
- '.git/**/*'
|
|
12
|
+
- 'bin/*'
|
|
13
|
+
TargetRubyVersion: 2.7
|
|
14
|
+
SuggestExtensions: false
|
|
15
|
+
|
|
16
|
+
Metrics/AbcSize:
|
|
17
|
+
Enabled: False
|
|
18
|
+
Metrics/MethodLength:
|
|
19
|
+
Max: 15
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
source 'https://rubygems.org'
|
|
4
|
+
|
|
5
|
+
# Specify your gem's dependencies in sia_skynet.gemspec
|
|
6
|
+
gemspec
|
|
7
|
+
|
|
8
|
+
gem 'rake', '~> 12.0'
|
|
9
|
+
gem 'typhoeus', '~> 1.4.0'
|
|
10
|
+
gem 'mimemagic', '~> 0.4.3'
|
|
11
|
+
gem 'multipart_body', '~> 0.2.1'
|
|
12
|
+
gem 'thor', '~> 1.1.0'
|
|
13
|
+
|
|
14
|
+
group :test, :development do
|
|
15
|
+
gem 'rspec', '~> 3.0'
|
|
16
|
+
gem 'rubocop', '~> 1.13.0'
|
|
17
|
+
gem 'rubocop-rspec', '~> 2.2.0'
|
|
18
|
+
gem 'byebug', require: 'byebug'
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
group :test do
|
|
22
|
+
gem "webmock", '~> 3.12.0'
|
|
23
|
+
gem 'rspec-json_expectations'
|
|
24
|
+
end
|
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
sia_skynet (0.1.0)
|
|
5
|
+
|
|
6
|
+
GEM
|
|
7
|
+
remote: https://rubygems.org/
|
|
8
|
+
specs:
|
|
9
|
+
addressable (2.7.0)
|
|
10
|
+
public_suffix (>= 2.0.2, < 5.0)
|
|
11
|
+
ast (2.4.2)
|
|
12
|
+
byebug (11.1.3)
|
|
13
|
+
crack (0.4.5)
|
|
14
|
+
rexml
|
|
15
|
+
diff-lcs (1.4.4)
|
|
16
|
+
ethon (0.14.0)
|
|
17
|
+
ffi (>= 1.15.0)
|
|
18
|
+
ffi (1.15.0)
|
|
19
|
+
hashdiff (1.0.1)
|
|
20
|
+
mimemagic (0.4.3)
|
|
21
|
+
nokogiri (~> 1)
|
|
22
|
+
rake
|
|
23
|
+
mini_portile2 (2.5.1)
|
|
24
|
+
multipart_body (0.2.1)
|
|
25
|
+
nokogiri (1.11.3)
|
|
26
|
+
mini_portile2 (~> 2.5.0)
|
|
27
|
+
racc (~> 1.4)
|
|
28
|
+
parallel (1.20.1)
|
|
29
|
+
parser (3.0.1.0)
|
|
30
|
+
ast (~> 2.4.1)
|
|
31
|
+
public_suffix (4.0.6)
|
|
32
|
+
racc (1.5.2)
|
|
33
|
+
rainbow (3.0.0)
|
|
34
|
+
rake (12.3.3)
|
|
35
|
+
regexp_parser (2.1.1)
|
|
36
|
+
rexml (3.2.5)
|
|
37
|
+
rspec (3.10.0)
|
|
38
|
+
rspec-core (~> 3.10.0)
|
|
39
|
+
rspec-expectations (~> 3.10.0)
|
|
40
|
+
rspec-mocks (~> 3.10.0)
|
|
41
|
+
rspec-core (3.10.1)
|
|
42
|
+
rspec-support (~> 3.10.0)
|
|
43
|
+
rspec-expectations (3.10.1)
|
|
44
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
45
|
+
rspec-support (~> 3.10.0)
|
|
46
|
+
rspec-json_expectations (2.2.0)
|
|
47
|
+
rspec-mocks (3.10.2)
|
|
48
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
49
|
+
rspec-support (~> 3.10.0)
|
|
50
|
+
rspec-support (3.10.2)
|
|
51
|
+
rubocop (1.13.0)
|
|
52
|
+
parallel (~> 1.10)
|
|
53
|
+
parser (>= 3.0.0.0)
|
|
54
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
55
|
+
regexp_parser (>= 1.8, < 3.0)
|
|
56
|
+
rexml
|
|
57
|
+
rubocop-ast (>= 1.2.0, < 2.0)
|
|
58
|
+
ruby-progressbar (~> 1.7)
|
|
59
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
|
60
|
+
rubocop-ast (1.4.1)
|
|
61
|
+
parser (>= 2.7.1.5)
|
|
62
|
+
rubocop-rspec (2.2.0)
|
|
63
|
+
rubocop (~> 1.0)
|
|
64
|
+
rubocop-ast (>= 1.1.0)
|
|
65
|
+
ruby-progressbar (1.11.0)
|
|
66
|
+
thor (1.1.0)
|
|
67
|
+
typhoeus (1.4.0)
|
|
68
|
+
ethon (>= 0.9.0)
|
|
69
|
+
unicode-display_width (2.0.0)
|
|
70
|
+
webmock (3.12.2)
|
|
71
|
+
addressable (>= 2.3.6)
|
|
72
|
+
crack (>= 0.3.2)
|
|
73
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
|
74
|
+
|
|
75
|
+
PLATFORMS
|
|
76
|
+
ruby
|
|
77
|
+
|
|
78
|
+
DEPENDENCIES
|
|
79
|
+
byebug
|
|
80
|
+
mimemagic (~> 0.4.3)
|
|
81
|
+
multipart_body (~> 0.2.1)
|
|
82
|
+
rake (~> 12.0)
|
|
83
|
+
rspec (~> 3.0)
|
|
84
|
+
rspec-json_expectations
|
|
85
|
+
rubocop (~> 1.13.0)
|
|
86
|
+
rubocop-rspec (~> 2.2.0)
|
|
87
|
+
sia_skynet!
|
|
88
|
+
thor (~> 1.1.0)
|
|
89
|
+
typhoeus (~> 1.4.0)
|
|
90
|
+
webmock (~> 3.12.0)
|
|
91
|
+
|
|
92
|
+
BUNDLED WITH
|
|
93
|
+
2.1.4
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 Christoph Klocker
|
|
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.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Skynet
|
|
2
|
+
|
|
3
|
+
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/sia_skynet`. To experiment with that code, run `bin/console` for an interactive prompt.
|
|
4
|
+
|
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Add this line to your application's Gemfile:
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
gem 'sia_skynet'
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
And then execute:
|
|
16
|
+
|
|
17
|
+
$ bundle install
|
|
18
|
+
|
|
19
|
+
Or install it yourself as:
|
|
20
|
+
|
|
21
|
+
$ gem install sia_skynet
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
require 'skynet'
|
|
26
|
+
|
|
27
|
+
### Uploading to a Skynet portal
|
|
28
|
+
|
|
29
|
+
#### Uploading a single file
|
|
30
|
+
|
|
31
|
+
client = Skynet::Client.new
|
|
32
|
+
client.upload_file '/path/to/file.pdf'
|
|
33
|
+
=> "sia://ZAAZyxRQ7Ixzd3zujn1ly8RA..."
|
|
34
|
+
|
|
35
|
+
# if you want to get the full response
|
|
36
|
+
client.upload_file '/path/to/file.pdf', full_response: true
|
|
37
|
+
=> {
|
|
38
|
+
"skylink"=>"ZAAZyxRQ7Ixzd3zujn1ly8RA...",
|
|
39
|
+
"merkleroot"=>"19cb1450ec8981fcc63c73777cee8e7d65cbc44",
|
|
40
|
+
"bitfield"=>100,
|
|
41
|
+
"sialink"=>"sia://ZAAZyxRQ7Ixzd3zujn1ly8RA"
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#### Uploading a directory:
|
|
45
|
+
|
|
46
|
+
client.upload_directory '/path/to/directory'
|
|
47
|
+
|
|
48
|
+
#### Downloading a file or directory:
|
|
49
|
+
|
|
50
|
+
This function downloads a skylink using HTTP streaming. The call blocks until the data is received. There is a 30s default timeout applied to downloading a skylink. If the data can not be found within this 30s time constraint, a 404 error will be returned. This timeout is configurable.
|
|
51
|
+
|
|
52
|
+
A directory will be downloaded as zip file, otherwise as regular file.
|
|
53
|
+
|
|
54
|
+
client.download_file("/path/foo.zip", skylink)
|
|
55
|
+
|
|
56
|
+
#### Getting Metadata
|
|
57
|
+
|
|
58
|
+
Returns the metadata of an upload. Currently quite often no metadata is returned and a `Skynet::NoMetadataError` exception will be raised.
|
|
59
|
+
|
|
60
|
+
client.get_metadata "ZAAZyxRQ7ImB_...."
|
|
61
|
+
|
|
62
|
+
## Progress
|
|
63
|
+
|
|
64
|
+
☑ Uploading a file\
|
|
65
|
+
☑ Uploading a directory\
|
|
66
|
+
☑ Downloading a file\
|
|
67
|
+
☑ Downloading a directory\
|
|
68
|
+
☑ Getting Metadata\
|
|
69
|
+
☐ SkyDB\
|
|
70
|
+
☐ Registry\
|
|
71
|
+
☐ MySky\
|
|
72
|
+
|
|
73
|
+
## Contributing
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/corck/sia_skynet.
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
## License
|
|
80
|
+
|
|
81
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
82
|
+
|
|
83
|
+
Copyright 2021, by Christoph Klocker.
|
data/Rakefile
ADDED
data/bin/console
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'bundler/setup'
|
|
5
|
+
require 'skynet'
|
|
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
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
11
|
+
# require "pry"
|
|
12
|
+
# Pry.start
|
|
13
|
+
|
|
14
|
+
require 'irb'
|
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/lib/skynet.rb
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'typhoeus'
|
|
5
|
+
require 'multipart_body'
|
|
6
|
+
require 'mimemagic'
|
|
7
|
+
|
|
8
|
+
module Skynet
|
|
9
|
+
# Client for interacting with Skynet
|
|
10
|
+
#
|
|
11
|
+
# Default portal is set to https://siasky.net
|
|
12
|
+
#
|
|
13
|
+
class Client
|
|
14
|
+
DEFAULT_SKYNET_PORTAL_URL = 'https://siasky.net'
|
|
15
|
+
DEFAULT_SKYNET_PORTAL_PATH = '/skynet/skyfile'
|
|
16
|
+
URI_SKYNET_PREFIX = 'sia://'
|
|
17
|
+
DEFAULT_USER_AGENT = 'Sia-Agent'
|
|
18
|
+
|
|
19
|
+
attr_reader :user_agent
|
|
20
|
+
attr_accessor :config
|
|
21
|
+
|
|
22
|
+
# Initializes the client, allows to set a custom portal or uses siasky.net as default
|
|
23
|
+
#
|
|
24
|
+
# @param [Hash] config the configuration options to initialize the client with
|
|
25
|
+
# @option config [String] :api_key The API password used for authentication.
|
|
26
|
+
# @option config [String] :user_agent Allows changing the User Agent, as some portals may reject user agents
|
|
27
|
+
# that are not `Sia-Agent` for security reasons.
|
|
28
|
+
# @option config [String] :on_upload_progress Optional callback to track upload progress. (Not implemented yet)
|
|
29
|
+
# @option config [String] :portal url to a custom portal, defaults to https://siasky.net
|
|
30
|
+
# @option config [String] :dirname Optional directory name on skynet
|
|
31
|
+
# @option config [Boolean] :verbose Set to true to log network requests
|
|
32
|
+
|
|
33
|
+
def initialize(custom_config = {})
|
|
34
|
+
@config = default_upload_options
|
|
35
|
+
@config.merge!(custom_config)
|
|
36
|
+
@api_key = config[:api_key] || nil
|
|
37
|
+
Typhoeus::Config.user_agent = config[:user_agent]
|
|
38
|
+
@on_upload_progress = config[:on_upload_progress]
|
|
39
|
+
Typhoeus::Config.verbose = true if custom_config[:verbose]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Takes a file path and uploads it
|
|
43
|
+
#
|
|
44
|
+
# @param [String] file File or file path where the file is located
|
|
45
|
+
#
|
|
46
|
+
# @param [Hash] custom_opts additional upload options
|
|
47
|
+
# @option custom_opts [String] :portal_file_field_name The field name for files on the portal.
|
|
48
|
+
# Usually should not need to be changed.
|
|
49
|
+
# @option custom_opts [String] :portal_directory_file_field_name The field name for directories on the portal.
|
|
50
|
+
# Usually should not need to be changed.
|
|
51
|
+
# @option custom_opts [String] :filename Custom filename.
|
|
52
|
+
# This is the filename that will be returned when downloading the file in a browser
|
|
53
|
+
# @option custom_opts [String] :custom_dirname Custom dirname. If this is empty,
|
|
54
|
+
# the base name of the directory being uploaded will be used by default.
|
|
55
|
+
# @option custom_opts [String] :timeout_seconds Custom filename. The timeout in seconds.
|
|
56
|
+
# @option custom_opts [Boolean] :full_response Returns full hash with skylink, merkleroot and bitfield
|
|
57
|
+
#
|
|
58
|
+
# @return [String] Returns the sialink (sia://AABBCC) by default
|
|
59
|
+
# @return [Hash] Response Hash with full response from skynet including skylink, merkleroot
|
|
60
|
+
# bitfield and sialink if :full_response option is given
|
|
61
|
+
# @option response [String] :skylink
|
|
62
|
+
#
|
|
63
|
+
# @example Default response:
|
|
64
|
+
# sia://KAA54bKo-YqFRj345xGXdo9h15k.....
|
|
65
|
+
#
|
|
66
|
+
# @example Full response as hash
|
|
67
|
+
# {
|
|
68
|
+
# "skylink"=>"KAA54bKo-YqFRjDxRxGXdo9h15k8......",
|
|
69
|
+
# "merkleroot"=>"39e1b2a....",
|
|
70
|
+
# "bitfield"=>40,
|
|
71
|
+
# "sialink"=>"sia://KAA54bKo-YqFRjDxRxGXdo9h15k8...."
|
|
72
|
+
# }
|
|
73
|
+
#
|
|
74
|
+
#
|
|
75
|
+
def upload_file(file, custom_opts = {})
|
|
76
|
+
res = upload(file, config.merge(custom_opts)).run
|
|
77
|
+
|
|
78
|
+
format_response(res, custom_opts)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def upload_directory(directory, opts = {})
|
|
82
|
+
custom_options = filter_upload_options(config.merge(opts))
|
|
83
|
+
|
|
84
|
+
multipart = prepare_multipart_body(directory)
|
|
85
|
+
header = default_headers.merge({ 'Content-Type' => "multipart/form-data; boundary=#{multipart.boundary}" })
|
|
86
|
+
|
|
87
|
+
res = Typhoeus::Request.new(
|
|
88
|
+
"#{portal}#{portal_path}",
|
|
89
|
+
method: :post,
|
|
90
|
+
params: custom_options.merge(filename: File.basename(directory)),
|
|
91
|
+
headers: header,
|
|
92
|
+
body: multipart.to_s
|
|
93
|
+
).run
|
|
94
|
+
|
|
95
|
+
format_response(res, custom_options)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Download a file
|
|
99
|
+
# @param [String] path The local path where the file should be downloaded to.
|
|
100
|
+
# @param [String] skylink The skylink that should be downloaded. The skylink can contain an optional path.
|
|
101
|
+
#
|
|
102
|
+
# @return [String] path Path of the downloaded file
|
|
103
|
+
def download_file(path, skylink)
|
|
104
|
+
skylink = strip_uri_prefix(skylink)
|
|
105
|
+
|
|
106
|
+
f = File.open(path, 'wb')
|
|
107
|
+
begin
|
|
108
|
+
request = Typhoeus::Request.new("#{portal}/#{skylink}", headers: default_headers)
|
|
109
|
+
request.on_headers do |response|
|
|
110
|
+
raise 'Request failed' if response.code != 200
|
|
111
|
+
end
|
|
112
|
+
request.on_body do |chunk|
|
|
113
|
+
f.write(chunk)
|
|
114
|
+
end
|
|
115
|
+
request.on_complete do |_response|
|
|
116
|
+
f.close
|
|
117
|
+
end
|
|
118
|
+
request.run
|
|
119
|
+
ensure
|
|
120
|
+
f.close
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
path
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Downloads the metadata of a skylink
|
|
127
|
+
#
|
|
128
|
+
# @param [String] skylink Skylink of the file
|
|
129
|
+
#
|
|
130
|
+
# @return [Hash]
|
|
131
|
+
#
|
|
132
|
+
# @example Response
|
|
133
|
+
# {
|
|
134
|
+
# 'filename' => 'foo.pdf',
|
|
135
|
+
# 'length' => 21_977,
|
|
136
|
+
# 'subfiles' =>
|
|
137
|
+
# { 'foo.pdf' =>
|
|
138
|
+
# { 'filename' => 'foo.pdf',
|
|
139
|
+
# 'contenttype' => 'application/octet-stream',
|
|
140
|
+
# 'len' => 21_977 } }
|
|
141
|
+
# }
|
|
142
|
+
def get_metadata(skylink)
|
|
143
|
+
skylink = strip_uri_prefix(skylink)
|
|
144
|
+
res = Typhoeus::Request.head(
|
|
145
|
+
"#{portal}/#{skylink}", headers: default_headers
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
raise Skynet::NoMetadataError, 'No metadata returned' unless res.headers['skynet-file-metadata']
|
|
149
|
+
|
|
150
|
+
JSON.parse res.headers['skynet-file-metadata']
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
private
|
|
154
|
+
|
|
155
|
+
# Return all files recursively, exclude directories
|
|
156
|
+
#
|
|
157
|
+
def files_to_upload(path)
|
|
158
|
+
Dir.glob("#{path}/**/*")
|
|
159
|
+
.reject { |fn| File.directory?(fn) }
|
|
160
|
+
.map do |f|
|
|
161
|
+
{ path: f, relative_path: f.gsub(%r{#{path}/}, '') }
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Returns default upload options
|
|
166
|
+
def default_upload_options
|
|
167
|
+
opts = {}
|
|
168
|
+
opts[:portal] = DEFAULT_SKYNET_PORTAL_URL
|
|
169
|
+
opts[:portal_path] = DEFAULT_SKYNET_PORTAL_PATH
|
|
170
|
+
opts[:user_agent] = DEFAULT_USER_AGENT
|
|
171
|
+
opts[:portal_file_fieldname] = 'file'
|
|
172
|
+
opts[:portal_directory_file_fieldname] = 'files[]'
|
|
173
|
+
opts[:filename] = 'file'
|
|
174
|
+
opts[:dirname] = ''
|
|
175
|
+
opts
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def portal_path
|
|
179
|
+
File.join(config[:portal_path], config[:dirname])
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def portal
|
|
183
|
+
config[:portal]
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def upload(file, opts = {})
|
|
187
|
+
custom_opts = config.merge(opts)
|
|
188
|
+
params = custom_opts.filter { |k| default_upload_options.keys.include?(k) }
|
|
189
|
+
|
|
190
|
+
begin
|
|
191
|
+
f = File.open(file, 'rb')
|
|
192
|
+
|
|
193
|
+
Typhoeus::Request.new(
|
|
194
|
+
"#{portal}#{portal_path}",
|
|
195
|
+
method: :post,
|
|
196
|
+
params: params,
|
|
197
|
+
body: {
|
|
198
|
+
file: f
|
|
199
|
+
}
|
|
200
|
+
)
|
|
201
|
+
ensure
|
|
202
|
+
f&.close
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Filter by available upload options
|
|
207
|
+
def filter_upload_options(opts)
|
|
208
|
+
opts.filter { |k| default_upload_options.keys.include?(k) }
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def default_headers
|
|
212
|
+
{ "User-Agent": DEFAULT_USER_AGENT }
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def format_response(res, custom_opts = {})
|
|
216
|
+
json = JSON.parse res.body
|
|
217
|
+
sialink = "#{URI_SKYNET_PREFIX}#{json['skylink']}"
|
|
218
|
+
|
|
219
|
+
custom_opts[:full_response] == true ? json.merge({ 'sialink' => sialink }) : sialink
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def prepare_multipart_body(directory)
|
|
223
|
+
files = files_to_upload(directory)
|
|
224
|
+
|
|
225
|
+
file_parts = files.inject([]) do |parts, file|
|
|
226
|
+
ct = MimeMagic.by_path(file[:path])&.type
|
|
227
|
+
begin
|
|
228
|
+
f = File.open(file[:path], 'r')
|
|
229
|
+
parts << Part.new(name: config[:portal_directory_file_fieldname],
|
|
230
|
+
body: f.read,
|
|
231
|
+
filename: file[:relative_path],
|
|
232
|
+
content_type: ct)
|
|
233
|
+
ensure
|
|
234
|
+
f.close
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
MultipartBody.new(file_parts)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def strip_uri_prefix(skylink)
|
|
242
|
+
skylink.delete_prefix(URI_SKYNET_PREFIX)
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
data/sia_skynet.gemspec
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/skynet/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'skynet_ruby'
|
|
7
|
+
spec.version = Skynet::VERSION
|
|
8
|
+
spec.authors = ['Christoph Klocker']
|
|
9
|
+
spec.email = ['christoph@vedanova.com']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'Skynet client to interact with Sia Skynet'
|
|
12
|
+
spec.description = 'Skynet is a decentralized storage solution built on the Sia blockchain'
|
|
13
|
+
spec.homepage = 'https://siasky.net'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.7.0')
|
|
16
|
+
|
|
17
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
|
18
|
+
|
|
19
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
20
|
+
spec.metadata['source_code_uri'] = 'https://github.com/corck/sia_skynet'
|
|
21
|
+
# spec.metadata["changelog_uri"] = "https://github.com/corck/sia_skynet"
|
|
22
|
+
|
|
23
|
+
# Specify which files should be added to the gem when it is released.
|
|
24
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
25
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
26
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
27
|
+
end
|
|
28
|
+
spec.bindir = 'exe'
|
|
29
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
30
|
+
spec.require_paths = ['lib']
|
|
31
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: skynet_ruby
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Christoph Klocker
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2021-06-14 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: Skynet is a decentralized storage solution built on the Sia blockchain
|
|
14
|
+
email:
|
|
15
|
+
- christoph@vedanova.com
|
|
16
|
+
executables: []
|
|
17
|
+
extensions: []
|
|
18
|
+
extra_rdoc_files: []
|
|
19
|
+
files:
|
|
20
|
+
- ".gitignore"
|
|
21
|
+
- ".rspec"
|
|
22
|
+
- ".rubocop.yml"
|
|
23
|
+
- ".travis.yml"
|
|
24
|
+
- Gemfile
|
|
25
|
+
- Gemfile.lock
|
|
26
|
+
- LICENSE.txt
|
|
27
|
+
- README.md
|
|
28
|
+
- Rakefile
|
|
29
|
+
- bin/console
|
|
30
|
+
- bin/setup
|
|
31
|
+
- lib/skynet.rb
|
|
32
|
+
- lib/skynet/client.rb
|
|
33
|
+
- lib/skynet/version.rb
|
|
34
|
+
- sia_skynet.gemspec
|
|
35
|
+
homepage: https://siasky.net
|
|
36
|
+
licenses:
|
|
37
|
+
- MIT
|
|
38
|
+
metadata:
|
|
39
|
+
allowed_push_host: https://rubygems.org
|
|
40
|
+
homepage_uri: https://siasky.net
|
|
41
|
+
source_code_uri: https://github.com/corck/sia_skynet
|
|
42
|
+
post_install_message:
|
|
43
|
+
rdoc_options: []
|
|
44
|
+
require_paths:
|
|
45
|
+
- lib
|
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
47
|
+
requirements:
|
|
48
|
+
- - ">="
|
|
49
|
+
- !ruby/object:Gem::Version
|
|
50
|
+
version: 2.7.0
|
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
52
|
+
requirements:
|
|
53
|
+
- - ">="
|
|
54
|
+
- !ruby/object:Gem::Version
|
|
55
|
+
version: '0'
|
|
56
|
+
requirements: []
|
|
57
|
+
rubygems_version: 3.2.20
|
|
58
|
+
signing_key:
|
|
59
|
+
specification_version: 4
|
|
60
|
+
summary: Skynet client to interact with Sia Skynet
|
|
61
|
+
test_files: []
|