wetransfer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []