viddl-rb 0.8 → 0.61
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.txt +14 -0
- data/Gemfile.lock +7 -29
- data/README.md +34 -122
- data/Rakefile +8 -22
- data/bin/viddl-rb +117 -45
- data/helper/download-helper.rb +67 -94
- data/helper/plugin-helper.rb +10 -60
- data/plugins/blip.rb +2 -3
- data/plugins/metacafe.rb +54 -53
- data/plugins/soundcloud.rb +15 -19
- data/plugins/veoh.rb +41 -40
- data/plugins/vimeo.rb +23 -30
- data/plugins/youtube.rb +138 -266
- metadata +29 -50
- data/TODO.txt +0 -3
- data/bin/helper/downloader.rb +0 -20
- data/bin/helper/driver.rb +0 -47
- data/bin/helper/parameter-parser.rb +0 -109
- data/helper/audio-helper.rb +0 -48
- data/helper/utility-helper.rb +0 -45
- data/lib/viddl-rb.rb +0 -103
- data/plugins/dailymotion.rb +0 -44
data/lib/viddl-rb.rb
DELETED
@@ -1,103 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'helper')
|
3
|
-
|
4
|
-
require "rubygems"
|
5
|
-
require "net/http"
|
6
|
-
require "nokogiri"
|
7
|
-
require "mechanize"
|
8
|
-
require "cgi"
|
9
|
-
require "open-uri"
|
10
|
-
require "stringio"
|
11
|
-
require "download-helper.rb"
|
12
|
-
require "plugin-helper.rb"
|
13
|
-
require "utility-helper.rb"
|
14
|
-
|
15
|
-
#load all plugins
|
16
|
-
ViddlRb::UtilityHelper.load_plugins
|
17
|
-
|
18
|
-
module ViddlRb
|
19
|
-
class PluginError < StandardError; end
|
20
|
-
class DownloadError < StandardError; end
|
21
|
-
|
22
|
-
def self.io=(io_object)
|
23
|
-
PluginBase.io = io_object
|
24
|
-
end
|
25
|
-
|
26
|
-
#set the default PluginBase io object to a StringIO instance.
|
27
|
-
#this will suppress any standard output from the plugins.
|
28
|
-
self.io = StringIO.new
|
29
|
-
|
30
|
-
#returns an array of hashes containing the download url(s) and filenames(s)
|
31
|
-
#for the specified video url.
|
32
|
-
#if the url does not match any plugin, return nil and if a plugin
|
33
|
-
#throws an error, throw PluginError.
|
34
|
-
#the reason for returning an array is because some urls will give multiple
|
35
|
-
#download urls (for example a Youtube playlist url).
|
36
|
-
def self.get_urls_names(url)
|
37
|
-
plugin = PluginBase.registered_plugins.find { |p| p.matches_provider?(url) }
|
38
|
-
|
39
|
-
if plugin
|
40
|
-
begin
|
41
|
-
#we'll end up with an array of hashes with they keys :url and :name
|
42
|
-
urls_filenames = plugin.get_urls_and_filenames(url)
|
43
|
-
rescue PluginBase::CouldNotDownloadVideoError => e
|
44
|
-
raise_download_error(e)
|
45
|
-
rescue StandardError => e
|
46
|
-
raise_plugin_error(e, plugin)
|
47
|
-
end
|
48
|
-
follow_all_redirects(urls_filenames)
|
49
|
-
else
|
50
|
-
nil
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
#returns an array of download urls for the given video url.
|
55
|
-
def self.get_urls(url)
|
56
|
-
urls_filenames = get_urls_names(url)
|
57
|
-
urls_filenames.nil? ? nil : urls_filenames.map { |uf| uf[:url] }
|
58
|
-
end
|
59
|
-
|
60
|
-
#returns an array of filenames for the given video url.
|
61
|
-
def self.get_names(url)
|
62
|
-
urls_filenames = get_urls_names(url)
|
63
|
-
urls_filenames.nil? ? nil : urls_filenames.map { |uf| uf[:name] }
|
64
|
-
end
|
65
|
-
|
66
|
-
#same as get_urls_and_filenames but with the extensions only.
|
67
|
-
def self.get_urls_exts(url)
|
68
|
-
urls_filenames = get_urls_names(url)
|
69
|
-
urls_filenames.map do |uf|
|
70
|
-
ext = File.extname(uf[:name])
|
71
|
-
{:url => uf[:url], :ext => ext}
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
#<<< helper methods >>>
|
76
|
-
|
77
|
-
#the default error message when a plugin fails in some unexpected way.
|
78
|
-
def self.raise_plugin_error(e, plugin)
|
79
|
-
error = PluginError.new(e.message + " [Plugin: #{plugin.name}]")
|
80
|
-
error.set_backtrace(e.backtrace)
|
81
|
-
raise error
|
82
|
-
end
|
83
|
-
private_class_method :raise_plugin_error
|
84
|
-
|
85
|
-
#the default error message when a plugin fails to download a video for a known reason.
|
86
|
-
def self.raise_download_error(e)
|
87
|
-
error = DownloadError.new(e.message)
|
88
|
-
error.set_backtrace(e.backtrace)
|
89
|
-
raise error
|
90
|
-
end
|
91
|
-
private_class_method :raise_download_error
|
92
|
-
|
93
|
-
#takes a url-filenames array and returns a new array where the
|
94
|
-
#"location" header has been followed all the way to the end for all urls.
|
95
|
-
def self.follow_all_redirects(urls_filenames)
|
96
|
-
urls_filenames.map do |uf|
|
97
|
-
url = uf[:url]
|
98
|
-
final_location = UtilityHelper.get_final_location(url)
|
99
|
-
{:url => final_location, :name => uf[:name]}
|
100
|
-
end
|
101
|
-
end
|
102
|
-
private_class_method :follow_all_redirects
|
103
|
-
end
|
data/plugins/dailymotion.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
|
2
|
-
class Dailymotion < PluginBase
|
3
|
-
|
4
|
-
#the video quality is choosen based on the following priority list:
|
5
|
-
QUALITY_PRIORITY = %w[hd1080 hd720 hq sd ld]
|
6
|
-
|
7
|
-
# this will be called by the main app to check whether this plugin is responsible for the url passed
|
8
|
-
def self.matches_provider?(url)
|
9
|
-
url.include?("dailymotion.com")
|
10
|
-
end
|
11
|
-
|
12
|
-
# return the url for original video file and title
|
13
|
-
def self.get_urls_and_filenames(url, options = {})
|
14
|
-
doc = Nokogiri::HTML(open(url))
|
15
|
-
|
16
|
-
#check to see that the video is hosted on dailymotion.com - if not raise exception
|
17
|
-
unless doc.xpath("//div[@class='dmco_html dmpi_video_partnerplayer']").empty?
|
18
|
-
raise CouldNotDownloadVideoError,
|
19
|
-
"This video is not hosted on dailymotion's own content servers. It can't be downloaded."
|
20
|
-
end
|
21
|
-
|
22
|
-
title = doc.xpath("//meta[@property='og:title']").attribute("content").value
|
23
|
-
urls = get_download_urls(doc)
|
24
|
-
quality = QUALITY_PRIORITY.find { |q| urls[q] } #quality is the first quality from the priority list that exists for the video
|
25
|
-
down_url = urls[quality]
|
26
|
-
extension = down_url[/(\.[\w\d]+)\?/, 1]
|
27
|
-
file_name = PluginBase.make_filename_safe(title) + extension
|
28
|
-
|
29
|
-
[{:url => unescape_url(down_url), :name => file_name}]
|
30
|
-
end
|
31
|
-
|
32
|
-
#returns a hash with the different video qualities mapped to their respective download urls
|
33
|
-
def self.get_download_urls(doc)
|
34
|
-
flashvars = doc.xpath("//div[@class='dmco_html player_box']/script").text #the flash player script
|
35
|
-
decoded = CGI::unescape(flashvars)
|
36
|
-
url_array = decoded.scan(/(ld|sd|hq|hd720|hd1080)URL":"(.+?)"/).flatten #group 1 = the quality, group 2 = the url
|
37
|
-
Hash[*url_array] #hash like this: {"quality" => "url"}
|
38
|
-
end
|
39
|
-
|
40
|
-
#remove backslashes
|
41
|
-
def self.unescape_url(url)
|
42
|
-
url.gsub("\\", "")
|
43
|
-
end
|
44
|
-
end
|