box-api 0.1.9 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/box-api.gemspec +1 -1
- data/doc/Box.html +5 -5
- data/doc/Box/Account.html +430 -188
- data/doc/Box/Api.html +731 -428
- data/doc/Box/Api/AccountExceeded.html +3 -3
- data/doc/Box/Api/EmailInvalid.html +6 -6
- data/doc/Box/Api/EmailTaken.html +3 -3
- data/doc/Box/Api/ErrorStatus.html +3 -3
- data/doc/Box/Api/Exception.html +3 -3
- data/doc/Box/Api/Generic.html +3 -3
- data/doc/Box/Api/InvalidFolder.html +6 -6
- data/doc/Box/Api/InvalidInput.html +3 -3
- data/doc/Box/Api/InvalidName.html +3 -3
- data/doc/Box/Api/NameTaken.html +3 -3
- data/doc/Box/Api/NoAccess.html +3 -3
- data/doc/Box/Api/NoParent.html +3 -3
- data/doc/Box/Api/NotAuthorized.html +3 -3
- data/doc/Box/Api/Restricted.html +6 -6
- data/doc/Box/Api/SizeExceeded.html +3 -3
- data/doc/Box/Api/Unknown.html +3 -3
- data/doc/Box/Api/UnknownResponse.html +6 -6
- data/doc/Box/Api/UploadFailed.html +6 -6
- data/doc/Box/Comment.html +560 -0
- data/doc/Box/File.html +318 -53
- data/doc/Box/Folder.html +298 -136
- data/doc/Box/Item.html +398 -348
- data/doc/_index.html +22 -7
- data/doc/class_list.html +1 -1
- data/doc/css/full_list.css +2 -0
- data/doc/css/style.css +2 -0
- data/doc/file.README.html +3 -3
- data/doc/frames.html +1 -1
- data/doc/index.html +3 -3
- data/doc/js/full_list.js +23 -6
- data/doc/method_list.html +233 -89
- data/doc/top-level-namespace.html +3 -3
- data/examples/files.rb +3 -5
- data/examples/login.rb +14 -18
- data/lib/box/account.rb +57 -16
- data/lib/box/api.rb +34 -1
- data/lib/box/api/exceptions.rb +3 -0
- data/lib/box/comment.rb +50 -0
- data/lib/box/file.rb +31 -0
- data/lib/box/folder.rb +57 -1
- data/lib/box/item.rb +20 -4
- data/spec/account_spec.rb +4 -0
- data/spec/file_spec.rb +37 -0
- data/spec/folder_spec.rb +78 -0
- data/spec/helper/account.rb +1 -1
- metadata +55 -61
@@ -6,7 +6,7 @@
|
|
6
6
|
<title>
|
7
7
|
Top Level Namespace
|
8
8
|
|
9
|
-
— Documentation by YARD 0.7.
|
9
|
+
— Documentation by YARD 0.7.3
|
10
10
|
|
11
11
|
</title>
|
12
12
|
|
@@ -94,9 +94,9 @@
|
|
94
94
|
</div>
|
95
95
|
|
96
96
|
<div id="footer">
|
97
|
-
Generated on
|
97
|
+
Generated on Tue Nov 8 15:32:24 2011 by
|
98
98
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
99
|
-
0.7.
|
99
|
+
0.7.3 (ruby-1.9.3).
|
100
100
|
</div>
|
101
101
|
|
102
102
|
</body>
|
data/examples/files.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
# log in using the login example, so we don't have to duplicate code
|
2
1
|
$: << File.dirname(__FILE__) # for 1.9
|
2
|
+
|
3
|
+
# log in using the login example, so we don't have to duplicate code
|
3
4
|
require 'login'
|
4
5
|
|
5
6
|
# get the root of the folder structure
|
@@ -16,18 +17,15 @@ index = gets
|
|
16
17
|
|
17
18
|
begin
|
18
19
|
# grab the folder they selected
|
19
|
-
# to_i or [] will throw an exception if the index is invalid or out of range respectively
|
20
20
|
folder = root.folders[index.to_i]
|
21
21
|
rescue
|
22
|
-
# they picked
|
22
|
+
# they picked a folder that broke our script!
|
23
23
|
puts "You picked an invalid folder, please try again."
|
24
24
|
exit
|
25
25
|
end
|
26
26
|
|
27
|
-
# the folder they picked was valid
|
28
27
|
puts "Excellent choice, here are the contents of that folder"
|
29
28
|
|
30
|
-
# show the selected folder
|
31
29
|
puts "FOLDER: #{ folder.name } (#{ folder.id })"
|
32
30
|
|
33
31
|
# loop through and show each of the sub files and folders
|
data/examples/login.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
|
-
# add the lib directory to our require path (you do not need this if you
|
1
|
+
# add the lib directory to our require path (you do not need this if you use the box-api gem)
|
2
2
|
$: << File.dirname(__FILE__) + "/../lib"
|
3
3
|
|
4
4
|
# we use bundler to keep all of our gems up to date, but it is optional
|
5
5
|
require 'rubygems'
|
6
6
|
require 'bundler/setup'
|
7
7
|
|
8
|
-
|
9
|
-
require 'box/account'
|
8
|
+
require 'box-api'
|
10
9
|
|
11
10
|
# launchy is a simple gem that opens a browser, but is completely optional
|
12
11
|
require 'launchy'
|
@@ -19,18 +18,17 @@ app_data = YAML.load_file(app_data_file)
|
|
19
18
|
# you need to get your own API key at http://www.box.net/developers/services
|
20
19
|
account = Box::Account.new(app_data['api_key'])
|
21
20
|
|
22
|
-
#
|
23
|
-
# this auth token works between sessions, so read it from disk if the user has authed before
|
21
|
+
# read any auth tokens if they are saved, so we don't have to re-authenticate on Box
|
24
22
|
auth_token = app_data['auth_token']
|
25
23
|
|
26
|
-
#
|
27
|
-
account.authorize(auth_token) do |auth_url|
|
24
|
+
# try to authorize using the auth token, or request a new one if not
|
25
|
+
account.authorize(:auth_token => auth_token) do |auth_url|
|
28
26
|
# this block is called if the auth_token is invalid or missing
|
29
27
|
|
30
|
-
# we use launchy to open a new browser
|
28
|
+
# we use launchy to open a new browser to the given url
|
31
29
|
Launchy.open(auth_url)
|
32
30
|
|
33
|
-
#
|
31
|
+
# wait until the user authenticates on box before continuing
|
34
32
|
puts "Please press the enter key once you have authorized this application to use your account"
|
35
33
|
gets
|
36
34
|
end
|
@@ -41,17 +39,15 @@ unless account.authorized?
|
|
41
39
|
exit
|
42
40
|
end
|
43
41
|
|
44
|
-
#
|
45
|
-
|
42
|
+
# we managed to log in successfully!
|
43
|
+
puts "Logged in as #{ account.login }"
|
44
|
+
|
45
|
+
# this is so the other example can access the account variable
|
46
|
+
@account = account
|
47
|
+
|
48
|
+
# this auth token will let us instantly authorize next time this app is run, so we save it
|
46
49
|
app_data['auth_token'] = account.auth_token
|
47
50
|
|
48
|
-
# we write the auth_token to file so it can be accessed on next run
|
49
51
|
File.open(app_data_file, 'w') do |file|
|
50
52
|
YAML.dump(app_data, file)
|
51
53
|
end
|
52
|
-
|
53
|
-
# we managed to log in successfully!
|
54
|
-
puts "Logged in as #{ account.info['login'] }"
|
55
|
-
|
56
|
-
# this is so the other example can access the account variable (bad practice)
|
57
|
-
@account = account
|
data/lib/box/account.rb
CHANGED
@@ -42,7 +42,7 @@ module Box
|
|
42
42
|
true
|
43
43
|
end
|
44
44
|
|
45
|
-
# Authorize the account using the given auth token, or request
|
45
|
+
# Authorize the account using the given auth token/ticket, or request
|
46
46
|
# permission from the user to let this application use their account.
|
47
47
|
#
|
48
48
|
# An auth token can be reused from previous authorizations provided the
|
@@ -51,8 +51,18 @@ module Box
|
|
51
51
|
# normally and requires the user to log in and provide access for their
|
52
52
|
# account.
|
53
53
|
#
|
54
|
-
#
|
55
|
-
#
|
54
|
+
# A ticket can be used for applications that do not block on the user,
|
55
|
+
# such as a website, where specifying a redirection url is not possible.
|
56
|
+
#
|
57
|
+
# In order to maintain backwards compatibility, a ticket can only be
|
58
|
+
# specified in the hash syntax, while an auth token can be used in
|
59
|
+
# either the hash or string syntax.
|
60
|
+
#
|
61
|
+
# @param [Optional, String, Hash{:ticket,:auth_token => String}] details
|
62
|
+
# Uses an existing auth token or ticket. If nil, a new ticket
|
63
|
+
# will be generated and used. If a String, it is assumed to be
|
64
|
+
# an auth_token (depreciated). If a Hash, then any values of
|
65
|
+
# the :ticket and :auth_token keys will be used to authenticate.
|
56
66
|
# @yield [authorize_url] This block called when the user has not yet
|
57
67
|
# granted this application permission to use their account. You
|
58
68
|
# must have the user navigate to the passed url and authorize
|
@@ -68,15 +78,24 @@ module Box
|
|
68
78
|
#
|
69
79
|
# @example Authorize an account using an existing auth token.
|
70
80
|
# auth_token = "saved auth token" # load from file ideally
|
71
|
-
# account.authorize(auth_token)
|
81
|
+
# account.authorize(:auth_token => auth_token)
|
72
82
|
#
|
73
83
|
# @example Combining the above two for the best functionality.
|
74
84
|
# auth_token = "saved auth token" # load from file if possible
|
75
|
-
# account.authorize(auth_token) do |auth_url|
|
85
|
+
# account.authorize(:auth_token => auth_token) do |auth_url|
|
76
86
|
# # auth token was invalid or nil, have the user visit auth_url
|
77
87
|
# end
|
78
88
|
#
|
79
|
-
def authorize(
|
89
|
+
def authorize(details = nil)
|
90
|
+
# for backwards compatibility
|
91
|
+
if details.is_a?(Hash)
|
92
|
+
auth_token = details[:auth_token]
|
93
|
+
ticket = details[:ticket]
|
94
|
+
else
|
95
|
+
auth_token = details
|
96
|
+
ticket = nil
|
97
|
+
end
|
98
|
+
|
80
99
|
# use a saved auth token if it is given
|
81
100
|
if auth_token
|
82
101
|
return true if authorize_token(auth_token)
|
@@ -84,12 +103,12 @@ module Box
|
|
84
103
|
|
85
104
|
# the auth token either failed or was not provided
|
86
105
|
# we must try to authorize a ticket, and call the block if that fails
|
87
|
-
if not authorize_ticket and block_given?
|
106
|
+
if not authorize_ticket(ticket) and block_given?
|
88
107
|
# the supplied block should instruct the user to visit this url
|
89
|
-
yield authorize_url
|
108
|
+
yield authorize_url(ticket)
|
90
109
|
|
91
110
|
# try authorizing once more
|
92
|
-
authorize_ticket
|
111
|
+
authorize_ticket(ticket)
|
93
112
|
end
|
94
113
|
|
95
114
|
# return our authorized status
|
@@ -152,17 +171,36 @@ module Box
|
|
152
171
|
@info != nil
|
153
172
|
end
|
154
173
|
|
155
|
-
protected
|
156
|
-
|
157
|
-
# @return [Api] The api currently in use.
|
158
|
-
attr_reader :api
|
159
|
-
|
160
174
|
# Get the cached ticket or request a new one from the Box api.
|
161
175
|
# @return [String] The authorization ticket.
|
162
176
|
def ticket
|
163
177
|
@ticket ||= @api.get_ticket['ticket']
|
164
178
|
end
|
165
179
|
|
180
|
+
# Provides an easy way to access this account's info.
|
181
|
+
#
|
182
|
+
# @example
|
183
|
+
# account.login # returns @info['login']
|
184
|
+
def method_missing(sym, *args, &block)
|
185
|
+
super unless authorized?
|
186
|
+
|
187
|
+
# TODO: Use symbols instead of strings
|
188
|
+
str = sym.to_s
|
189
|
+
|
190
|
+
return @info[str] if @info.key?(str)
|
191
|
+
|
192
|
+
super
|
193
|
+
end
|
194
|
+
|
195
|
+
def respond_to?(sym)
|
196
|
+
@info.key?(sym.to_s) or super
|
197
|
+
end
|
198
|
+
|
199
|
+
protected
|
200
|
+
|
201
|
+
# @return [Api] The api currently in use.
|
202
|
+
attr_reader :api
|
203
|
+
|
166
204
|
# The url the user needs to visit in order to grant this application
|
167
205
|
# permission to use their account. This requires a ticket, which
|
168
206
|
# is either pulled from the cache or requested.
|
@@ -171,7 +209,8 @@ module Box
|
|
171
209
|
# If no ticket is provided, one will be requested and cached.
|
172
210
|
# @return [String] the url used for authorizing this account.
|
173
211
|
#
|
174
|
-
def authorize_url(ticket =
|
212
|
+
def authorize_url(ticket = nil)
|
213
|
+
ticket = self.ticket unless ticket
|
175
214
|
"#{ api.base_url }/auth/#{ ticket }"
|
176
215
|
end
|
177
216
|
|
@@ -183,7 +222,9 @@ module Box
|
|
183
222
|
# If no ticket is provided, one will be requested and cached.
|
184
223
|
# @return [String, nil] The auth token if successful otherwise, nil.
|
185
224
|
#
|
186
|
-
def authorize_ticket(ticket =
|
225
|
+
def authorize_ticket(ticket = nil)
|
226
|
+
ticket = self.ticket unless ticket
|
227
|
+
|
187
228
|
begin
|
188
229
|
response = @api.get_auth_token(ticket)
|
189
230
|
|
data/lib/box/api.rb
CHANGED
@@ -129,7 +129,7 @@ module Box
|
|
129
129
|
end
|
130
130
|
end
|
131
131
|
|
132
|
-
raise ErrorStatus, response.code unless response.success? # when the http return code is not normal
|
132
|
+
raise ErrorStatus, "HTTP code #{ response.code }" unless response.success? # when the http return code is not normal
|
133
133
|
response
|
134
134
|
end
|
135
135
|
|
@@ -298,5 +298,38 @@ module Box
|
|
298
298
|
def new_copy(path, file_id, name = nil)
|
299
299
|
query_upload('new_copy', file_id, 'upload_ok', :file => ::File.new(path), :new_file_name => name)
|
300
300
|
end
|
301
|
+
|
302
|
+
# Gets the comments posted on the given item.
|
303
|
+
#
|
304
|
+
# @param ["file"] target The type of item.
|
305
|
+
# @param [String] target_id The id of the item to get.
|
306
|
+
def get_comments(target, target_id)
|
307
|
+
query_rest('get_comments_ok', :action => :get_comments, :target => target, :target_id => target_id)
|
308
|
+
end
|
309
|
+
|
310
|
+
# Adds a new comment to the given item.
|
311
|
+
#
|
312
|
+
# @param ["file"] target The type of item.
|
313
|
+
# @param [String] target_id The id of the item to add to.
|
314
|
+
# @param [String] message The message to use.
|
315
|
+
def add_comment(target, target_id, message)
|
316
|
+
query_rest('add_comment_ok', :action => :add_comment, :target => target, :target_id => target_id, :message => message)
|
317
|
+
end
|
318
|
+
|
319
|
+
# Deletes a given comment.
|
320
|
+
#
|
321
|
+
# @param [String] comment_id The id of the comment to delete.
|
322
|
+
def delete_comment(comment_id)
|
323
|
+
query_rest('delete_comment_ok', :action => :delete_comment, :target_id => comment_id)
|
324
|
+
end
|
325
|
+
|
326
|
+
# Request the HTML embed code for a file.
|
327
|
+
#
|
328
|
+
# @param [String] id The id of the file to use.
|
329
|
+
# @param [Hash] options The properties for the generated preview code.
|
330
|
+
# See File#embed_code for a more detailed list of options.
|
331
|
+
def file_embed(id, options = Hash.new)
|
332
|
+
query_rest('s_create_file_embed', { :action => :create_file_embed, :file_id => id }.merge(options))
|
333
|
+
end
|
301
334
|
end
|
302
335
|
end
|
data/lib/box/api/exceptions.rb
CHANGED
data/lib/box/comment.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
module Box
|
2
|
+
class Comment
|
3
|
+
def self.create(api, comments)
|
4
|
+
if comments
|
5
|
+
comments = [ comments ] if comments.class == Hash
|
6
|
+
|
7
|
+
comments.collect do |comment|
|
8
|
+
sub_comments = comment.delete('reply_comments')
|
9
|
+
|
10
|
+
comment['id'] = comment.delete('comment_id')
|
11
|
+
comment['comments'] = self.create(api, sub_comments['item']) if sub_comments
|
12
|
+
|
13
|
+
Comment.new(api, comment)
|
14
|
+
end
|
15
|
+
else
|
16
|
+
Array.new
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Create a new comment object for a file.
|
21
|
+
#
|
22
|
+
# @param [Api] api The {Api} instance used to generate requests.
|
23
|
+
# @param [Hash] data The hash of initial info for this item, like 'id' and 'message'.
|
24
|
+
def initialize(api, data)
|
25
|
+
@api = api
|
26
|
+
@data = data
|
27
|
+
end
|
28
|
+
|
29
|
+
def id; @data['id']; end
|
30
|
+
|
31
|
+
def method_missing(sym, *args, &block)
|
32
|
+
# TODO: Use symbols instead of strings for keys.
|
33
|
+
sym = sym.to_s
|
34
|
+
|
35
|
+
return @data[sym] if @data.key?(sym)
|
36
|
+
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
40
|
+
def respond_to?(sym)
|
41
|
+
@data.key?(sym.to_s) or super
|
42
|
+
end
|
43
|
+
|
44
|
+
def delete
|
45
|
+
@api.delete_comment(id)
|
46
|
+
|
47
|
+
true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/box/file.rb
CHANGED
@@ -40,6 +40,37 @@ module Box
|
|
40
40
|
self.class.new(api, parent, info)
|
41
41
|
end
|
42
42
|
|
43
|
+
# Get the comments left on this file.
|
44
|
+
#
|
45
|
+
# @return [Array] An array of {Comment}s.
|
46
|
+
def get_comments
|
47
|
+
comments = @api.get_comments(type, id)['comments']
|
48
|
+
|
49
|
+
comments = Comment.create(@api, comments['comment']) if comments
|
50
|
+
|
51
|
+
@data['comments'] = comments || Array.new
|
52
|
+
end
|
53
|
+
|
54
|
+
# Add a comment to the file.
|
55
|
+
#
|
56
|
+
# @return [Comment] The created comment.
|
57
|
+
def add_comment(message)
|
58
|
+
response = @api.add_comment(type, id, message)
|
59
|
+
|
60
|
+
Comment.create(@api, response['comment']).first
|
61
|
+
end
|
62
|
+
|
63
|
+
# Request the HTML embed code for this file.
|
64
|
+
#
|
65
|
+
# @param [Optional, Hash{:allow_download,:allow_print,:allow_share,
|
66
|
+
# :width,:height,:color => String}] options Options to use
|
67
|
+
# when generating the embed code.
|
68
|
+
# @return [String] HTML code to use to embed the file.
|
69
|
+
#
|
70
|
+
def embed_code(options = Hash.new)
|
71
|
+
@api.file_embed(id, options)['file_embed_html']
|
72
|
+
end
|
73
|
+
|
43
74
|
protected
|
44
75
|
|
45
76
|
# (see Item#get_info)
|
data/lib/box/folder.rb
CHANGED
@@ -122,6 +122,62 @@ module Box
|
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
125
|
+
# Get the item at the given path.
|
126
|
+
#
|
127
|
+
# @param [String] The path to search for. This follows the typical unix
|
128
|
+
# path syntax, in that the root folder is '/'. Supports
|
129
|
+
# the dot sytax, where '.' is the current folder and
|
130
|
+
# '..' is the parent folder.
|
131
|
+
#
|
132
|
+
# @return [Item] The item that exists at this path, or nil.
|
133
|
+
#
|
134
|
+
# @example Find a folder based on its absolute path.
|
135
|
+
# folder.at('/box/is/awesome')
|
136
|
+
#
|
137
|
+
# @example Find a file based on a relative path.
|
138
|
+
# folder.at('awesome/file.pdf')
|
139
|
+
#
|
140
|
+
# @example Find a folder using the parent.
|
141
|
+
# folder.at('../other/folder')
|
142
|
+
def at(target_path)
|
143
|
+
# start with this folder
|
144
|
+
current = self
|
145
|
+
|
146
|
+
if target_path.start_with?('/')
|
147
|
+
# absolute path, find the root folder
|
148
|
+
current = current.parent while current.parent != nil
|
149
|
+
end
|
150
|
+
|
151
|
+
# split each part of the target path
|
152
|
+
target_path.split('/').each do |target_name|
|
153
|
+
# update current based on the target name
|
154
|
+
current = case target_name
|
155
|
+
when "", "."
|
156
|
+
# no-op
|
157
|
+
current
|
158
|
+
when ".."
|
159
|
+
# use the parent folder
|
160
|
+
parent
|
161
|
+
else
|
162
|
+
# must be a file/folder name, so make sure this is a folder
|
163
|
+
return nil unless current and current.type == 'folder'
|
164
|
+
|
165
|
+
# search for an item with that name
|
166
|
+
current.find(:name => target_name, :recursive => false).first
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
if current
|
171
|
+
# ends with a slash, so it has to be a folder
|
172
|
+
if target_path.end_with?('/') and current.type != 'folder'
|
173
|
+
# get the folder with the same name (if it exists)
|
174
|
+
current = parent.find(:type => 'folder', :name => name, :recursive => false).first
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
current
|
179
|
+
end
|
180
|
+
|
125
181
|
protected
|
126
182
|
|
127
183
|
attr_accessor :cached_tree
|
@@ -180,7 +236,7 @@ module Box
|
|
180
236
|
def find!(criteria, recursive)
|
181
237
|
matches = (files + folders).collect do |item| # search over our files and folders
|
182
238
|
match = criteria.all? do |key, value| # make sure all criteria pass
|
183
|
-
item.send(key)
|
239
|
+
value === item.send(key) rescue false
|
184
240
|
end
|
185
241
|
|
186
242
|
item if match # use the item if it is a match
|