lib/rapidshare-ext/download.rb in rapidshare-ext-0.0.6 vs lib/rapidshare-ext/download.rb in rapidshare-ext-0.1.0

- old
+ new

@@ -1,47 +1,119 @@ module Rapidshare module Ext - # Note from odiszapc: + # Downloads files from Rapidshare. Separate from +Rapidshare::API+ class because + # downloading is much more complex than other service calls. # + # Displays text progress bar during download. + # + # Note from odiszapc: # 1 oct 2012 the Rapidshare download API (http://images.rapidshare.com/apidoc.txt) was changed # so the base download function provided by rapidshare gem became broken # # In the original method the parameter :filename being interpreted incorrectly now. - # It's being interpreted like a "save file as" parameter. Actually it must be equal to the file name you want to download + # It's being interpreted like a 'save file as' parameter. Actually it must be equal to the file name you want to download # So, to download file now you must specify exactly two parameters: file id and file name. - class Download < Rapidshare::Download + class Download + DOWNLOAD_URL = 'https://rs%s%s.rapidshare.com/cgi-bin/rsapi.cgi?%s' + attr_reader :url, :api, :fileid, :filename, :filesize, :server_id, + :short_host, :downloads_dir, :downloaded, :error + # Options: # * *filename* (optional) - specifies filename under which the file will be # saved. Default: filename parsed from Rapidshare link. # * *downloads_dir* (optional) - specifies directory into which downloaded files # will be saved. Default: current directory. # def initialize(url, api, options = {}) - super + @url = url + @api = api + @filename = options[:save_as] + @downloads_dir = options[:downloads_dir] || Dir.pwd + + # OPTIMIZE replace these simple status variables with status codes + # and corresponding errors like "File not found" + # + # set to true when file is successfully downloaded + @downloaded = false + # non-critical error is stored here, beside being displayed + @error = nil + @local_filename = options[:save_as] @filename = nil # It will be filled automatically by the #check method of the base class end # Checks if file exists (using checkfiles service) and gets data necessary for download. # # Returns true or false, which determines whether the file can be downloaded. # def check - res = super - if res + # PS: Api#checkfiles throws exception when file cannot be found + response = @api.checkfiles(@url).first rescue {} + + if response[:file_status] == :ok + @fileid = response[:file_id] + @filename ||= response[:file_name] + @filesize = response[:file_size].to_i + @server_id = response[:server_id] + @short_host = response[:short_host] + @remote_filename = @filename @filename = @local_filename || @remote_filename + true + else + # TODO report errors according to actual file status + @error = 'File not found' + false end - res end + # Downloads file. Calls +check+ method first. + # When block is given a custom progress bar interpretation can be implemented + def perform + # before downloading we have to check if file exists. checkfiles service + # also gives us information for the download: hostname, file size for + # progressbar + return self unless self.check + + file = open(File.join(@downloads_dir, @filename), 'wb') + block_response = Proc.new do |response| + downloaded = 0 + total = response.header['content-length'].to_i + + unless total == @filesize + @error = 'Access denied' + return self + end + + response.read_body do |chunk| + file << chunk + downloaded += chunk.size + progress = ((downloaded * 100).to_f / total).round(2) + yield chunk.size, downloaded, total, progress if block_given? + end + end + + RestClient::Request.execute(:method => :get, + :url => self.download_link, + :block_response => block_response) + file.close() + @downloaded = true + self + end + # Generates link which downloads file by Rapidshare API # def download_link download_params = { :sub => 'download', :fileid => @fileid, :filename => @remote_filename, :cookie => @api.cookie } DOWNLOAD_URL % [ @server_id, @short_host, download_params.to_query ] + end + + # Says whether file has been successfully downloaded. + # + def downloaded? + @downloaded end end end end \ No newline at end of file