Class: Dbox::API
Instance Attribute Summary collapse
-
#client ⇒ Object
readonly
Returns the value of attribute client.
Class Method Summary collapse
Instance Method Summary collapse
- #connect ⇒ Object
- #create_dir(path) ⇒ Object
- #delete_dir(path) ⇒ Object
- #delete_file(path) ⇒ Object
- #get_file(path, file_obj, stream = false) ⇒ Object
- #handle_response(path, res, &else_proc) ⇒ Object
-
#initialize ⇒ API
constructor
A new instance of API.
- #initialize_copy(other) ⇒ Object
- #metadata(path = "/", hash = nil, list = true) ⇒ Object
- #move(old_path, new_path) ⇒ Object
- #put_file(path, local_path, previous_revision = nil) ⇒ Object
- #run(path, tries = NUM_TRIES, &proc) ⇒ Object
- #streaming_download(url, io, num_redirects = 0) ⇒ Object
Methods included from Loggable
Constructor Details
#initialize ⇒ API
Returns a new instance of API.
54 55 |
# File 'lib/dbox/api.rb', line 54 def initialize end |
Instance Attribute Details
#client ⇒ Object (readonly)
Returns the value of attribute client.
50 51 52 |
# File 'lib/dbox/api.rb', line 50 def client @client end |
Class Method Details
.authorize ⇒ Object
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/dbox/api.rb', line 14 def self. app_key = ENV["DROPBOX_APP_KEY"] app_secret = ENV["DROPBOX_APP_SECRET"] raise(ConfigurationError, "Please set the DROPBOX_APP_KEY environment variable to a Dropbox application key") unless app_key raise(ConfigurationError, "Please set the DROPBOX_APP_SECRET environment variable to a Dropbox application secret") unless app_secret flow = DropboxOAuth2FlowNoRedirect.new(app_key, app_secret) = flow.start() puts '1. Go to: ' + puts '2. Click "Allow" (you might have to log in first)' puts '3. Copy the authorization code' print 'Enter the authorization code here: ' code = STDIN.readline.strip # This will fail if the user gave us an invalid authorization code access_token, user_id = flow.finish(code) puts "export DROPBOX_ACCESS_TOKEN=#{access_token}" puts "export DROPBOX_USER_ID=#{user_id}" puts puts "This auth token will last for 10 years, or when you choose to invalidate it, whichever comes first." puts puts "Now either include these constants in yours calls to dbox, or set them as environment variables." puts "In bash, including them in calls looks like:" puts "$ DROPBOX_ACCESS_TOKEN=#{access_token} DROPBOX_USER_ID=#{user_id} dbox ..." end |
.connect ⇒ Object
44 45 46 47 48 |
# File 'lib/dbox/api.rb', line 44 def self.connect api = new() api.connect api end |
Instance Method Details
#connect ⇒ Object
61 62 63 64 65 66 67 68 |
# File 'lib/dbox/api.rb', line 61 def connect access_token = ENV["DROPBOX_ACCESS_TOKEN"] access_type = ENV["DROPBOX_ACCESS_TYPE"] || "dropbox" raise(ConfigurationError, "Please set the DROPBOX_ACCESS_TOKEN environment variable to a Dropbox access token") unless access_token raise(ConfigurationError, "Please set the DROPBOX_ACCESS_TYPE environment variable either dropbox (full access) or sandbox (App access)") unless access_type == "dropbox" || access_type == "app_folder" @client = DropboxClient.new(access_token) end |
#create_dir(path) ⇒ Object
133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/dbox/api.rb', line 133 def create_dir(path) run(path) do log.info "Creating #{path}" begin @client.file_create_folder(path) rescue DropboxError => e if e.http_response.kind_of?(Net::HTTPForbidden) raise RemoteAlreadyExists, "Either the directory at #{path} already exists, or it has invalid characters in the name" else raise e end end end end |
#delete_dir(path) ⇒ Object
148 149 150 151 152 153 |
# File 'lib/dbox/api.rb', line 148 def delete_dir(path) run(path) do log.info "Deleting #{path}" @client.file_delete(path) end end |
#delete_file(path) ⇒ Object
189 190 191 192 193 194 |
# File 'lib/dbox/api.rb', line 189 def delete_file(path) run(path) do log.info "Deleting #{path}" @client.file_delete(path) end end |
#get_file(path, file_obj, stream = false) ⇒ Object
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/dbox/api.rb', line 155 def get_file(path, file_obj, stream=false) unless stream # just download directly using the get_file API res = run(path) do log.info "Downloading #{path}" @client.get_file(path) end if res.kind_of?(String) file_obj << res true else raise DropboxError.new("Invalid response #{res.inspect}") end else # use the media API to get a URL that we can stream from, and # then stream the file to disk res = run(path) { @client.media(path) } url = res[:url] if res && res.kind_of?(Hash) if url log.info "Downloading #{path}" streaming_download(url, file_obj) else get_file(path, file_obj, false) end end end |
#handle_response(path, res, &else_proc) ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/dbox/api.rb', line 104 def handle_response(path, res, &else_proc) case res when Hash InsensitiveHash[res] when String res when Net::HTTPNotFound raise RemoteMissing, "#{path} does not exist on Dropbox" when Net::HTTPForbidden raise RequestDenied, "Operation on #{path} denied" when Net::HTTPNotModified :not_modified when true true else else_proc.call() end end |
#initialize_copy(other) ⇒ Object
57 58 59 |
# File 'lib/dbox/api.rb', line 57 def initialize_copy(other) @client = other.client.clone() end |
#metadata(path = "/", hash = nil, list = true) ⇒ Object
123 124 125 126 127 128 129 130 131 |
# File 'lib/dbox/api.rb', line 123 def (path = "/", hash = nil, list=true) run(path) do log.debug "Fetching metadata for #{path}" res = @client.(path, 10000, list, hash) log.debug res.inspect raise Dbox::RemoteMissing, "#{path} has been deleted on Dropbox" if res["is_deleted"] res end end |
#move(old_path, new_path) ⇒ Object
196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/dbox/api.rb', line 196 def move(old_path, new_path) run(old_path) do log.info "Moving #{old_path} to #{new_path}" begin @client.file_move(old_path, new_path) rescue DropboxError => e if e.http_response.kind_of?(Net::HTTPForbidden) raise RemoteAlreadyExists, "Error during move -- there may already be a Dropbox folder at #{new_path}" else raise e end end end end |
#put_file(path, local_path, previous_revision = nil) ⇒ Object
182 183 184 185 186 187 |
# File 'lib/dbox/api.rb', line 182 def put_file(path, local_path, previous_revision=nil) run(path) do log.info "Uploading #{path}" File.open(local_path, "r") {|f| @client.put_file(path, f, false, previous_revision) } end end |
#run(path, tries = NUM_TRIES, &proc) ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/dbox/api.rb', line 70 def run(path, tries = NUM_TRIES, &proc) begin res = proc.call handle_response(path, res) { raise RuntimeError, "Unexpected result: #{res.inspect}" } rescue DropboxNotModified => e :not_modified rescue DropboxAuthError => e raise e rescue DropboxError => e if tries > 0 if e.http_response.kind_of?(Net::HTTPServiceUnavailable) log.info "Encountered 503 on #{path} (likely rate limiting). Sleeping #{TIME_BETWEEN_TRIES}s and trying again." # TODO check for "Retry-After" header and use that for sleep instead of TIME_BETWEEN_TRIES log.info "Headers: #{e.http_response.to_hash.inspect}" else log.info "Encountered a dropbox error. Sleeping #{TIME_BETWEEN_TRIES}s and trying again. Error: #{e.inspect}" log.info "Headers: #{e.http_response.to_hash.inspect}" end sleep TIME_BETWEEN_TRIES run(path, tries - 1, &proc) else handle_response(path, e.http_response) { raise ServerError, "Server error -- might be a hiccup, please try your request again (#{e.})" } end rescue => e if tries > 0 log.info "Encounted an unknown error. Sleeping #{TIME_BETWEEN_TRIES}s and trying again. Error: #{e.inspect}" sleep TIME_BETWEEN_TRIES run(path, tries - 1, &proc) else raise e end end end |
#streaming_download(url, io, num_redirects = 0) ⇒ Object
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/dbox/api.rb', line 211 def streaming_download(url, io, num_redirects = 0) url = URI.parse(url) http = Net::HTTP.new(url.host, url.port) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE http.ca_file = Dropbox::TRUSTED_CERT_FILE req = Net::HTTP::Get.new(url.request_uri) req["User-Agent"] = "OfficialDropboxRubySDK/#{Dropbox::SDK_VERSION}" http.request(req) do |res| if res.kind_of?(Net::HTTPSuccess) # stream into given io res.read_body {|chunk| io.write(chunk) } true else if res.kind_of?(Net::HTTPRedirection) && res.header['location'] && num_redirects < 10 log.info("following redirect, num_redirects = #{num_redirects}") log.info("redirect url: #{res.header['location']}") streaming_download(res.header['location'], io, num_redirects + 1) else raise DropboxError.new("Invalid response #{res.inspect}") end end end end |