dropbox-sdk-v2 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3012cc4be1ed874d4eb5584f39564e7812d93803
4
- data.tar.gz: 7d0d205741968270914b5e4a719fa18dc7488edc
3
+ metadata.gz: 1e9ebfa28c6f64384eb59cacf9dc1d7d9540e07f
4
+ data.tar.gz: cafd6c08e23ac9a3367447433b91f2050b93dcb2
5
5
  SHA512:
6
- metadata.gz: d21f8305e1a3b66d2d81219201df04bcecee3355067d92f83204b936371431cec2c718ec4db124048e4b39d6e79dff248212445785575440e014d5374cbb412d
7
- data.tar.gz: 52723a3ae802a78155e8af7db3f37c940f70d6a356fbe2e648f357ad95684172e99b34a1271ab77b052d1d4be1da3a2cb9473cabed156fa3d1264e764dc7491e
6
+ metadata.gz: a0c84b39b60423ced2aea4e112e01c5ce1034b3d470bc0cb81467f6c597239e228271a4f2dea8a7dcc73ce17c4acfb5189f111ba2ca7dbc0bdff8dc2820a7ff6
7
+ data.tar.gz: 3f1663941133696025b32c435cdbb9892182ce400bfec44d8a36975c0bce1f14a2994bbff4f8fde537c569cc12816f7ad7c537c6bbbca75fa78ee667b13ac714
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Dropbox SDK for Ruby
2
2
 
3
+ [![Gem Version](https://img.shields.io/gem/v/dropbox-sdk-v2.svg)](https://rubygems.org/gems/dropbox-sdk-v2)
3
4
  [![Build Status](https://travis-ci.org/waits/dropbox-sdk-ruby.svg?branch=master)](https://travis-ci.org/waits/dropbox-sdk-ruby)
5
+ [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/waits/dropbox-sdk-ruby/blob/master/LICENSE)
4
6
 
5
7
  This is a small Ruby library for accessing the new [Dropbox API](https://www.dropbox.com/developers/documentation/http/overview). It provides a single class, `Dropbox::Client`, with methods that map to most of the Dropbox API endpoints. Currently all of the endpoints in the `auth`, `files`, and `users` namespaces are supported. Sharing methods are planned.
6
8
 
@@ -27,7 +29,7 @@ gem 'dropbox-sdk-v2'
27
29
 
28
30
  ## Usage
29
31
 
30
- Also see the [full method documentation](http://www.rubydoc.info/gems/dropbox-sdk-v2/Dropbox/Client).
32
+ Also see the [full YARD documentation](http://www.rubydoc.info/github/waits/dropbox-sdk-ruby).
31
33
 
32
34
  Set up a client:
33
35
  ```ruby
@@ -46,16 +48,16 @@ folder.path_lower # => "/myfolder"
46
48
 
47
49
  Upload a file:
48
50
  ```ruby
49
- file = dbx.upload('/myfolder/file.txt', 'the file contents') # Accepts a String or File
50
- file.class # => Dropbox::FileMetadata
51
- file.size # => 17
51
+ # File body can be a String, File, or any Enumerable.
52
+ file = dbx.upload('/myfolder/file.txt', 'file body') # => Dropbox::FileMetadata
53
+ file.size # => 9
52
54
  file.rev # => a1c10ce0dd78
53
55
  ```
54
56
 
55
57
  Download a file:
56
58
  ```ruby
57
59
  file, body = dbx.download('/myfolder/file.txt') # => Dropbox::FileMetadata, HTTP::Response::Body
58
- body.to_s # => "the file contents"
60
+ body.to_s # => "file body"
59
61
  ```
60
62
 
61
63
  Delete a file:
@@ -2,8 +2,14 @@ require_relative 'dropbox/client'
2
2
  require_relative 'dropbox/errors'
3
3
  require_relative 'dropbox/account'
4
4
  require_relative 'dropbox/metadata'
5
+ require_relative 'dropbox/upload_session_cursor'
5
6
 
7
+ # A small library for accessing the new Dropbox API. All of the Dropbox API
8
+ # endpoints are implemented as methods on {Dropbox::Client}.
6
9
  module Dropbox
7
- API = 'https://api.dropboxapi.com/2'
8
- CONTENT_API = 'https://content.dropboxapi.com/2'
10
+ # The main API endpoint used for most calls.
11
+ API = 'https://api.dropboxapi.com/2'.freeze
12
+
13
+ # The content API endpoint used for upload/download calls.
14
+ CONTENT_API = 'https://content.dropboxapi.com/2'.freeze
9
15
  end
@@ -5,8 +5,6 @@ require 'time'
5
5
  module Dropbox
6
6
  # Client contains all the methods that map to the Dropbox API endpoints.
7
7
  class Client
8
- # Initialize a new client.
9
- #
10
8
  # @param [String] access_token
11
9
  def initialize(access_token)
12
10
  unless access_token =~ /^[a-z0-9_-]{64}$/i
@@ -16,6 +14,14 @@ module Dropbox
16
14
  @access_token = access_token
17
15
  end
18
16
 
17
+ # Disable the access token used to authenticate the call.
18
+ #
19
+ # @return [void]
20
+ def revoke_token
21
+ r = HTTP.auth('Bearer ' + @access_token).post(API + '/auth/token/revoke')
22
+ raise ApiError.new(r) if r.code != 200
23
+ end
24
+
19
25
  # Copy a file or folder to a different location in the user's Dropbox.
20
26
  #
21
27
  # @param [String] from_path
@@ -26,13 +32,34 @@ module Dropbox
26
32
  parse_tagged_response(resp)
27
33
  end
28
34
 
35
+ # Get a copy reference to a file or folder.
36
+ #
37
+ # @param [String] path
38
+ # @return [Dropbox::Metadata] metadata
39
+ # @return [String] copy_reference
40
+ def get_copy_reference(path)
41
+ resp = request('/files/copy_reference/get', path: path)
42
+ metadata = parse_tagged_response(resp['metadata'])
43
+ return metadata, resp['copy_reference']
44
+ end
45
+
46
+ # Save a copy reference to the user's Dropbox.
47
+ #
48
+ # @param [String] copy_reference
49
+ # @param [String] path
50
+ # @return [Dropbox::Metadata] metadata
51
+ def save_copy_reference(copy_reference, path)
52
+ resp = request('/files/copy_reference/save', copy_reference: copy_reference, path: path)
53
+ parse_tagged_response(resp['metadata'])
54
+ end
55
+
29
56
  # Create a folder at a given path.
30
57
  #
31
58
  # @param [String] path
32
59
  # @return [Dropbox::FolderMetadata]
33
60
  def create_folder(path)
34
61
  resp = request('/files/create_folder', path: path)
35
- parse_tagged_response(resp, 'folder')
62
+ FolderMetadata.new(resp)
36
63
  end
37
64
 
38
65
  # Delete the file or folder at a given path.
@@ -51,33 +78,7 @@ module Dropbox
51
78
  # @return [HTTP::Response::Body] body
52
79
  def download(path)
53
80
  resp, body = content_request('/files/download', path: path)
54
- return parse_tagged_response(resp, 'file'), body
55
- end
56
-
57
- # Get information about a user's account.
58
- #
59
- # @param [String] account_id
60
- # @return [Dropbox::BasicAccount]
61
- def get_account(account_id)
62
- resp = request('/users/get_account', account_id: account_id)
63
- parse_tagged_response(resp, 'basic_account')
64
- end
65
-
66
- # Get information about multiple user accounts.
67
- #
68
- # @param [Array<String>] account_ids
69
- # @return [Array<Dropbox::BasicAccount>]
70
- def get_account_batch(account_ids)
71
- resp = request('/users/get_account_batch', account_ids: ids)
72
- resp.map { |a| parse_tagged_response(a, 'basic_account') }
73
- end
74
-
75
- # Get information about the current user's account.
76
- #
77
- # @return [Dropbox::FullAccount]
78
- def get_current_account
79
- resp = request('/users/get_current_account')
80
- parse_tagged_response(resp, 'full_account')
81
+ return FileMetadata.new(resp), body
81
82
  end
82
83
 
83
84
  # Get the metadata for a file or folder.
@@ -96,15 +97,7 @@ module Dropbox
96
97
  # @return [HTTP::Response::Body] body
97
98
  def get_preview(path)
98
99
  resp, body = content_request('/files/get_preview', path: path)
99
- return parse_tagged_response(resp, 'file'), body
100
- end
101
-
102
- # Get the space usage information for the current user's account.
103
- #
104
- # @return [Dropbox::SpaceUsage]
105
- def get_space_usage
106
- resp = request('/users/get_space_usage')
107
- SpaceUsage.new(resp)
100
+ return FileMetadata.new(resp), body
108
101
  end
109
102
 
110
103
  # Get a temporary link to stream content of a file.
@@ -114,7 +107,7 @@ module Dropbox
114
107
  # @return [String] link
115
108
  def get_temporary_link(path)
116
109
  resp = request('/files/get_temporary_link', path: path)
117
- return parse_tagged_response(resp['metadata'], 'file'), resp['link']
110
+ return FileMetadata.new(resp['metadata']), resp['link']
118
111
  end
119
112
 
120
113
  # Get a thumbnail for an image.
@@ -126,18 +119,36 @@ module Dropbox
126
119
  # @return [HTTP::Response::Body] body
127
120
  def get_thumbnail(path, format='jpeg', size='w64h64')
128
121
  resp, body = content_request('/files/get_thumbnail', path: path, format: format, size: size)
129
- return parse_tagged_response(resp, 'file'), body
122
+ return FileMetadata.new(resp), body
130
123
  end
131
124
 
132
125
  # Get the contents of a folder.
133
126
  #
134
127
  # @param [String] path
135
- # @return [Array<Dropbox::Metadata]
128
+ # @return [Array<Dropbox::Metadata>]
136
129
  def list_folder(path)
137
130
  resp = request('/files/list_folder', path: path)
138
131
  resp['entries'].map { |e| parse_tagged_response(e) }
139
132
  end
140
133
 
134
+ # Get the contents of a folder that are after a cursor.
135
+ #
136
+ # @param [String] cursor
137
+ # @return [Array<Dropbox::Metadata>]
138
+ def continue_list_folder(cursor)
139
+ resp = request('/files/list_folder/continue', cursor: cursor)
140
+ resp['entries'].map { |e| parse_tagged_response(e) }
141
+ end
142
+
143
+ # Get a cursor for a folder's current state.
144
+ #
145
+ # @param [String] path
146
+ # @return [String] cursor
147
+ def get_latest_list_folder_cursor(path)
148
+ resp = request('/files/list_folder/get_latest_cursor', path: path)
149
+ resp['cursor']
150
+ end
151
+
141
152
  # Get the revisions of a file.
142
153
  #
143
154
  # @param [String] path
@@ -145,7 +156,7 @@ module Dropbox
145
156
  # @return [Boolean] is_deleted
146
157
  def list_revisions(path)
147
158
  resp = request('/files/list_revisions', path: path)
148
- entries = resp['entries'].map { |e| parse_tagged_response(e, 'file') }
159
+ entries = resp['entries'].map { |e| FileMetadata.new(e) }
149
160
  return entries, resp['is_deleted']
150
161
  end
151
162
 
@@ -155,10 +166,19 @@ module Dropbox
155
166
  # @param [String] to_path
156
167
  # @return [Dropbox::Metadata]
157
168
  def move(from_path, to_path)
158
- resp = request('/files/move', from_path: from, to_path: to)
169
+ resp = request('/files/move', from_path: from_path, to_path: to_path)
159
170
  parse_tagged_response(resp)
160
171
  end
161
172
 
173
+ # Permanently delete the file or folder at a given path.
174
+ #
175
+ # @param [String] path
176
+ # @return [void]
177
+ def permanently_delete(path)
178
+ request('/files/permanently_delete', path: path)
179
+ nil
180
+ end
181
+
162
182
  # Restore a file to a specific revision.
163
183
  #
164
184
  # @param [String] path
@@ -166,15 +186,7 @@ module Dropbox
166
186
  # @return [Dropbox::FileMetadata]
167
187
  def restore(path, rev)
168
188
  resp = request('/files/restore', path: path, rev: rev)
169
- parse_tagged_response(resp, 'file')
170
- end
171
-
172
- # Disable the access token used to authenticate the call.
173
- #
174
- # @return [void]
175
- def revoke_token
176
- r = HTTP.auth('Bearer ' + @access_token).post(API + '/auth/token/revoke')
177
- raise APIError.new(r) if r.code != 200
189
+ FileMetadata.new(resp)
178
190
  end
179
191
 
180
192
  # Save a specified URL into a file in user's Dropbox.
@@ -185,46 +197,126 @@ module Dropbox
185
197
  # @return [Dropbox::FileMetadata] if the processing is synchronous.
186
198
  def save_url(path, url)
187
199
  resp = request('/files/save_url', path: path, url: url)
188
- case resp['.tag']
189
- when 'complete'
190
- parse_tagged_response(resp['complete'], 'file')
191
- when 'async_job_id'
192
- resp['async_job_id']
193
- else
194
- raise ClientError.unknown_response_type(resp['.tag'])
195
- end
200
+ parse_tagged_response(resp)
201
+ end
202
+
203
+ # Check the status of a save_url job.
204
+ #
205
+ # @param [String] async_job_id
206
+ # @return [nil] if the job is still in progress.
207
+ # @return [Dropbox::FileMetadata] if the job is complete.
208
+ # @return [String] an error message, if the job failed.
209
+ def check_save_url_job_status(async_job_id)
210
+ resp = request('/files/save_url/check_job_status', async_job_id: async_job_id)
211
+ parse_tagged_response(resp)
196
212
  end
197
213
 
198
214
  # Search for files and folders.
199
215
  #
200
- # @param [String] query
201
216
  # @param [String] path
217
+ # @param [String] query
218
+ # @param [Integer] start
202
219
  # @param [Integer] max_results
220
+ # @param [String] mode
203
221
  # @return [Array<Dropbox::Metadata>] matches
204
- def search(query, path='', max_results=100)
205
- resp = request('/files/search', path: path, query: query, max_results: max)
206
- resp['matches'].map { |m| parse_tagged_response(m['metadata']) }
222
+ def search(path, query, start=0, max_results=100, mode='filename')
223
+ resp = request('/files/search', path: path, query: query, start: start,
224
+ max_results: max_results, mode: mode)
225
+ matches = resp['matches'].map { |m| parse_tagged_response(m['metadata']) }
226
+ return matches
207
227
  end
208
228
 
209
229
  # Create a new file.
210
230
  #
211
231
  # @param [String] path
212
232
  # @param [String, Enumerable] body
213
- # @param [String] mode
214
- # @param [Boolean] autorename
215
- # @param [String, Time] client_modified
216
- # @param [Boolean] mute
233
+ # @option options [String] :mode
234
+ # @option options [Boolean] :autorename
235
+ # @option options [Boolean] :mute
217
236
  # @return [Dropbox::FileMetadata]
218
- def upload(path, body, mode='add', autorename=false, client_modified=nil, mute=false)
219
- client_modified = client_modified.iso8601 if client_modified.is_a?(Time)
220
- resp = upload_request('/files/upload', body, path: path, mode: mode,
221
- autorename: autorename, client_modified: client_modified, mute: mute)
222
- parse_tagged_response(resp, 'file')
237
+ def upload(path, body, options={})
238
+ options[:client_modified] = Time.now.utc.iso8601
239
+ options[:path] = path
240
+ resp = upload_request('/files/upload', body, options.merge(path: path))
241
+ FileMetadata.new(resp)
242
+ end
243
+
244
+ # Start an upload session to upload a file using multiple requests.
245
+ #
246
+ # @param [String, Enumerable] body
247
+ # @param [Boolean] close
248
+ # @return [Dropbox::UploadSessionCursor] cursor
249
+ def start_upload_session(body, close=false)
250
+ resp = upload_request('/files/upload_session/start', body, close: close)
251
+ UploadSessionCursor.new(resp['session_id'], body.length)
252
+ end
253
+
254
+ # Append more data to an upload session.
255
+ #
256
+ # @param [Dropbox::UploadSessionCursor] cursor
257
+ # @param [String, Enumerable] body
258
+ # @param [Boolean] close
259
+ # @return [Dropbox::UploadSessionCursor] cursor
260
+ def append_upload_session(cursor, body, close=false)
261
+ args = {cursor: cursor.to_h, close: close}
262
+ resp = upload_request('/files/upload_session/append_v2', body, args)
263
+ cursor.offset += body.length
264
+ cursor
265
+ end
266
+
267
+ # Finish an upload session and save the uploaded data to the given file path.
268
+ #
269
+ # @param [Dropbox::UploadSessionCursor] cursor
270
+ # @param [String] path
271
+ # @param [String, Enumerable] body
272
+ # @param [Hash] options
273
+ # @option (see #upload)
274
+ # @return [Dropbox::FileMetadata]
275
+ def finish_upload_session(cursor, path, body, options={})
276
+ options[:client_modified] = Time.now.utc.iso8601
277
+ options[:path] = path
278
+ args = {cursor: cursor.to_h, commit: options}
279
+ resp = upload_request('/files/upload_session/finish', body, args)
280
+ FileMetadata.new(resp)
281
+ end
282
+
283
+ # Get information about a user's account.
284
+ #
285
+ # @param [String] account_id
286
+ # @return [Dropbox::BasicAccount]
287
+ def get_account(account_id)
288
+ resp = request('/users/get_account', account_id: account_id)
289
+ BasicAccount.new(resp)
290
+ end
291
+
292
+ # Get information about multiple user accounts.
293
+ #
294
+ # @param [Array<String>] account_ids
295
+ # @return [Array<Dropbox::BasicAccount>]
296
+ def get_account_batch(account_ids)
297
+ resp = request('/users/get_account_batch', account_ids: account_ids)
298
+ resp.map { |a| BasicAccount.new(a) }
299
+ end
300
+
301
+ # Get information about the current user's account.
302
+ #
303
+ # @return [Dropbox::FullAccount]
304
+ def get_current_account
305
+ resp = request('/users/get_current_account')
306
+ FullAccount.new(resp)
307
+ end
308
+
309
+ # Get the space usage information for the current user's account.
310
+ #
311
+ # @return [Dropbox::SpaceUsage]
312
+ def get_space_usage
313
+ resp = request('/users/get_space_usage')
314
+ SpaceUsage.new(resp)
223
315
  end
224
316
 
225
317
  private
226
- def parse_tagged_response(resp, tag=resp['.tag'])
227
- case tag
318
+ def parse_tagged_response(resp)
319
+ case resp['.tag']
228
320
  when 'file'
229
321
  FileMetadata.new(resp)
230
322
  when 'folder'
@@ -235,8 +327,16 @@ module Dropbox
235
327
  BasicAccount.new(resp)
236
328
  when 'full_account'
237
329
  FullAccount.new(resp)
330
+ when 'complete'
331
+ FileMetadata.new(resp)
332
+ when 'async_job_id'
333
+ resp['async_job_id']
334
+ when 'in_progress'
335
+ nil
336
+ when 'failed'
337
+ resp['failed']['.tag']
238
338
  else
239
- raise ClientError.unknown_response_type(tag)
339
+ raise ClientError.unknown_response_type(resp['.tag'])
240
340
  end
241
341
  end
242
342
 
@@ -246,7 +346,7 @@ module Dropbox
246
346
  .headers(content_type: ('application/json' if data))
247
347
  .post(url, json: data)
248
348
 
249
- raise APIError.new(resp) if resp.code != 200
349
+ raise ApiError.new(resp) if resp.code != 200
250
350
  JSON.parse(resp.to_s)
251
351
  end
252
352
 
@@ -255,7 +355,7 @@ module Dropbox
255
355
  resp = HTTP.auth('Bearer ' + @access_token)
256
356
  .headers('Dropbox-API-Arg' => args.to_json).get(url)
257
357
 
258
- raise APIError.new(resp) if resp.code != 200
358
+ raise ApiError.new(resp) if resp.code != 200
259
359
  file = JSON.parse(resp.headers['Dropbox-API-Result'])
260
360
  return file, resp.body
261
361
  end
@@ -267,8 +367,8 @@ module Dropbox
267
367
  'Transfer-Encoding' => ('chunked' unless body.is_a?(String))
268
368
  }).post(CONTENT_API + action, body: body)
269
369
 
270
- raise APIError.new(resp) if resp.code != 200
271
- JSON.parse(resp.to_s)
370
+ raise ApiError.new(resp) if resp.code != 200
371
+ JSON.parse(resp.to_s) unless resp.to_s == 'null'
272
372
  end
273
373
  end
274
374
  end
@@ -1,6 +1,7 @@
1
1
  require 'json'
2
2
 
3
3
  module Dropbox
4
+ # Thrown when Dropbox::Client encounters an error unrelated to the API.
4
5
  class ClientError < StandardError
5
6
  attr_reader :message
6
7
 
@@ -21,7 +22,8 @@ module Dropbox
21
22
  end
22
23
  end
23
24
 
24
- class APIError < StandardError
25
+ # Thrown when the API returns an error response.
26
+ class ApiError < StandardError
25
27
  attr_reader :message
26
28
 
27
29
  def initialize(response)
@@ -1,6 +1,7 @@
1
1
  require 'time'
2
2
 
3
3
  module Dropbox
4
+ # Abstract class inherited by the other metadata classes.
4
5
  class Metadata
5
6
  attr_reader :name, :path_lower, :path_display
6
7
 
@@ -11,6 +12,7 @@ module Dropbox
11
12
  end
12
13
  end
13
14
 
15
+ # Contains the metadata (but not contents) of a file.
14
16
  class FileMetadata < Metadata
15
17
  attr_reader :id, :client_modified, :server_modified, :rev, :size
16
18
 
@@ -24,8 +26,13 @@ module Dropbox
24
26
  @size = attrs.delete('size')
25
27
  super(attrs)
26
28
  end
29
+
30
+ def ==(cmp)
31
+ cmp.is_a?(self.class) && self.id == cmp.id
32
+ end
27
33
  end
28
34
 
35
+ # Contains the metadata (but not contents) of a folder.
29
36
  class FolderMetadata < Metadata
30
37
  attr_reader :id
31
38
 
@@ -33,8 +40,13 @@ module Dropbox
33
40
  @id = attrs.delete('id')
34
41
  super(attrs)
35
42
  end
43
+
44
+ def ==(cmp)
45
+ cmp.is_a?(self.class) && self.id == cmp.id
46
+ end
36
47
  end
37
48
 
49
+ # Contains the metadata of a deleted file.
38
50
  class DeletedMetadata < Metadata
39
51
  end
40
52
  end
@@ -0,0 +1,22 @@
1
+ module Dropbox
2
+ # UploadSessionCursor holds information about an in-progress upload session.
3
+ #
4
+ # @attr [String] session_id A unique identifier for the session.
5
+ # @attr [Integer] offset The size of the data uploaded so far.
6
+ class UploadSessionCursor
7
+ attr_reader :session_id
8
+ attr_accessor :offset
9
+
10
+ # @param [String] session_id
11
+ # @param [Integer] offset
12
+ def initialize(session_id, offset)
13
+ @session_id = session_id
14
+ @offset = offset
15
+ end
16
+
17
+ # @return [Hash]
18
+ def to_h
19
+ {session_id: session_id, offset: offset}
20
+ end
21
+ end
22
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dropbox-sdk-v2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dylan Waits
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-20 00:00:00.000000000 Z
11
+ date: 2016-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -51,6 +51,7 @@ files:
51
51
  - lib/dropbox/client.rb
52
52
  - lib/dropbox/errors.rb
53
53
  - lib/dropbox/metadata.rb
54
+ - lib/dropbox/upload_session_cursor.rb
54
55
  homepage: https://github.com/waits/dropbox-sdk-ruby
55
56
  licenses:
56
57
  - MIT