lib/nv/niconico/video.rb in nv-1.0.1 vs lib/nv/niconico/video.rb in nv-1.2.1
- old
+ new
@@ -9,38 +9,124 @@
@flv = nil
@id = normalize(ptr) # pvid | thumb_cached
end
def download(output=".")
- escapedTitle = thumb.title.gsub(/\//, "/")
- filename = "#{escapedTitle} - [#{thumb.video_id}].#{thumb.extension}"
- filepath = File.join(output, filename)
+ escaped_title = escape_string(thumb.title)
+ escaped_output = escape_string(output)
- Dir.mkdir(output) unless Dir.exist? output
+ filename = sprintf OUTPUT_NAME, {:title => escaped_title, :id => thumb.video_id, :extension => thumb.extension}
+ filepath = File.join(escaped_output, filename)
+ filepath_nvdownload = "#{filepath}.nvdownload"
+ # Return when video file is already exist
+ if File.exist? filepath
+ File.delete filepath_nvdownload if File.exist? filepath_nvdownload
+ return
+ end
+
+ # Create output dir
+ Dir.mkdir escaped_output unless Dir.exist? escaped_output
+
+ # Define request headers
+ options = {
+ 'Cookie' => flv.history_cookies
+ }
+ if File.exist? filepath_nvdownload
+ options['Range'] = "bytes=#{File.size(filepath_nvdownload)}-"
+ end
+
+ # Download video
progress_bar = nil
- File.open(filepath, 'wb') do |fp|
- open(flv.url, 'rb',
- 'Cookie' => flv.history_cookies,
- :content_length_proc => lambda{ |content_length|
- if content_length
- progress_bar = ProgressBar.create(:total => content_length)
+ url = URI.parse(flv.url)
+ begin
+ Net::HTTP.start(url.host, url.port) do |http|
+ header = http.request_head("#{url.path}?#{url.query}", options)
+ progress_bar = ProgressBar.create(:total => header['content-length'].to_i)
+ transferred_bytes = 0
+ request = Net::HTTP::Get.new(url, options)
+ http.request request do |response|
+ open(filepath_nvdownload, 'ab') do |io|
+ response.read_body do |chunk|
+ transferred_bytes += chunk.size
+ if progress_bar
+ progress_bar.progress = transferred_bytes
+ else
+ puts "#{transferred_bytes} / Total size is unknown"
+ end
+
+ io.write chunk
+ end
end
- },
- :progress_proc => lambda{ |transferred_bytes|
- if progress_bar
- progress_bar.progress = transferred_bytes
- else
- puts "#{transferred_bytes} / Total size is unknown"
- end
- }
- ) do |f|
- fp.print f.read
+ end
end
+ rescue => e
+ puts "Failed download: #{e}"
+ return
end
+
+ # Rename .nvdownload to real file
+ File.rename(filepath_nvdownload, filepath)
end
+ # GET http://flapi.nicovideo.jp/api/getwaybackkey?thread=1345476375
+ # => waybackkey=1417346808.E9d0LUF9gvFvt3Rrf5TP91Pa0LA
+
+ # POST http://msg.nicovideo.jp/53/api/
+ # <packet><thread thread="1345476375" version="20090904" user_id="1501297" scores="1" nicoru="1" with_global="1"/><thread_leaves thread="1345476375" user_id="1501297" scores="1" nicoru="1">0-14:100,1000</thread_leaves></packet>
+ # <packet>
+ # <thread thread="1345476375"
+ # version="20090904"
+ # waybackkey="1417346808.E9d0LUF9gvFvt3Rrf5TP91Pa0LA"
+ # when="1417346804"
+ # user_id="1501297"
+ # scores="1"
+ # nicoru="1"
+ # />
+ # <thread_leaves
+ # thread="1345476375"
+ # waybackkey="1417346808.E9d0LUF9gvFvt3Rrf5TP91Pa0LA"
+ # when="1417346804" # 起点
+ # user_id="1501297"
+ # res_before="8541"
+ # scores="1"
+ # nicoru="1" >0-14:100,1000</thread_leaves>
+ # </packet>
+ # <chat thread="1345476375" no="8540" vpos="55658" date="1417346426" mail="184" user_id="tzaiW5hp-SvJG6UGkEa0kELQd3w" anonymity="1" leaf="9">白いレースのハンカチかな?</chat>
+ # <chat thread="1345476375" no="8539" vpos="41534" date="1417233687" mail="184" user_id="1p_4U9fr-YvliRaUl3E6XGEavp4" premium="1" anonymity="1" leaf="6">くっそwwww</chat>
+ def download_comments(output=".")
+ escaped_title = escape_string(thumb.title)
+ escaped_output = escape_string(output)
+
+ filename = sprintf OUTPUT_NAME, {:title => escaped_title, :id => thumb.video_id, :extension => 'comments'}
+ filepath = File.join(escaped_output, filename)
+
+ Dir.mkdir(escaped_output) unless Dir.exist? escaped_output
+
+ url = URI.parse(flv.ms)
+
+ thread_id = flv.thread_id
+ length = (flv.l.to_i / 60).round
+ res = Net::HTTP.new(url.host).start do |http|
+ req = Net::HTTP::Post.new(url.path, {'Cookie' => flv.history_cookies})
+ req.body = %|<packet><thread thread="#{thread_id}" version="20090904" scores="1" nicoru="1" with_global="1"/><thread_leaves thread="#{thread_id}" scores="1" nicoru="1">0-#{length}:10</thread_leaves></packet>|
+ http.request(req)
+ end
+
+ open(filepath, 'w') do |f|
+ f.write res.body
+ end
+
+ # TODO: Comment parser
+ # doc = REXML::Document.new(res.body)
+ # chats = doc.elements.to_a('/packet/chat')
+ # chats.each do |chat|
+ # puts chat.attribute('vpos')
+ # puts chat.text
+ # end
+ end
+
# Combined parameter fetcher
def method_missing(method, *args)
thumb[method] || flv[method] || raise(NoMethodError, method)
end
@@ -76,10 +162,9 @@
})
end
def flv(id=@id)
return @flv if @flv
-
@agent.get("http://www.nicovideo.jp/watch/#{id}")
history_cookie = @agent.cookies.map(&:to_s).join('; ')
flv_str = @agent.get("http://www.nicovideo.jp/api/getflv?v=#{id}").body
flv_hash = Hash[flv_str.split("&").map{|e| i=e.split('=');i[1]=CGI.unescape(i[1]);i }]