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.
45 46 |
# File 'lib/dbox/api.rb', line 45 def initialize end |
Instance Attribute Details
#client ⇒ Object (readonly)
Returns the value of attribute client.
41 42 43 |
# File 'lib/dbox/api.rb', line 41 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 |
# 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 auth = DropboxSession.new(app_key, app_secret) puts "Please visit the following URL in your browser, log into Dropbox, and authorize the app you created.\n\n#{auth.}\n\nWhen you have done so, press [ENTER] to continue." STDIN.readline res = auth.get_access_token puts "export DROPBOX_AUTH_KEY=#{res.key}" puts "export DROPBOX_AUTH_SECRET=#{res.secret}" 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_AUTH_KEY=#{res.key} DROPBOX_AUTH_SECRET=#{res.secret} dbox ..." end |
.connect ⇒ Object
35 36 37 38 39 |
# File 'lib/dbox/api.rb', line 35 def self.connect api = new() api.connect api end |
Instance Method Details
#connect ⇒ Object
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/dbox/api.rb', line 52 def connect app_key = ENV["DROPBOX_APP_KEY"] app_secret = ENV["DROPBOX_APP_SECRET"] auth_key = ENV["DROPBOX_AUTH_KEY"] auth_secret = ENV["DROPBOX_AUTH_SECRET"] access_type = ENV["DROPBOX_ACCESS_TYPE"] || "dropbox" # "app_folder" 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 raise(ConfigurationError, "Please set the DROPBOX_AUTH_KEY environment variable to an authenticated Dropbox session key") unless auth_key raise(ConfigurationError, "Please set the DROPBOX_AUTH_SECRET environment variable to an authenticated Dropbox session secret") unless auth_secret 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" @session = DropboxSession.new(app_key, app_secret) @session.set_access_token(auth_key, auth_secret) @client = DropboxClient.new(@session, access_type) 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
48 49 50 |
# File 'lib/dbox/api.rb', line 48 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 Exception => 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_PEER 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 |