boxview.rb 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +17 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +22 -0
- data/README.md +268 -0
- data/Rakefile +7 -0
- data/boxview.rb.gemspec +26 -0
- data/lib/boxview.rb +56 -0
- data/lib/boxview/document.rb +364 -0
- data/lib/boxview/errors.rb +147 -0
- data/lib/boxview/session.rb +144 -0
- data/lib/boxview/version.rb +3 -0
- data/spec/lib/boxview/document_spec.rb +87 -0
- data/spec/lib/boxview/errors_spec.rb +5 -0
- data/spec/lib/boxview/session_spec.rb +29 -0
- data/spec/lib/boxview/version_spec.rb +11 -0
- data/spec/lib/boxview_spec.rb +28 -0
- data/spec/spec_helper.rb +5 -0
- metadata +127 -0
@@ -0,0 +1,364 @@
|
|
1
|
+
module BoxView
|
2
|
+
class Document
|
3
|
+
|
4
|
+
# ToDo: Investigate https://github.com/jwagener/httmultiparty
|
5
|
+
# For multi part upload support
|
6
|
+
|
7
|
+
PATH = '/documents'
|
8
|
+
ZIP = 'zip' # Constant for generating a zip of assets of a document
|
9
|
+
PDF = 'pdf' # Constant for generating a pdf of a document
|
10
|
+
|
11
|
+
class << self
|
12
|
+
|
13
|
+
attr_accessor :url, :name, :non_svg, :type, :width, :height, :retry_after, :filepath
|
14
|
+
|
15
|
+
# Description:
|
16
|
+
# => The getter method for the url of a box view compatible file. Look at supported_mimetypes.
|
17
|
+
# No Params!
|
18
|
+
# Note:
|
19
|
+
# => Raises an error if the url is nil.
|
20
|
+
def url
|
21
|
+
raise BoxView::Errors::UrlNotFound if @url.nil?
|
22
|
+
@url
|
23
|
+
end
|
24
|
+
|
25
|
+
# Description:
|
26
|
+
# => The getter method for the filepath of a box view compatible file. Look at supported_mimetypes.
|
27
|
+
# No Params!
|
28
|
+
# Note:
|
29
|
+
# => Raises an error if the filepath is nil or does not exist.
|
30
|
+
def filepath
|
31
|
+
raise BoxView::Errors::FilepathNotFound if @filepath.nil? || !File.file?(@filepath)
|
32
|
+
@filepath
|
33
|
+
end
|
34
|
+
|
35
|
+
# Description:
|
36
|
+
# => The setter method for the type of asset to be downloaded.
|
37
|
+
# Required Params:
|
38
|
+
# => type
|
39
|
+
# Note:
|
40
|
+
# => This method only accepts pdf or zip as types.
|
41
|
+
def type=(type)
|
42
|
+
raise BoxView::Errors::TypeNotFound if ![ZIP, PDF].include? type.downcase
|
43
|
+
@type = type
|
44
|
+
end
|
45
|
+
|
46
|
+
#########################################################
|
47
|
+
|
48
|
+
### BEGIN Document HTTP Requests ###
|
49
|
+
|
50
|
+
# Description:
|
51
|
+
# => Sends a document url (and other metadata) for Box to download
|
52
|
+
# Required Paramaters:
|
53
|
+
# => URL: Url of the file to convert. (.pdf, .doc, .docx, .ppt, and .pptx)
|
54
|
+
# Optional Paramaters:
|
55
|
+
# => name: Name of the document.
|
56
|
+
# => non_svg: false by default, enable to support < IE9 browsers
|
57
|
+
# => width: width of a thumbnail that will be generated from this document (16-1024)
|
58
|
+
# => height: height of a thumbnail that will be generated from this document (16-768)
|
59
|
+
# Note:
|
60
|
+
# => The params may be passed in when calling the function or defined before hand.
|
61
|
+
def create(options = {})
|
62
|
+
response = BoxView.post document_path, body: json_data(options), headers: BoxView.headers
|
63
|
+
create_response_handler response
|
64
|
+
return response
|
65
|
+
end
|
66
|
+
|
67
|
+
# Description:
|
68
|
+
# => Allows metadata, specifically the name of a document to be updated. Requires a document id.
|
69
|
+
# Optional Params:
|
70
|
+
# => Name, Document ID
|
71
|
+
def update(options = {})
|
72
|
+
name = options[:name] if options[:name]
|
73
|
+
BoxView.document_id = options[:document_id] if options[:document_id]
|
74
|
+
response = BoxView.put document_path, body: {name: name}.to_json, headers: BoxView.headers
|
75
|
+
update_response_handler response
|
76
|
+
return response
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
# Description:
|
81
|
+
# => Uses https://github.com/jwagener/httmultiparty for multipart uploading while still using HTTParty
|
82
|
+
# No Params!
|
83
|
+
def multipart(options = {})
|
84
|
+
BoxView.base_uri BoxView::MULTIPART_URI
|
85
|
+
(multipart_headers = BoxView.headers).delete('Content-type')
|
86
|
+
response = BoxView.post document_path, body: multipart_data(options), headers: multipart_headers, detect_mime_type: true
|
87
|
+
multipart_response_handler response
|
88
|
+
return response
|
89
|
+
end
|
90
|
+
|
91
|
+
# Description:
|
92
|
+
# => This request will list all the current documents that were uploaded to box view by api key.
|
93
|
+
# No Params!
|
94
|
+
def list
|
95
|
+
response = BoxView.get document_path, headers: BoxView.headers
|
96
|
+
list_response_handler response
|
97
|
+
return response
|
98
|
+
end
|
99
|
+
|
100
|
+
# Description:
|
101
|
+
# => Returns the box view object for a specific document. Requires a document id.
|
102
|
+
# No Params!
|
103
|
+
def show(options = {})
|
104
|
+
BoxView.document_id = options[:document_id] if options[:document_id]
|
105
|
+
response = BoxView.get "#{document_path}/#{BoxView.document_id}", headers: BoxView.headers
|
106
|
+
show_response_handler response
|
107
|
+
return response
|
108
|
+
end
|
109
|
+
|
110
|
+
# Description:
|
111
|
+
# => Delete a document from box view given a document id.
|
112
|
+
# No Required Params!
|
113
|
+
# Optional Params:
|
114
|
+
# => Document ID
|
115
|
+
def delete(options = {})
|
116
|
+
BoxView.document_id = options[:document_id] if options[:document_id]
|
117
|
+
response = BoxView.delete "#{document_path}/#{BoxView.document_id}", headers: BoxView.headers
|
118
|
+
delete_response_handler response
|
119
|
+
return response
|
120
|
+
end
|
121
|
+
|
122
|
+
# Description:
|
123
|
+
# =>
|
124
|
+
# No Params!
|
125
|
+
# Description:
|
126
|
+
# => Returns a pdf or zip representation of a document that has previously been uploaded to box view. Requires a document id.
|
127
|
+
# No Required Params!
|
128
|
+
# Optional Params:
|
129
|
+
# => Type, Document ID
|
130
|
+
def assets(options = {})
|
131
|
+
BoxView.document_id = options[:document_id] if options[:document_id]
|
132
|
+
type = options[:type] if options[:type]
|
133
|
+
response = BoxView.get asset_url, headers: BoxView.headers
|
134
|
+
asset_response_handler response
|
135
|
+
return response
|
136
|
+
end
|
137
|
+
|
138
|
+
# Description:
|
139
|
+
# => Returns a thumbnail image representation of a document that has previously been uploaded to box view. Requires a document id.
|
140
|
+
# => Inform BoxView early by specifying width and height when creating the document.
|
141
|
+
# No Required Params!
|
142
|
+
# Optional Params:
|
143
|
+
# => Width, Height, Document ID
|
144
|
+
def thumbnail(options = {})
|
145
|
+
BoxView.document_id = options[:document_id] if options[:document_id]
|
146
|
+
width = options[:width] if options[:width]
|
147
|
+
height = options[:height] if options[:height]
|
148
|
+
response = BoxView.get thumbnail_url, headers: BoxView.headers
|
149
|
+
thumbnail_response_handler response
|
150
|
+
return response
|
151
|
+
end
|
152
|
+
|
153
|
+
### END Document HTTP Requests ###
|
154
|
+
|
155
|
+
# Description:
|
156
|
+
# => A path that is used for all document related requests.
|
157
|
+
# No Params!
|
158
|
+
def document_path
|
159
|
+
"#{BoxView::BASE_PATH}#{PATH}"
|
160
|
+
end
|
161
|
+
|
162
|
+
# Description:
|
163
|
+
# => A convenience method that contains all of the supported mimetypes of Box View.
|
164
|
+
# No Params!
|
165
|
+
def supported_mimetypes
|
166
|
+
[ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
167
|
+
"application/vnd.openxmlformats-officedocument.presentationml.slideshow",
|
168
|
+
"application/vnd.ms-powerpoint",
|
169
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
170
|
+
"application/msword",
|
171
|
+
"application/pdf"
|
172
|
+
]
|
173
|
+
end
|
174
|
+
|
175
|
+
# Description:
|
176
|
+
# => A convenience method that contains all the supported extension types of Box View
|
177
|
+
# No Params!
|
178
|
+
def supported_file_extensions
|
179
|
+
['.pdf', '.doc', '.docx', '.ppt', '.pptx']
|
180
|
+
end
|
181
|
+
|
182
|
+
# Description:
|
183
|
+
# => The asset url that is used in the request for document assets.
|
184
|
+
# No Params!
|
185
|
+
# Note:
|
186
|
+
# => Type defaults to zip if not defined.
|
187
|
+
# => A Document ID must be defined.
|
188
|
+
def asset_url
|
189
|
+
type = if @type then @type else ZIP end # Defaults to ZIP
|
190
|
+
"#{document_path}/#{BoxView.document_id}/content.#{type}"
|
191
|
+
end
|
192
|
+
|
193
|
+
# Description: Params for retrieving a thumbnail of a certain size
|
194
|
+
# => Minimum Width and Height is 16
|
195
|
+
# => Maximum Width is 1024
|
196
|
+
# => Maximum Height is 768
|
197
|
+
# No Params!
|
198
|
+
# Note: Height and Width MUST be defined.
|
199
|
+
def thumbnail_params
|
200
|
+
raise BoxView::Errors::DimensionsNotFound if width.nil? || height.nil?
|
201
|
+
"?width=#{width}&height=#{height}"
|
202
|
+
end
|
203
|
+
|
204
|
+
# Description:
|
205
|
+
# =>
|
206
|
+
# No Params!
|
207
|
+
def dimensions
|
208
|
+
raise BoxView::Errors::DimensionsNotFound if width.nil? || height.nil?
|
209
|
+
"#{width}x#{height}"
|
210
|
+
end
|
211
|
+
|
212
|
+
# Description:
|
213
|
+
# => Path to request thumbnail generation for a specific document. Requires document id, width and height.
|
214
|
+
# No Params!
|
215
|
+
def thumbnail_url
|
216
|
+
"#{document_path}/#{BoxView.document_id}/thumbnail#{thumbnail_params}"
|
217
|
+
end
|
218
|
+
|
219
|
+
private
|
220
|
+
|
221
|
+
# Description:
|
222
|
+
# => Response Handler for the thumbnail request
|
223
|
+
# Required Params:
|
224
|
+
# => response
|
225
|
+
def thumbnail_response_handler(response)
|
226
|
+
case response.code
|
227
|
+
when 200 # Valid thumbnail
|
228
|
+
when 202 # Thumbnail isn't ready yet
|
229
|
+
retry_after = response['Retry-After']
|
230
|
+
when 400 # Width/Height are invalid
|
231
|
+
raise BoxView::Errors::ThumbnailInvalidWidthHeight
|
232
|
+
else
|
233
|
+
raise BoxView::Errors::ThumbnailGenerationFailed
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
# Description:
|
238
|
+
# => Response Handler for the delete request
|
239
|
+
# Required Params:
|
240
|
+
# => response
|
241
|
+
def delete_response_handler(response)
|
242
|
+
case response.code
|
243
|
+
when 200
|
244
|
+
else
|
245
|
+
raise BoxView::Errors::DocumentDeletionFailed.new(response)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
# Description:
|
250
|
+
# => Response Handler for the asset request
|
251
|
+
# Required Params:
|
252
|
+
# => response
|
253
|
+
def asset_response_handler(response)
|
254
|
+
case response.code
|
255
|
+
when 200
|
256
|
+
else
|
257
|
+
raise BoxView::Errors::AssetGeneratioFailed.new(response)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
# Description:
|
262
|
+
# => Response Handler for the show request
|
263
|
+
# Required Params:
|
264
|
+
# => response
|
265
|
+
def show_response_handler(response)
|
266
|
+
case response.code
|
267
|
+
when 200
|
268
|
+
else
|
269
|
+
raise BoxView::Errors::DocumentFetchFailed.new(response)
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
# Description:
|
274
|
+
# => Response Handler for the list request
|
275
|
+
# Required Params:
|
276
|
+
# => response
|
277
|
+
def list_response_handler(response)
|
278
|
+
case response.code
|
279
|
+
when 200
|
280
|
+
else
|
281
|
+
raise BoxView::Errors::DocumentListFetchFailed.new(response)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
# Description:
|
286
|
+
# => Response Handler for the create request
|
287
|
+
# Required Params:
|
288
|
+
# => response
|
289
|
+
def create_response_handler(response)
|
290
|
+
if (200..202).include? response.code
|
291
|
+
parsed = JSON.parse response.body
|
292
|
+
document_id = parsed["id"]
|
293
|
+
BoxView.document_id = document_id
|
294
|
+
else
|
295
|
+
raise BoxView::Errors::DocumentIdNotGenerated.new(response)
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
# Description:
|
300
|
+
# => Response Handler for the update request
|
301
|
+
# Required Params:
|
302
|
+
# => response
|
303
|
+
def update_response_handler(response)
|
304
|
+
if (200..202).include? response.code
|
305
|
+
parsed = JSON.parse response.body
|
306
|
+
document_id = parsed["id"]
|
307
|
+
BoxView.document_id = document_id
|
308
|
+
else
|
309
|
+
raise BoxView::Errors::DocumentNotUpdated.new(response)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
# Description:
|
314
|
+
# => Response Handler for the multipart request
|
315
|
+
# Required Params:
|
316
|
+
# => response
|
317
|
+
def multipart_response_handler(response)
|
318
|
+
BoxView.base_uri BoxView::BASE_URI # restores original base_uri
|
319
|
+
if (200..202).include? response.code
|
320
|
+
parsed = JSON.parse response.body
|
321
|
+
document_id = parsed["id"]
|
322
|
+
BoxView.document_id = document_id
|
323
|
+
else
|
324
|
+
raise BoxView::Errors::DocumentNotUpdated.new(response)
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
# Description:
|
329
|
+
# => The JSON that is sent in document creation requests.
|
330
|
+
# No Required Params!
|
331
|
+
# Optional Params:
|
332
|
+
# => URL, Name, Width, Height, non_svg
|
333
|
+
def json_data(options = {})
|
334
|
+
options.each do |k,v|
|
335
|
+
send "#{k}=", v if v
|
336
|
+
end
|
337
|
+
data = {}
|
338
|
+
data[:url] = url
|
339
|
+
data[:name] = name if name
|
340
|
+
data[:thumbnails] = dimensions if width && height
|
341
|
+
data[:non_svg] = non_svg if non_svg
|
342
|
+
return data.to_json
|
343
|
+
end
|
344
|
+
|
345
|
+
# Description:
|
346
|
+
# => The hash that is sent in document multipart requests.
|
347
|
+
# No Required Params!
|
348
|
+
# Optional Params:
|
349
|
+
# => Filepath, Name, Width, Height, non_svg
|
350
|
+
def multipart_data(options = {})
|
351
|
+
options.each do |k,v|
|
352
|
+
send "#{k}=", v if v
|
353
|
+
end
|
354
|
+
data = {}
|
355
|
+
data[:file] = File.new(filepath, 'r') if filepath
|
356
|
+
data[:name] = name if name
|
357
|
+
data[:thumbnails] = dimensions if width && height
|
358
|
+
data[:non_svg] = non_svg if non_svg
|
359
|
+
return data
|
360
|
+
end
|
361
|
+
|
362
|
+
end
|
363
|
+
end
|
364
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
module BoxView
|
2
|
+
class Errors < StandardError
|
3
|
+
|
4
|
+
def initialize(message, error = nil)
|
5
|
+
# super message
|
6
|
+
if error.nil?
|
7
|
+
super message
|
8
|
+
else
|
9
|
+
case error
|
10
|
+
when 400 then super "#{message} - Error Code: 400 - Document does not exist or failed converting."
|
11
|
+
else super message
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class DocumentNotUpdated < StandardError
|
17
|
+
DOCUMENT_UPDATE_ERROR_MESSAGE = "The document failed to update."
|
18
|
+
def initialize(response = nil)
|
19
|
+
super "#{DOCUMENT_UPDATE_ERROR_MESSAGE} - with ID: #{BoxView.document_id} - Response Code: #{response.code}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class AssetGenerationFailed < StandardError
|
24
|
+
ASSET_GENERATION_ERROR_MESSAGE = "The assets failed to generate."
|
25
|
+
def initialize(response = nil)
|
26
|
+
super "#{ASSET_GENERATION_ERROR_MESSAGE} - with ID: #{BoxView.document_id} - Response Code: #{response.code}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class DocumentListFetchFailed < StandardError
|
31
|
+
DOCUMENT_LIST_ERROR_MESSAGE = "Could not fetch document list."
|
32
|
+
def initialize(response = nil)
|
33
|
+
super "#{DOCUMENT_LIST_ERROR_MESSAGE} - Response Code: #{response.code}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class DocumentDeletionFailed < StandardError
|
38
|
+
DOCUMENT_DELETE_ERROR_MESSAGE = "Could not delete document."
|
39
|
+
def initialize(response = nil)
|
40
|
+
super "#{DOCUMENT_DELETE_ERROR_MESSAGE} - Response Code: #{response.code}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class DocumentFetchFailed < StandardError
|
45
|
+
DOCUMENT_ERROR_MESSAGE = "Could not fetch document."
|
46
|
+
def initialize(response = nil)
|
47
|
+
super "#{DOCUMENT_ERROR_MESSAGE} - with ID: #{BoxView.document_id} - Response Code: #{response.code}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class DocumentIdNotGenerated < StandardError
|
52
|
+
DOCUMENT_ID_ERROR_MESSAGE = "The document id has failed to be generated."
|
53
|
+
def initialize(response = nil)
|
54
|
+
if response
|
55
|
+
super "#{DOCUMENT_ID_ERROR_MESSAGE} - Response Code: #{response.code}"
|
56
|
+
else
|
57
|
+
super DOCUMENT_ID_ERROR_MESSAGE
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class DocumentConversionFailed < StandardError
|
63
|
+
CONVERSION_ERROR_MESSAGE = "Converting the document has failed."
|
64
|
+
def initialize
|
65
|
+
super CONVERSION_ERROR_MESSAGE
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class SessionNotGenerated < StandardError
|
70
|
+
GENERATION_ERROR_MESSAGE = "Session could not be generated."
|
71
|
+
def initialize
|
72
|
+
super GENERATION_ERROR_MESSAGE
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class ThumbnailGenerationFailed < StandardError
|
77
|
+
GENERATION_ERROR_MESSAGE = "Thumbnail could not be generated."
|
78
|
+
def initialize
|
79
|
+
super GENERATION_ERROR_MESSAGE
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class ThumbnailInvalidWidthHeight < StandardError
|
84
|
+
WIDTH_HEIGHT_ERROR_MESSAGE = "The thumbnails width or height is invalid."
|
85
|
+
def initialize
|
86
|
+
super WIDTH_HEIGHT_ERROR_MESSAGE
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class ApiKeyNotFound < StandardError
|
91
|
+
API_KEY_ERROR_MESSAGE = "API Key is nil." # test to make sure it is string, digits and alphanumeric, correct length?
|
92
|
+
def initialize
|
93
|
+
super API_KEY_ERROR_MESSAGE
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class DimensionsNotFound < StandardError
|
98
|
+
DIMENSIONS_ERROR_MESSAGE = "Height and Width must both be specified."
|
99
|
+
def initialize
|
100
|
+
super DIMENSIONS_ERROR_MESSAGE
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
class DocumentIdNotFound < StandardError
|
105
|
+
DOCUMENT_ID_ERROR_MESSAGE = "Document ID must be specified."
|
106
|
+
def initialize
|
107
|
+
super DOCUMENT_ID_ERROR_MESSAGE
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class ExpirationDateNotFound < StandardError
|
112
|
+
EXPIRATION_DATE_ERROR_MESSAGE = "An Expiration Date must be specified."
|
113
|
+
def initialize
|
114
|
+
super EXPIRATION_DATE_ERROR_MESSAGE
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
class DurationNotFound < StandardError
|
119
|
+
DURATION_ERROR_MESSAGE = "A Duration must be specified."
|
120
|
+
def initialize
|
121
|
+
super DURATION_ERROR_MESSAGE
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
class SessionIdNotFound < StandardError
|
126
|
+
SESSION_ID_ERROR_MESSAGE = "A Session ID must be specified."
|
127
|
+
def initialize
|
128
|
+
super SESSION_ID_ERROR_MESSAGE
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
class TypeNotFound < StandardError
|
133
|
+
TYPE_ERROR_MESSAGE = "A type must be specified."
|
134
|
+
def initialize
|
135
|
+
super TYPE_ERROR_MESSAGE
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
class UrlNotFound < StandardError
|
140
|
+
URL_ERROR_MESSAGE = "A url must be specified."
|
141
|
+
def initialize
|
142
|
+
super URL_ERROR_MESSAGE
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
end
|