acts_as_unvlogable_fork 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/.travis.yml +16 -0
- data/Gemfile +14 -0
- data/MIT-LICENSE +20 -0
- data/README.markdown +130 -0
- data/Rakefile +2 -0
- data/acts_as_unvlogable.gemspec +25 -0
- data/lib/acts_as_unvlogable/flickr.rb +713 -0
- data/lib/acts_as_unvlogable/object_base.rb +15 -0
- data/lib/acts_as_unvlogable/string_base.rb +24 -0
- data/lib/acts_as_unvlogable/string_extend.rb +8 -0
- data/lib/acts_as_unvlogable/version.rb +3 -0
- data/lib/acts_as_unvlogable/vg_11870.rb +48 -0
- data/lib/acts_as_unvlogable/vg_blip.rb +48 -0
- data/lib/acts_as_unvlogable/vg_collegehumor.rb +58 -0
- data/lib/acts_as_unvlogable/vg_dailymotion.rb +67 -0
- data/lib/acts_as_unvlogable/vg_dalealplay.rb +50 -0
- data/lib/acts_as_unvlogable/vg_flickr.rb +70 -0
- data/lib/acts_as_unvlogable/vg_marca.rb +48 -0
- data/lib/acts_as_unvlogable/vg_metacafe.rb +77 -0
- data/lib/acts_as_unvlogable/vg_myspace.rb +48 -0
- data/lib/acts_as_unvlogable/vg_prostopleer.rb +46 -0
- data/lib/acts_as_unvlogable/vg_qik.rb +64 -0
- data/lib/acts_as_unvlogable/vg_rutube.rb +80 -0
- data/lib/acts_as_unvlogable/vg_ted.rb +51 -0
- data/lib/acts_as_unvlogable/vg_vimeo.rb +89 -0
- data/lib/acts_as_unvlogable/vg_youtu.rb +11 -0
- data/lib/acts_as_unvlogable/vg_youtube.rb +67 -0
- data/lib/acts_as_unvlogable.rb +117 -0
- data/test/acts_as_unvlogable_test.rb +392 -0
- data/test/video_factory_test.rb +66 -0
- data/unvlogable_sample.yml +5 -0
- metadata +137 -0
@@ -0,0 +1,80 @@
|
|
1
|
+
class VgRutube
|
2
|
+
|
3
|
+
def initialize(url=nil, options={})
|
4
|
+
@url = url
|
5
|
+
parse_url(url)
|
6
|
+
end
|
7
|
+
|
8
|
+
def title
|
9
|
+
rt_info["movie"][0]["title"][0].strip
|
10
|
+
end
|
11
|
+
|
12
|
+
# this method of extraction is somewhat fragile to changes in RuTube urls
|
13
|
+
# more correct way would be using rt_info structure, like it was done in title()
|
14
|
+
def thumbnail
|
15
|
+
# size=1 gives bigger thumbnail.
|
16
|
+
# I'm not sure how to add size parameter in compatible way
|
17
|
+
size = 2
|
18
|
+
"http://img.rutube.ru/thumbs/#{movie_hash[0,2]}/#{movie_hash[2,2]}/#{movie_hash}-#{size}.jpg"
|
19
|
+
end
|
20
|
+
|
21
|
+
def embed_url
|
22
|
+
# path to swf
|
23
|
+
"http://video.rutube.ru/#{movie_hash}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def embed_html(width=425, height=344, options={}, params={})
|
27
|
+
# overridden cause we have to change default size if needed
|
28
|
+
return <<-"END"
|
29
|
+
<object width="#{width}" height="#{height}"><param
|
30
|
+
name="movie" value="#{embed_url}"></param><param
|
31
|
+
name="wmode" value="window"></param><param
|
32
|
+
name="allowFullScreen" value="true"></param><embed
|
33
|
+
src="#{embed_url}" type="application/x-shockwave-flash"
|
34
|
+
wmode="window" width="#{width}" height="#{height}"
|
35
|
+
allowFullScreen="true"></embed>
|
36
|
+
</object>
|
37
|
+
END
|
38
|
+
end
|
39
|
+
|
40
|
+
def flv
|
41
|
+
# Fragile, untested, issues one redirect to actual location
|
42
|
+
# can't be extracted from rt_info
|
43
|
+
"http://bl.rutube.ru/#{movie_hash}.iflv"
|
44
|
+
end
|
45
|
+
|
46
|
+
def download_url
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
|
50
|
+
def duration
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
|
54
|
+
def service
|
55
|
+
"Rutube"
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
attr_accessor :movie_id
|
61
|
+
RT_XML_API = "http://rutube.ru/cgi-bin/xmlapi.cgi"
|
62
|
+
|
63
|
+
def movie_hash
|
64
|
+
@movie_hash ||= rt_info["movie"][0]["playerLink"][0].match( %r{[a-f0-9]+$} )[0]
|
65
|
+
end
|
66
|
+
|
67
|
+
def rt_info
|
68
|
+
url = RT_XML_API + "?rt_movie_id=#{movie_id}&rt_mode=movie"
|
69
|
+
@rt_info ||= XmlSimple.xml_in( Net::HTTP.get_response( URI.parse(url) ).body )
|
70
|
+
end
|
71
|
+
|
72
|
+
def parse_url(url)
|
73
|
+
uri = URI.parse(url)
|
74
|
+
@movie_id = uri.path.match(/\d+/)[0]
|
75
|
+
# this doesn't work reliably:
|
76
|
+
# @movie_hash = uri.query.match(/(^|&)v=([^&]+)/)[2]
|
77
|
+
# we'll cut it from rt_info instead
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# ----------------------------------------------
|
2
|
+
# Class for Ted Talks (www.ted.com/talks)
|
3
|
+
# http://www.ted.com/talks/benjamin_wallace_on_the_price_of_happiness.html
|
4
|
+
# ----------------------------------------------
|
5
|
+
|
6
|
+
|
7
|
+
class VgTed
|
8
|
+
|
9
|
+
def initialize(url=nil, options={})
|
10
|
+
@url = url
|
11
|
+
raise unless URI::parse(url).path.split("/").include? "talks"
|
12
|
+
@page = Hpricot(open(url))
|
13
|
+
id = @page.to_s.split("ted id=")[1].split("\]")[0]
|
14
|
+
@emb = Hpricot(open("http://www.ted.com/talks/embed/id/#{id}"))
|
15
|
+
@flashvars = CGI::unescapeHTML(@emb.to_s).split("param name=\"flashvars\" value=\"")[1].split("\"")[0]
|
16
|
+
@args = CGI::parse(@flashvars)
|
17
|
+
end
|
18
|
+
|
19
|
+
def title
|
20
|
+
@page.search("//h1/span").first.inner_html.strip
|
21
|
+
end
|
22
|
+
|
23
|
+
def thumbnail
|
24
|
+
"#{@args['su']}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def duration
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def embed_url
|
32
|
+
"http://video.ted.com/assets/player/swf/EmbedPlayer.swf?#{@flashvars}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def embed_html(width=425, height=344, options={}, params={})
|
36
|
+
"<object width='#{width}' height='#{height}'><param name='movie' value='#{embed_url}'></param><param name='allowFullScreen' value='true' /><param name='wmode' value='transparent'></param><param name='bgColor' value='#ffffff'></param><embed src='#{embed_url}' pluginspace='http://www.macromedia.com/go/getflashplayer' type='application/x-shockwave-flash' wmode='transparent' bgColor='#ffffff' width='#{width}' height='#{height}' allowFullScreen='true'></embed></object>"
|
37
|
+
end
|
38
|
+
|
39
|
+
def flv
|
40
|
+
"#{@args['vu'].to_s}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def download_url
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
|
47
|
+
def service
|
48
|
+
"Ted Talks"
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# ----------------------------------------------
|
2
|
+
# Class for Vimeo (vimeo.com)
|
3
|
+
# http://vimeo.com/5362441
|
4
|
+
# ----------------------------------------------
|
5
|
+
|
6
|
+
|
7
|
+
class VgVimeo
|
8
|
+
|
9
|
+
def initialize(url=nil, options={})
|
10
|
+
# general settings
|
11
|
+
@url = url
|
12
|
+
@video_id = parse_url(url)
|
13
|
+
|
14
|
+
if !(@vimeo_id =~ /^[0-9]+$/)
|
15
|
+
r = Net::HTTP.get_response(URI.parse(url))
|
16
|
+
|
17
|
+
if r.code == "301"
|
18
|
+
@url = "http://vimeo.com#{r.header['location']}"
|
19
|
+
@video_id = parse_url(@url)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
res = Net::HTTP.get(URI.parse("http://vimeo.com/api/v2/video/#{@video_id}.xml"))
|
24
|
+
@feed = REXML::Document.new(res)
|
25
|
+
end
|
26
|
+
|
27
|
+
def video_id
|
28
|
+
@video_id
|
29
|
+
end
|
30
|
+
|
31
|
+
def title
|
32
|
+
REXML::XPath.first( @feed, "//title" )[0].to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
def thumbnail
|
36
|
+
REXML::XPath.first( @feed, "//thumbnail_medium" )[0].to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
def duration
|
40
|
+
REXML::XPath.first( @feed, "//duration" )[0].to_s.to_i
|
41
|
+
end
|
42
|
+
|
43
|
+
def embed_url
|
44
|
+
"http://vimeo.com/moogaloop.swf?clip_id=#{@video_id}&force_embed=1&server=vimeo.com&show_title=1&show_byline=0&show_portrait=1&color=ffffff&fullscreen=1&autoplay=0&loop=0"
|
45
|
+
end
|
46
|
+
|
47
|
+
def embed_html(width=425, height=344, options={}, params={})
|
48
|
+
"<object width='#{width}' height='#{height}'><param name='movie' value='#{embed_url}'></param><param name='allowFullScreen' value='true'></param><param name='allowscriptaccess' value='always'></param><embed src='#{embed_url}' type='application/x-shockwave-flash' allowscriptaccess='always' allowfullscreen='true' width='#{width}' height='#{height}'></embed></object>"
|
49
|
+
end
|
50
|
+
|
51
|
+
def flv
|
52
|
+
res = Net::HTTP.get(URI.parse("http://vimeo.com/42966264?action=download"))
|
53
|
+
request_signature = res.split("\"signature\":\"")[1].split("\"")[0]
|
54
|
+
request_cached_timestamp = res.split("\"cached_timestamp\":")[1].split(",")[0]
|
55
|
+
"http://player.vimeo.com/play_redirect?clip_id=#{@video_id}&sig=#{request_signature}&time=#{request_cached_timestamp}&quality=sd&codecs=H264,VP8,VP6&type=moogaloop&embed_location="
|
56
|
+
end
|
57
|
+
|
58
|
+
def download_url
|
59
|
+
request_signature = REXML::XPath.first( @feed, "//request_signature" )[0]
|
60
|
+
request_signature_expires = REXML::XPath.first( @feed, "//request_signature_expires" )[0]
|
61
|
+
"http://www.vimeo.com/moogaloop/play/clip:#{@video_id}/#{request_signature}/#{request_signature_expires}/?q=hd"
|
62
|
+
end
|
63
|
+
|
64
|
+
def service
|
65
|
+
"Vimeo"
|
66
|
+
end
|
67
|
+
|
68
|
+
protected
|
69
|
+
|
70
|
+
# formats: http://vimeo.com/<video_id> or http://vimeo.com/channels/hd#<video_id>
|
71
|
+
def parse_url(url)
|
72
|
+
uri = URI.parse(url)
|
73
|
+
path = uri.path
|
74
|
+
videoargs = ''
|
75
|
+
|
76
|
+
return uri.fragment if uri.fragment
|
77
|
+
|
78
|
+
if uri.path and path.split("/").size > 0
|
79
|
+
videoargs = path.split("/")
|
80
|
+
raise unless videoargs.size > 0
|
81
|
+
else
|
82
|
+
raise
|
83
|
+
end
|
84
|
+
videoargs[1]
|
85
|
+
rescue
|
86
|
+
nil
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require "acts_as_unvlogable/vg_youtube"
|
2
|
+
|
3
|
+
class VgYoutu < VgYoutube
|
4
|
+
def initialize(url=nil, options={})
|
5
|
+
url = URI(url)
|
6
|
+
url.host = 'www.youtube.com'
|
7
|
+
url.query = "#{url.query}&v=#{url.path[1..-1]}"
|
8
|
+
url.path = '/watch'
|
9
|
+
super(url.to_s, options)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# ----------------------------------------------
|
2
|
+
# Class for Youtube (youtube.com)
|
3
|
+
# http://www.youtube.com/watch?v=25AsfkriHQc
|
4
|
+
# ----------------------------------------------
|
5
|
+
|
6
|
+
class VgYoutube
|
7
|
+
|
8
|
+
def initialize(url=nil, options={})
|
9
|
+
object = YouTubeIt::Client.new({})
|
10
|
+
@url = url
|
11
|
+
@video_id = @url.query_param('v')
|
12
|
+
begin
|
13
|
+
@details = object.video_by(@video_id)
|
14
|
+
raise if @details.blank?
|
15
|
+
raise ArgumentError, "Embedding disabled by request" unless @details.embeddable?
|
16
|
+
@details.instance_variable_set(:@noembed, false)
|
17
|
+
rescue
|
18
|
+
raise ArgumentError, "Unsuported url or service"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def title
|
23
|
+
@details.title
|
24
|
+
end
|
25
|
+
|
26
|
+
def thumbnail
|
27
|
+
@details.thumbnails.first.url
|
28
|
+
end
|
29
|
+
|
30
|
+
def duration
|
31
|
+
@details.duration
|
32
|
+
end
|
33
|
+
|
34
|
+
def embed_url
|
35
|
+
@details.media_content.first.url if @details.noembed == false
|
36
|
+
end
|
37
|
+
|
38
|
+
# options
|
39
|
+
# You can read more about the youtube player options in
|
40
|
+
# http://code.google.com/intl/en/apis/youtube/player_parameters.html
|
41
|
+
# Use them in options (ex {:rel => 0, :color1 => '0x333333'})
|
42
|
+
#
|
43
|
+
def embed_html(width=425, height=344, options={}, params={})
|
44
|
+
"<object width='#{width}' height='#{height}'><param name='movie' value='#{embed_url}#{options.map {|k,v| "&#{k}=#{v}"}}'></param><param name='allowFullScreen' value='true'></param><param name='allowscriptaccess' value='always'></param>#{params.map{|k,v|"<param name='#{k}' value='#{v}'></param>"}.join}<embed src='#{embed_url}#{options.map {|k,v| "&#{k}=#{v}"}}' type='application/x-shockwave-flash' allowscriptaccess='always' allowfullscreen='true' width='#{width}' height='#{height}' #{params.map {|k,v| "#{k}=#{v}"}.join(" ")}></embed></object>" if @details.noembed == false
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def flv
|
49
|
+
doc = URI::parse("http://www.youtube.com/get_video_info?&video_id=#{@video_id}").read
|
50
|
+
CGI::unescape(doc.split("&url_encoded_fmt_stream_map=")[1]).split("url=").each do |u|
|
51
|
+
u = CGI::unescape(u)
|
52
|
+
unless u.index("x-flv").nil?
|
53
|
+
return u.split("&quality").first
|
54
|
+
break
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def download_url
|
60
|
+
flv
|
61
|
+
end
|
62
|
+
|
63
|
+
def service
|
64
|
+
"Youtube"
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler/setup"
|
3
|
+
|
4
|
+
require "xmlsimple"
|
5
|
+
require "youtube_it"
|
6
|
+
require "hpricot"
|
7
|
+
require "net/http"
|
8
|
+
require "json"
|
9
|
+
|
10
|
+
require "acts_as_unvlogable/flickr"
|
11
|
+
# Extensions
|
12
|
+
if defined?(ActiveSupport).nil?
|
13
|
+
require "acts_as_unvlogable/string_base"
|
14
|
+
require "acts_as_unvlogable/object_base"
|
15
|
+
end
|
16
|
+
require "acts_as_unvlogable/string_extend"
|
17
|
+
|
18
|
+
# Video classes
|
19
|
+
videolibs = File.join(File.dirname(__FILE__), "acts_as_unvlogable", "vg_*.rb")
|
20
|
+
Dir.glob(videolibs).each {|file| require file}
|
21
|
+
|
22
|
+
class UnvlogIt
|
23
|
+
|
24
|
+
def initialize(url=nil, options={})
|
25
|
+
@object = VideoFactory.new(url, options).load_service
|
26
|
+
end
|
27
|
+
|
28
|
+
def title
|
29
|
+
@object.title #rescue nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def thumbnail
|
33
|
+
@object.thumbnail rescue nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def duration # duration is in seconds
|
37
|
+
@object.duration rescue nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def embed_url
|
41
|
+
@object.embed_url rescue nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def video_id
|
45
|
+
@object.video_id rescue nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def embed_html(width=425, height=344, options={}, params={})
|
49
|
+
@object.embed_html(width, height, options, params) rescue nil
|
50
|
+
end
|
51
|
+
|
52
|
+
def flv
|
53
|
+
@object.flv #rescue nil
|
54
|
+
end
|
55
|
+
|
56
|
+
def download_url
|
57
|
+
@object.download_url rescue nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def service
|
61
|
+
@object.service rescue nil
|
62
|
+
end
|
63
|
+
|
64
|
+
def video_details(width=425, height=344)
|
65
|
+
{
|
66
|
+
:title => @object.title,
|
67
|
+
:thumbnail => @object.thumbnail,
|
68
|
+
:embed_url => @object.embed_url,
|
69
|
+
:embed_html => @object.embed_html(width, height),
|
70
|
+
:flv => @object.flv,
|
71
|
+
:download_url => @object.download_url,
|
72
|
+
:service => @object.service,
|
73
|
+
:duration => @object.duration
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
class VideoFactory
|
78
|
+
def initialize(url, options = {})
|
79
|
+
raise ArgumentError.new("We need a video url") if url.blank?
|
80
|
+
@url = url
|
81
|
+
@options = options
|
82
|
+
end
|
83
|
+
|
84
|
+
def load_service
|
85
|
+
@object = service_object
|
86
|
+
|
87
|
+
validate_embed(@object)
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def validate_embed(object)
|
93
|
+
unless object.instance_variable_get("@details").nil? || !object.instance_variable_get("@details").respond_to?("noembed")
|
94
|
+
if object.instance_variable_get("@details").noembed
|
95
|
+
raise ArgumentError.new("Embedding disabled by request")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
object
|
99
|
+
end
|
100
|
+
|
101
|
+
def service_object
|
102
|
+
class_name = "vg_#{get_domain.downcase}".camelize
|
103
|
+
class_name.constantize.new(@url, @options)
|
104
|
+
rescue NameError
|
105
|
+
raise ArgumentError.new("Unsuported url or service. class: #{class_name}, url: #{@url}")
|
106
|
+
end
|
107
|
+
|
108
|
+
def get_domain
|
109
|
+
host = URI::parse(@url).host.split(".")
|
110
|
+
unless host.size == 1
|
111
|
+
host[host.size-2]
|
112
|
+
else
|
113
|
+
host[0]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|