wetransfer 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.
@@ -0,0 +1,104 @@
1
+ require 'spec_helper'
2
+
3
+ describe WeTransfer::ItemBuilder do
4
+ describe 'ItemBuilder process' do
5
+ let(:item_builder) { described_class.new }
6
+
7
+ it 'makes a new Item if no item is given on initialze' do
8
+ expect(item_builder).to be_an_instance_of(WeTransfer::ItemBuilder)
9
+ expect(item_builder.item).to be_an_instance_of(WeTransfer::Item)
10
+ end
11
+
12
+ it 'uses the item, when a item is given to the ItemBuilder' do
13
+ builder_item = described_class.new(item: item_builder.item)
14
+ expect(builder_item).to be_an_instance_of(WeTransfer::ItemBuilder)
15
+ expect(builder_item.item).to be_an_instance_of(WeTransfer::Item)
16
+ end
17
+
18
+ it 'sets the path when path method is called' do
19
+ item_builder.path(path: "#{__dir__}/fixtures/war-and-peace.txt")
20
+ expect(item_builder.item.path).to eq("#{__dir__}/fixtures/war-and-peace.txt")
21
+ end
22
+
23
+ it 'sets content always to file' do
24
+ item_builder.content_identifier
25
+ expect(item_builder.item.content_identifier).to eq('file')
26
+ end
27
+
28
+ it 'sets the local local_identifier to the first 36 characters of the file name' do
29
+ item_builder.path(path: "#{__dir__}/fixtures/war-and-peace.txt")
30
+ item_builder.local_identifier
31
+ expect(item_builder.item.local_identifier).to eq('war-and-peace.txt')
32
+ expect(item_builder.item.local_identifier.length).to be <= 36
33
+ end
34
+
35
+ it 'sets the local local_identifier to the first 36 characters of the file name' do
36
+ item_builder.path(path: "#{__dir__}/fixtures/war-and-peace-and-peace-and-war-and-war-and-peace.txt")
37
+ item_builder.local_identifier
38
+ expect(item_builder.item.local_identifier).to eq('war-and-peace-and-peace-and-war-and-')
39
+ expect(item_builder.item.local_identifier.length).to be <= 36
40
+ end
41
+
42
+ it 'sets the item name according to the given path' do
43
+ item_builder.path(path: "#{__dir__}/fixtures/war-and-peace.txt")
44
+ item_builder.name
45
+ expect(item_builder.item.name).to eq('war-and-peace.txt')
46
+ end
47
+
48
+ it 'sets the filesize by reading the file' do
49
+ item_builder.path(path: "#{__dir__}/fixtures/war-and-peace.txt")
50
+ item_builder.size
51
+ expect(item_builder.item.size).to_not be_nil
52
+ expect(item_builder.item.size).to eq(485192)
53
+ end
54
+
55
+ it 'sets the id according to the api response' do
56
+ item_builder.path(path: "#{__dir__}/fixtures/war-and-peace.txt")
57
+ item_builder.id(item: item_builder.item, id: 1234)
58
+ expect(item_builder.item.id).to eq(1234)
59
+ end
60
+
61
+ it 'sets the upload url according to the api response' do
62
+ item_builder.path(path: "#{__dir__}/fixtures/war-and-peace.txt")
63
+ item_builder.upload_url(item: item_builder.item, url: "#{ENV.fetch('WT_API_URL')}/upload/#{SecureRandom.hex(9)}")
64
+ expect(item_builder.item.upload_url).to_not be_nil
65
+ end
66
+
67
+ it 'sets the multipart_parts according to the api response' do
68
+ item_builder.path(path: "#{__dir__}/fixtures/war-and-peace.txt")
69
+ item_builder.multipart_parts(item: item_builder.item, part_count: 3)
70
+ expect(item_builder.item.multipart_parts).to eq(3)
71
+ end
72
+
73
+ it 'sets the multipart_id according to the api response' do
74
+ item_builder.path(path: "#{__dir__}/fixtures/war-and-peace.txt")
75
+ item_builder.multipart_id(item: item_builder.item, multi_id: 1234567890)
76
+ expect(item_builder.item.multipart_id).to eq(1234567890)
77
+ end
78
+
79
+ it 'sets the upload_id according to the api response' do
80
+ item_builder.path(path: "#{__dir__}/fixtures/war-and-peace.txt")
81
+ item_builder.upload_id(item: item_builder.item, upload_id: 1234567890)
82
+ expect(item_builder.item.upload_id).to eq(1234567890)
83
+ end
84
+
85
+ it 'returns the item object when ItemBuilder item method is calles' do
86
+ item_builder.path(path: "#{__dir__}/fixtures/war-and-peace.txt")
87
+ expect(item_builder.item).to be_an_instance_of(WeTransfer::Item)
88
+ end
89
+
90
+ it 'validates the file if it exists on the path given' do
91
+ expect {
92
+ item_builder.path(path: "#{__dir__}/fixtures/war-and-peace.txt")
93
+ item_builder.validate_file
94
+ }.to_not raise_error
95
+ end
96
+
97
+ it 'validates the file if it exists on the path given and returns with FileDoesNotExistError' do
98
+ expect {
99
+ item_builder.path(path: "#{__dir__}/peace-and-war.txt")
100
+ item_builder.validate_file
101
+ }.to raise_error(WeTransfer::ItemBuilder::FileDoesNotExistError, "#{item_builder.item} does not exist")
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,24 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter '/spec/'
4
+ end
5
+
6
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
7
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
+
9
+ require 'wetransfer'
10
+ require 'pry'
11
+ require 'rspec'
12
+ require_relative 'test_server'
13
+
14
+ RSpec.configure do |config|
15
+ config.before :suite do
16
+ TestServer.start(nil)
17
+ ENV['WT_API_URL'] = 'http://localhost:9001'
18
+ ENV['WT_API_CONNECTION_PATH'] = '/v1'
19
+ end
20
+
21
+ config.expect_with :rspec do |c|
22
+ c.syntax = :expect
23
+ end
24
+ end
@@ -0,0 +1,208 @@
1
+ require 'webrick'
2
+ require 'securerandom'
3
+ include WEBrick
4
+
5
+ class ForbiddenServlet < HTTPServlet::AbstractServlet
6
+ def do_GET(_req, res)
7
+ res['Content-Type'] = 'application/json'
8
+ res.status = 403
9
+ end
10
+ def do_POST(_req, res)
11
+ res['Content-Type'] = 'application/json'
12
+ res.status = 403
13
+ end
14
+ end
15
+
16
+ class AuthServlet < HTTPServlet::AbstractServlet
17
+ def do_POST(req, res)
18
+ if req.header["x-api-key"].empty?
19
+ res['Content-Type'] = 'application/json'
20
+ res.status = 401
21
+ else
22
+ res['Content-Type'] = 'application/json'
23
+ res.status = 200
24
+ res.body = {status: 'success', token: SecureRandom.hex(4)}.to_json
25
+ end
26
+ end
27
+ end
28
+
29
+ class TransfersServlet < HTTPServlet::AbstractServlet
30
+ def self.do_POST(req, res)
31
+ content = JSON.parse(req.body)
32
+ items_count = content["items"].count || 0
33
+ res['Content-Type'] = 'application/json'
34
+ res.status = 200
35
+ res.body = {shortened_url: "http://we.tl/s-#{SecureRandom.hex(5)}",
36
+ id: SecureRandom.hex(9),
37
+ name: content["name"],
38
+ description: content["description"],
39
+ size: totalsize_calc(items: content["items"]),
40
+ total_items: content["items"].count,
41
+ version_identifier: nil,
42
+ state: 'uploading',
43
+ items: item_params(items: content["items"])}.to_json
44
+ end
45
+
46
+ private
47
+
48
+ def self.item_params(items:)
49
+ items_array = []
50
+ items.each do |item|
51
+ items_array << {id: SecureRandom.hex(9),
52
+ local_identifier: item['filename'][0..36],
53
+ name: item['filename'],
54
+ size: item['filesize'],
55
+ meta:{
56
+ multipart_parts: multipart_calc(item: item),
57
+ multipart_id: SecureRandom.hex(9),
58
+ },
59
+ upload_url:"#{ENV.fetch('WT_API_URL')}/upload/#{SecureRandom.hex(9)}",
60
+ upload_id: SecureRandom.hex(9),
61
+ upload_expires_at: (Time.now + 5).to_i
62
+ }
63
+ end
64
+ return items_array
65
+ end
66
+
67
+ def self.totalsize_calc(items:)
68
+ total_size = []
69
+ items.each do |item|
70
+ total_size << item['filesize']
71
+ end
72
+ total_size.reduce(0, :+)
73
+ end
74
+
75
+ def self.multipart_calc(item:)
76
+ parts = item['filesize'] / 6291456
77
+ parts == 0 ? 1 : parts
78
+ end
79
+ end
80
+
81
+ class UploadUrlServlet < HTTPServlet::AbstractServlet
82
+ def self.do_GET(_req, res)
83
+ part_number = res.request_uri.to_s.split('/')[-2]
84
+ res['Content-Type'] = 'application/json'
85
+ res.status = 200
86
+ res.body = { upload_url: "#{ENV.fetch('WT_API_URL')}/upload/#{SecureRandom.hex(9)}",
87
+ part_number: part_number.to_i,
88
+ upload_id: SecureRandom.hex(9),
89
+ upload_expires_at: (Time.now + 5).to_i
90
+ }.to_json
91
+ end
92
+ end
93
+
94
+ class UploadPartServlet < HTTPServlet::AbstractServlet
95
+ def self.do_PUT(_req, res)
96
+ res['Content-Type'] = 'application/json'
97
+ res.status = 200
98
+ end
99
+ end
100
+
101
+ class TransferItemServlet < HTTPServlet::AbstractServlet
102
+ # this servlet is used for add_items_to_transfer functionality
103
+ def self.do_POST(req, res)
104
+ content = JSON.parse(req.body)
105
+ res['Content-Type'] = 'application/json'
106
+ res.status = 200
107
+ res.body = item_params(items: content["items"]).to_json
108
+ end
109
+
110
+ def self.item_params(items:)
111
+ items_array = []
112
+ items.each do |item|
113
+ items_array << {id: SecureRandom.hex(9),
114
+ local_identifier: item['filename'][0..36],
115
+ name: item['filename'],
116
+ size: item['filesize'],
117
+ meta:{
118
+ multipart_parts: multipart_calc(item: item),
119
+ multipart_id: SecureRandom.hex(9),
120
+ },
121
+ upload_url:"#{ENV.fetch('WT_API_URL')}/upload/#{SecureRandom.hex(9)}",
122
+ upload_id: SecureRandom.hex(9),
123
+ upload_expires_at: (Time.now + 5).to_i
124
+ }
125
+ end
126
+ return items_array
127
+ end
128
+ def self.multipart_calc(item:)
129
+ parts = item['filesize'] / 6291456
130
+ parts == 0 ? 1 : parts
131
+ end
132
+ end
133
+
134
+ class UploadServlet < HTTPServlet::AbstractServlet
135
+ def do_PUT(req, res)
136
+ res['Content-Type'] = 'application/json'
137
+ res.status = 200
138
+ end
139
+ end
140
+
141
+ class CompleteItemServlet < HTTPServlet::AbstractServlet
142
+ def self.do_POST(_req, res)
143
+ res['Content-Type'] = 'application/json'
144
+ res.status = 202
145
+ res.body = {ok: true, message: 'File is marked as complete.'}.to_json
146
+ end
147
+ end
148
+
149
+ class TestServer
150
+ def self.start(log_file = nil, port = 9001)
151
+ new(log_file, port).start
152
+ end
153
+
154
+ def initialize(log_file = nil, port = 9001)
155
+ log_file ||= StringIO.new
156
+ log = WEBrick::BasicLog.new(log_file, WEBrick::BasicLog::WARN)
157
+
158
+ options = {
159
+ Port: port,
160
+ Logger: log,
161
+ AccessLog: [
162
+ [log, WEBrick::AccessLog::COMMON_LOG_FORMAT],
163
+ [log, WEBrick::AccessLog::REFERER_LOG_FORMAT]
164
+ ],
165
+ DocumentRoot: File.expand_path(__dir__),
166
+ }
167
+
168
+ @server = WEBrick::HTTPServer.new(options)
169
+ @server.mount('/v1/forbidden', ForbiddenServlet)
170
+ @server.mount('/v1/authorize', AuthServlet)
171
+ @server.mount_proc('/v1/transfers') do |req, res|
172
+ if req.path =~ /^(?=.*\bv1\b)(?=.*\btransfers\b)(?=.*\bitems\b).+/
173
+ TransferItemServlet.do_POST(req, res)
174
+ else
175
+ TransfersServlet.do_POST(req, res)
176
+ end
177
+ end
178
+ @server.mount_proc('/v1/files/') do |req, res|
179
+ if req.request_method == "PUT"
180
+ UploadPartServlet.do_PUT(req, res)
181
+ elsif req.request_method == "GET"
182
+ UploadUrlServlet.do_GET(req, res)
183
+ else
184
+ CompleteItemServlet.do_POST(req,res)
185
+ end
186
+ end
187
+ @server.mount('/upload', UploadServlet)
188
+ end
189
+
190
+ def start
191
+ trap('INT') {
192
+ begin
193
+ @server.shutdown unless @server.nil?
194
+ rescue Object => e
195
+ warn "Error #{__FILE__}:#{__LINE__}\n#{e.message}"
196
+ end
197
+ }
198
+
199
+ @thread = Thread.new { @server.start }
200
+ Thread.pass
201
+ self
202
+ end
203
+
204
+ def join
205
+ @thread.join if defined? @thread and @thread
206
+ self
207
+ end
208
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe WeTransfer, :module do
4
+ it 'has a version number' do
5
+ expect(WeTransfer::VERSION).not_to be nil
6
+ end
7
+ end
@@ -0,0 +1,44 @@
1
+
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'wetransfer/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'wetransfer'
8
+ spec.version = WeTransfer::VERSION
9
+ spec.authors = ['Noah Berman', 'David Bosveld']
10
+ spec.email = ['noah@wetransfer.com', 'david@wetransfer.com', 'developers@wetransfer.com']
11
+
12
+ spec.summary = "A Ruby SDK for WeTransfer's Public API"
13
+ spec.description = "Ruby bindings for using WeTransfer's Public API."
14
+ spec.homepage = 'https://developers.wetransfer.com'
15
+ spec.license = 'MIT'
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ if spec.respond_to?(:metadata)
20
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
21
+ else
22
+ raise 'RubyGems 2.0 or newer is required to protect against ' \
23
+ 'public gem pushes.'
24
+ end
25
+
26
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
27
+ # Make sure large fixture files are not packaged with the gem every time
28
+ f.match(%r{^spec/fixtures/})
29
+ end
30
+ spec.bindir = 'exe'
31
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
+ spec.require_paths = ['lib']
33
+
34
+ spec.add_dependency 'faraday', '~> 0.13'
35
+ spec.add_dependency 'dotenv', '~> 2.2'
36
+ spec.add_dependency 'ks', '~> 0.0.1'
37
+
38
+ spec.add_development_dependency 'bundler', '~> 1.16'
39
+ spec.add_development_dependency 'pry', '~> 0.11'
40
+ spec.add_development_dependency 'rake', '~> 10.0'
41
+ spec.add_development_dependency 'rspec', '~> 3.0'
42
+ spec.add_development_dependency 'simplecov', '~> 0.15'
43
+ spec.add_development_dependency 'wetransfer_style', '0.5.0'
44
+ end
metadata ADDED
@@ -0,0 +1,201 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wetransfer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Noah Berman
8
+ - David Bosveld
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2018-05-07 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: faraday
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '0.13'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '0.13'
28
+ - !ruby/object:Gem::Dependency
29
+ name: dotenv
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '2.2'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '2.2'
42
+ - !ruby/object:Gem::Dependency
43
+ name: ks
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: 0.0.1
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: 0.0.1
56
+ - !ruby/object:Gem::Dependency
57
+ name: bundler
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '1.16'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '1.16'
70
+ - !ruby/object:Gem::Dependency
71
+ name: pry
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '0.11'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '0.11'
84
+ - !ruby/object:Gem::Dependency
85
+ name: rake
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '10.0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '10.0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: rspec
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - "~>"
103
+ - !ruby/object:Gem::Version
104
+ version: '3.0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - "~>"
110
+ - !ruby/object:Gem::Version
111
+ version: '3.0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: simplecov
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - "~>"
117
+ - !ruby/object:Gem::Version
118
+ version: '0.15'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - "~>"
124
+ - !ruby/object:Gem::Version
125
+ version: '0.15'
126
+ - !ruby/object:Gem::Dependency
127
+ name: wetransfer_style
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - '='
131
+ - !ruby/object:Gem::Version
132
+ version: 0.5.0
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - '='
138
+ - !ruby/object:Gem::Version
139
+ version: 0.5.0
140
+ description: Ruby bindings for using WeTransfer's Public API.
141
+ email:
142
+ - noah@wetransfer.com
143
+ - david@wetransfer.com
144
+ - developers@wetransfer.com
145
+ executables: []
146
+ extensions: []
147
+ extra_rdoc_files: []
148
+ files:
149
+ - ".gitignore"
150
+ - ".rspec"
151
+ - ".rubocop.yml"
152
+ - ".travis.yml"
153
+ - CODE_OF_CONDUCT.md
154
+ - CONTRIBUTING.md
155
+ - Gemfile
156
+ - LICENSE.txt
157
+ - README.md
158
+ - Rakefile
159
+ - bin/console
160
+ - bin/setup
161
+ - lib/wetransfer.rb
162
+ - lib/wetransfer/client.rb
163
+ - lib/wetransfer/connection.rb
164
+ - lib/wetransfer/item.rb
165
+ - lib/wetransfer/item_builder.rb
166
+ - lib/wetransfer/transfer.rb
167
+ - lib/wetransfer/transfer_builder.rb
168
+ - lib/wetransfer/version.rb
169
+ - spec/client_spec.rb
170
+ - spec/connection_spec.rb
171
+ - spec/item_builder_spec.rb
172
+ - spec/spec_helper.rb
173
+ - spec/test_server.rb
174
+ - spec/wetransfer_spec.rb
175
+ - wetransfer.gemspec
176
+ homepage: https://developers.wetransfer.com
177
+ licenses:
178
+ - MIT
179
+ metadata:
180
+ allowed_push_host: https://rubygems.org
181
+ post_install_message:
182
+ rdoc_options: []
183
+ require_paths:
184
+ - lib
185
+ required_ruby_version: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - ">="
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ required_rubygems_version: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ requirements: []
196
+ rubyforge_project:
197
+ rubygems_version: 2.6.13
198
+ signing_key:
199
+ specification_version: 4
200
+ summary: A Ruby SDK for WeTransfer's Public API
201
+ test_files: []