dropbox-sdk-v2 0.0.2 → 0.0.3

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