lib/dropbox/dropbox.rb in dropbox-0.0.2 vs lib/dropbox/dropbox.rb in dropbox-0.0.5

- old
+ new

@@ -1,49 +1,25 @@ -require 'rubygems' require 'nokogiri' require 'mechanize' -WWW::Mechanize.html_parser = Nokogiri::HTML +Mechanize.html_parser = Nokogiri::HTML # TODO: Tests (mock out expected DropBox output) # TODO: Directory object, File object class DropBox #before_filter :login_filter, :except => [:login] def initialize(email, password, folder_namespace = "") @email = email @password = password - @agent = WWW::Mechanize.new + @agent = Mechanize.new @folder_namespace = folder_namespace.gsub(/^\//,"") @logged_in = false end - def login - page = @agent.get('https://www.dropbox.com/login') - login_form = page.forms.detect { |f| f.action == "/login" } - login_form.login_email = @email - login_form.login_password = @password - - home_page = @agent.submit(login_form) - # todo check if we are logged in! (ie search for email and "Log out" - @logged_in = true - @token = home_page.at('//script[contains(text(), "TOKEN")]').content.match("TOKEN: '(.*)',$")[1] - - # check if we have our namespace - - home_page - end - - def login_filter - login unless @logged_in - end - - def list(path = "/") - index(path) - end - + # Lists all the files and folders in a given directory def index(path = "/") login_filter path = namespace_path(path) list = @agent.post("/browse2#{path}?ajax=yes", {"d"=> 1, "t" => @token }) @@ -56,21 +32,29 @@ #details['modified'] = file.at('div.details-modified a').try(:content).try(:strip) if match_data = details['url'].match(/^\/browse_plain(.*)$/) details['directory'] = true details['path'] = normalize_namespace(match_data[1]) - else + elsif match_data = details['url'].match(%r{^https?://[^/]*/get(.*)$}) details['directory'] = false - details['path'] = normalize_namespace(details['url'][33..-1]) + details['path'] = normalize_namespace(match_data[1]) + elsif match_data = details['url'].match(%r{^https?://[^/]*/u/\d*/(.*)$}) + details['directory'] = false + details['path'] = "Public/#{match_data[1]}" + else + raise "could not parse path from Dropbox URL: #{details['url'] }" end details end return listing end + alias :list :index + + # Lists the full history for a file on DropBox def list_history(path) login_filter path = namespace_path(path) @@ -89,74 +73,79 @@ details end return listing end - - def get(path) - show(path) - end + # Downloads the specified file from DropBox def show(path) # change to before filter login_filter path = namespace_path(path) #https://dl-web.dropbox.com/get/testing.txt?w=0ff80d5d&sjid=125987568 @agent.get("https://dl-web.dropbox.com/get/#{path}").content end - + + alias :get :show + + # Creates a directory def create_directory(new_path, destination = "/" ) # change to before filter login unless @logged_in destination = namespace_path(destination) - @agent.post("/cmd/new#{destination}",{"to_path"=>new_path, "folder"=>"yes", "t" => @token }) - # check status code + @agent.post("/cmd/new#{destination}",{"to_path"=>new_path, "folder"=>"yes", "t" => @token }).code == "200" end + # Uploads a file to DropBox under the given filename def create(file, destination = "/") # change to before filter if @logged_in home_page = @agent.get('https://www.dropbox.com/home') else home_page = login end - destination = namespace_path(destination) - upload_form = home_page.forms.detect{ |f| f.action == "https://dl-web.dropbox.com/upload" } - upload_form.dest = "/#{@folder_namespace}/#{destination}" + upload_form.dest = namespace_path(destination) upload_form.file_uploads.first.file_name = file if file - @agent.submit(upload_form) + @agent.submit(upload_form).code == "200" end - - def update(file, destination = "/") - create(file, destination) - end + alias :update :create + + # Renames a file or folder in the DropBox def rename(file, destination) login_filter file = namespace_path(file) destination = namespace_path(destination) - @agent.post("/cmd/rename#{file}", {"to_path"=> destination, "t" => @token }) + @agent.post("/cmd/rename#{file}", {"to_path"=> destination, "t" => @token }).code == "200" end + # Deletes a file/folder from the DropBox (accepts string path or an array of string paths) def destroy(paths) login_filter paths = [paths].flatten paths = paths.collect { |path| namespace_path(path) } - @agent.post("/cmd/delete", {"files"=> paths, "t" => @token }) + @agent.post("/cmd/delete", {"files"=> paths, "t" => @token }).code == "200" end + # Permanently deletes a file from the DropBox (no history!) accepts arrays, as #destroy does def purge(paths) login_filter paths = [paths].flatten paths = paths.collect { |path| namespace_path(path) } - @agent.post("/cmd/purge", {"files"=> paths, "t" => @token }) + @agent.post("/cmd/purge", {"files"=> paths, "t" => @token }).code == "200" end + + # Will give a hash of the amount of space left on the DropBox, the amound used, the calculated amount free (all as a 1 d.p. rounded GB value) and the percentage used (scraped) + def usage_stats + login_filter + @agent.get("/account").at('#usage-percent').content.scan(/(\d+(?:\.\d+)?)%\ used\ \((\d+(?:\.\d+)?)([MG])B of (\d+(?:\.\d+)?)GB\)/).collect{|d| {:used => d[1].to_f * ((d[2] == "M") ? 1024 : 1), :total => d[3].to_f, :free => (d[3].to_f - d[1].to_f * ((d[2] == "M") ? 1024 : 1)), :percent => Percentage.new(d[0].to_f/100)} }[0] + end private def namespace_path(path) # remove the start slash if we have one path.gsub(/^\//,"") @@ -169,6 +158,29 @@ def normalize_namespace(file) file.gsub(/^\/#{@folder_namespace}/,"") end -end \ No newline at end of file + def login + page = @agent.get('https://www.dropbox.com/login') + login_form = page.forms.detect { |f| f.action == "/login" } + login_form.login_email = @email + login_form.login_password = @password + + home_page = @agent.submit(login_form) + # todo check if we are logged in! (ie search for email and "Log out" + @logged_in = true + @token = home_page.at('//script[contains(text(), "TOKEN")]').content.match("TOKEN: '(.*)',$")[1] + + # check if we have our namespace + + home_page + end + + def login_filter + login unless @logged_in + end +end + +# this file doesn't use the standard ruby indent settings, so the following +# modeline will make sure that the whitespace stays consistent. +# vim:noexpandtab tabstop=4 shiftwidth=4