video_info 1.5.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +24 -0
  3. data/.travis.yml +10 -0
  4. data/Gemfile +11 -0
  5. data/Guardfile +8 -0
  6. data/{LICENSE → LICENSE.txt} +2 -0
  7. data/README.md +42 -43
  8. data/Rakefile +5 -0
  9. data/lib/video_info/provider.rb +36 -26
  10. data/lib/video_info/providers/vimeo.rb +45 -27
  11. data/lib/video_info/providers/vkontakte.rb +114 -0
  12. data/lib/video_info/providers/youtube.rb +62 -23
  13. data/lib/video_info/version.rb +1 -1
  14. data/lib/video_info.rb +1 -1
  15. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029/date/.yml +69 -0
  16. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029/description/.yml +69 -0
  17. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029/duration/.yml +69 -0
  18. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029/embed_code/.yml +69 -0
  19. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029/embed_url/.yml +69 -0
  20. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029/height/.yml +69 -0
  21. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029/keywords/.yml +69 -0
  22. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029/provider/.yml +69 -0
  23. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029/thumbnail_large/.yml +69 -0
  24. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029/thumbnail_medium/.yml +69 -0
  25. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029/thumbnail_small/.yml +69 -0
  26. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029/title/.yml +69 -0
  27. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029/url/.yml +69 -0
  28. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029/video_id/.yml +69 -0
  29. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029/view_count/.yml +69 -0
  30. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029/width/.yml +69 -0
  31. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029_and_iframe_attributes/.yml +69 -0
  32. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029_and_url_attributes/.yml +69 -0
  33. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029_in_/group/_url/provider/.yml +69 -0
  34. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029_in_/group/_url/video_id/.yml +69 -0
  35. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029_in_text/provider/.yml +69 -0
  36. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vimeo/with_video_898029_in_text/video_id/.yml +69 -0
  37. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vkontakte/with_video_39576223_108370515/date/.yml +1410 -0
  38. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vkontakte/with_video_39576223_108370515/description/.yml +1410 -0
  39. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vkontakte/with_video_39576223_108370515/duration/.yml +1410 -0
  40. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vkontakte/with_video_39576223_108370515/embed_code/.yml +1410 -0
  41. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vkontakte/with_video_39576223_108370515/embed_url/.yml +1410 -0
  42. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vkontakte/with_video_39576223_108370515/height/.yml +1410 -0
  43. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vkontakte/with_video_39576223_108370515/provider/.yml +1410 -0
  44. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vkontakte/with_video_39576223_108370515/title/.yml +1410 -0
  45. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vkontakte/with_video_39576223_108370515/url/.yml +1410 -0
  46. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vkontakte/with_video_39576223_108370515/video_id/.yml +1410 -0
  47. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vkontakte/with_video_39576223_108370515/video_owner/.yml +1369 -0
  48. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vkontakte/with_video_39576223_108370515/view_count/.yml +1410 -0
  49. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Vkontakte/with_video_39576223_108370515/width/.yml +1410 -0
  50. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_arbitrary_iframe_attributes/.yml +62 -0
  51. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_arbitrary_iframe_attributes/provider/.yml +62 -0
  52. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_iframe_attributes/.yml +62 -0
  53. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_iframe_attributes/provider/.yml +62 -0
  54. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_JM9NgvjjVng_in_youtu_be_url/provider/.yml +65 -0
  55. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_JM9NgvjjVng_in_youtu_be_url/video_id/.yml +65 -0
  56. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_VeasFckfMHY_after_params/provider/.yml +66 -0
  57. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_VeasFckfMHY_after_params/url/.yml +66 -0
  58. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_VeasFckfMHY_after_params/video_id/.yml +66 -0
  59. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_VeasFckfMHY_in_e_path/provider/.yml +66 -0
  60. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_VeasFckfMHY_in_e_path/video_id/.yml +66 -0
  61. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_VeasFckfMHY_in_embed_path/provider/.yml +66 -0
  62. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_VeasFckfMHY_in_embed_path/video_id/.yml +66 -0
  63. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_VeasFckfMHY_in_path/provider/.yml +66 -0
  64. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_VeasFckfMHY_in_path/video_id/.yml +66 -0
  65. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_VeasFckfMHY_in_user_url/provider/.yml +66 -0
  66. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_VeasFckfMHY_in_user_url/url/.yml +66 -0
  67. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_VeasFckfMHY_in_user_url/video_id/.yml +66 -0
  68. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_Xp6CXF-Cesg/provider/.yml +62 -0
  69. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_Xp6CXF-Cesg/video_id/.yml +62 -0
  70. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_mZqGqE0D0n4/date/.yml +62 -0
  71. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_mZqGqE0D0n4/description/.yml +62 -0
  72. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_mZqGqE0D0n4/duration/.yml +62 -0
  73. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_mZqGqE0D0n4/embed_code/.yml +62 -0
  74. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_mZqGqE0D0n4/embed_url/.yml +62 -0
  75. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_mZqGqE0D0n4/height/.yml +62 -0
  76. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_mZqGqE0D0n4/keywords/.yml +62 -0
  77. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_mZqGqE0D0n4/provider/.yml +62 -0
  78. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_mZqGqE0D0n4/thumbnail_large/.yml +62 -0
  79. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_mZqGqE0D0n4/thumbnail_medium/.yml +62 -0
  80. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_mZqGqE0D0n4/thumbnail_small/.yml +62 -0
  81. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_mZqGqE0D0n4/title/.yml +62 -0
  82. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_mZqGqE0D0n4/url/.yml +62 -0
  83. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_mZqGqE0D0n4/video_id/.yml +62 -0
  84. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_mZqGqE0D0n4/view_count/.yml +62 -0
  85. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_mZqGqE0D0n4/width/.yml +62 -0
  86. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_oQ49W_xKzKA/.yml +62 -0
  87. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_oQ49W_xKzKA/provider/.yml +62 -0
  88. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_oQ49W_xKzKA/video_id/.yml +62 -0
  89. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_url_in_text/provider/.yml +62 -0
  90. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/with_video_url_in_text/video_id/.yml +62 -0
  91. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/without_http_or_www/provider/.yml +65 -0
  92. data/spec/fixtures/vcr_cassettes/VideoInfo_Providers_Youtube/without_http_or_www/video_id/.yml +65 -0
  93. data/spec/lib/video_info/provider_spec.rb +44 -0
  94. data/spec/lib/video_info/providers/vimeo_spec.rb +74 -0
  95. data/spec/lib/video_info/providers/vkontakte_spec.rb +38 -0
  96. data/spec/lib/video_info/providers/youtube_spec.rb +138 -0
  97. data/spec/lib/video_info_spec.rb +50 -0
  98. data/spec/spec_helper.rb +22 -0
  99. data/video_info.gemspec +29 -0
  100. metadata +219 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2ed3d8969372248a0472f8987ee8b487af924e10
4
- data.tar.gz: 1e92e42ca47410bdcdeff660fd5df4f6f2fd295a
3
+ metadata.gz: f5bfff718ac239bdc03fcb92af2455394dd97d05
4
+ data.tar.gz: 556d2e23987b37bc175ce9603a0a367aa986fac8
5
5
  SHA512:
6
- metadata.gz: 790020a37c437e7c8868d7afeae0e9bfdb393dfe4f6c1057bde41396393cab86956476be53fb022aef3d5dc34459bac81fb52cfeaf7ca3dd7676270b6c200e3c
7
- data.tar.gz: d6635217f67d020d376fb30c8cacbc57789a2df31a79cc4cbc4c19f5c66e3629ffa0e9de0f90656c838c528f746b0d017152c9f3735f466b2cba37be614d39cf
6
+ metadata.gz: ea918f3867fe980ea5f86e415ab672ddb3e78a6a01f4ddb3ef13121c7f86e08e5ada9d243c4d9e36cdf29ca358b6fc676a544d50b44bb1b5cfa4a77a3e3874b0
7
+ data.tar.gz: ef6e684d5c501b35af781265a0ad0f7efdc2ca0e5403652895d02c9e0398c1393820205bd816cffaf83182225c1a079204662c788e072e03f8a631ef47082784
data/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+ Gemfile.lock
21
+
22
+ ## PROJECT::SPECIFIC
23
+ .bundle/config
24
+ vendor/bundle/
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+ bundler_args: --without tool
3
+ rvm:
4
+ - 1.8.7
5
+ - 1.9.3
6
+ - 2.0.0
7
+ - jruby-18mode
8
+ - jruby-19mode
9
+ - rbx-18mode
10
+ - rbx-19mode
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in video_info.gemspec
4
+ gemspec
5
+
6
+ gem 'coveralls', :require => false
7
+
8
+ group :tool do
9
+ gem 'ruby_gntp'
10
+ gem 'guard-rspec'
11
+ end
data/Guardfile ADDED
@@ -0,0 +1,8 @@
1
+ # A sample Guardfile
2
+ # More info at http://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', keep_failed: false do
5
+ watch('spec/spec_helper.rb') { "spec" }
6
+ watch(%r{lib/(.+)\.rb}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch(%r{spec/.+_spec\.rb})
8
+ end
@@ -1,5 +1,7 @@
1
1
  Copyright (c) 2013 Thibaud Guillaume-Gentil
2
2
 
3
+ MIT License
4
+
3
5
  Permission is hereby granted, free of charge, to any person obtaining
4
6
  a copy of this software and associated documentation files (the
5
7
  "Software"), to deal in the Software without restriction, including
data/README.md CHANGED
@@ -1,65 +1,66 @@
1
- # VideoInfo [![Gem Version](https://badge.fury.io/rb/video_info.png)](http://badge.fury.io/rb/video_info) [![Build Status](https://secure.travis-ci.org/thibaudgg/video_info.png?branch=master)](http://travis-ci.org/thibaudgg/video_info) [![Dependency Status](https://gemnasium.com/thibaudgg/video_info.png)](https://gemnasium.com/thibaudgg/video_info) [![Code Climate](https://codeclimate.com/github/thibaudgg/video_info.png)](https://codeclimate.com/github/thibaudgg/video_info) [![Coverage Status](https://coveralls.io/repos/thibaudgg/video_info/badge.png?branch=master)](https://coveralls.io/r/thibaudgg/video_info)
1
+ # VideoInfo
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/video_info.png)](http://badge.fury.io/rb/video_info) [![Build Status](https://travis-ci.org/thibaudgg/video_info.png?branch=master)](https://travis-ci.org/thibaudgg/video_info) [![Dependency Status](https://gemnasium.com/thibaudgg/video_info.png)](https://gemnasium.com/thibaudgg/video_info) [![Code Climate](https://codeclimate.com/github/thibaudgg/video_info.png)](https://codeclimate.com/github/thibaudgg/video_info) [![Coverage Status](https://coveralls.io/repos/thibaudgg/video_info/badge.png?branch=master)](https://coveralls.io/r/thibaudgg/video_info)
4
+
5
+ Simple Ruby Gem to get video info from YouTube and Vimeo url.
2
6
 
3
- Simple Ruby Gem to get video info from youtube and vimeo url.
4
7
  Tested against Ruby 1.8.7, 1.9.3, 2.0.0 and the latest versions of JRuby & Rubinius.
5
8
 
6
9
  Install
7
10
  --------
8
11
 
9
12
  ``` bash
10
- gem install video_info
13
+ gem install video_info
11
14
  ```
12
15
 
13
16
  Usage
14
17
  -----
15
18
 
16
19
  ``` ruby
17
- video = VideoInfo.get("http://www.youtube.com/watch?v=mZqGqE0D0n4")
18
-
19
- # video.video_id => "mZqGqE0D0n4"
20
- # video.provider => "YouTube"
21
- # video.title => "Cherry Bloom - King Of The Knife"
22
- # video.description => "The first video from the upcoming album Secret Sounds, to download in-stores April 14. Checkout http://www.cherrybloom.net"
23
- # video.duration => 175 (in seconds)
24
- # video.date => Sat Apr 12 22:25:35 UTC 2008
25
- # video.thumbnail_small => "http://i.ytimg.com/vi/mZqGqE0D0n4/default.jpg"
26
- # video.thumbnail_medium => "http://i.ytimg.com/vi/mZqGqE0D0n4/mqdefault.jpg"
27
- # video.thumbnail_large => "http://i.ytimg.com/vi/mZqGqE0D0n4/hqdefault.jpg"
28
- # video.embed_url => "http://www.youtube.com/embed/mZqGqE0D0n4"
29
- # video.embed_code => "'<iframe src="http://www.youtube.com/embed/mZqGqE0D0n4" frameborder="0" allowfullscreen="allowfullscreen"></iframe>'"
30
-
31
- video = VideoInfo.get("http://vimeo.com/898029")
32
-
33
- # video.video_id => "898029"
34
- # video.provider => "Vimeo"
35
- # video.title => "Cherry Bloom - King Of The Knife"
36
- # video.description => "The first video from the upcoming album Secret Sounds, to download in-stores April 14. Checkout http://www.cherrybloom.net"
37
- # video.keywords => "alternative, bloom, cherry, clip, drum, guitar, king, knife, of, Paris-Forum, rock, the, tremplin"
38
- # video.duration => 175 (in seconds)
39
- # video.date => Mon Apr 14 13:10:39 +0200 2008
40
- # video.width => 640
41
- # video.height => 360
42
- # video.thumbnail_small => "http://b.vimeocdn.com/ts/343/731/34373130_100.jpg"
43
- # video.thumbnail_medium => "http://b.vimeocdn.com/ts/343/731/34373130_200.jpg"
44
- # video.thumbnail_large => "http://b.vimeocdn.com/ts/343/731/34373130_640.jpg"
45
- # video.embed_url => "http://player.vimeo.com/video/898029"
46
- # video.embed_code => "'<iframe src="http://player.vimeo.com/video/898029?title=0&amp;byline=0&amp;portrait=0&amp;autoplay=0" frameborder="0"></iframe>'"
20
+ video = VideoInfo.get("http://www.youtube.com/watch?v=mZqGqE0D0n4")
21
+ # video.video_id => "mZqGqE0D0n4"
22
+ # video.provider => "YouTube"
23
+ # video.title => "Cherry Bloom - King Of The Knife"
24
+ # video.description => "The first video from the upcoming album Secret Sounds, to download in-stores April 14. Checkout http://www.cherrybloom.net"
25
+ # video.duration => 175 (in seconds)
26
+ # video.date => Sat Apr 12 22:25:35 UTC 2008
27
+ # video.thumbnail_small => "http://i.ytimg.com/vi/mZqGqE0D0n4/default.jpg"
28
+ # video.thumbnail_medium => "http://i.ytimg.com/vi/mZqGqE0D0n4/mqdefault.jpg"
29
+ # video.thumbnail_large => "http://i.ytimg.com/vi/mZqGqE0D0n4/hqdefault.jpg"
30
+ # video.embed_url => "http://www.youtube.com/embed/mZqGqE0D0n4"
31
+ # video.embed_code => "'<iframe src="http://www.youtube.com/embed/mZqGqE0D0n4" frameborder="0" allowfullscreen="allowfullscreen"></iframe>'"
32
+
33
+ video = VideoInfo.get("http://vimeo.com/898029")
34
+ # video.video_id => "898029"
35
+ # video.provider => "Vimeo"
36
+ # video.title => "Cherry Bloom - King Of The Knife"
37
+ # video.description => "The first video from the upcoming album Secret Sounds, to download in-stores April 14. Checkout http://www.cherrybloom.net"
38
+ # video.keywords => "alternative, bloom, cherry, clip, drum, guitar, king, knife, of, Paris-Forum, rock, the, tremplin"
39
+ # video.duration => 175 (in seconds)
40
+ # video.date => Mon Apr 14 13:10:39 +0200 2008
41
+ # video.width => 640
42
+ # video.height => 360
43
+ # video.thumbnail_small => "http://b.vimeocdn.com/ts/343/731/34373130_100.jpg"
44
+ # video.thumbnail_medium => "http://b.vimeocdn.com/ts/343/731/34373130_200.jpg"
45
+ # video.thumbnail_large => "http://b.vimeocdn.com/ts/343/731/34373130_640.jpg"
46
+ # video.embed_url => "http://player.vimeo.com/video/898029"
47
+ # video.embed_code => "'<iframe src="http://player.vimeo.com/video/898029?title=0&amp;byline=0&amp;portrait=0&amp;autoplay=0" frameborder="0"></iframe>'"
47
48
  ```
48
49
 
49
50
  Options
50
51
  -------
51
52
 
52
53
  ``` ruby
53
- video = VideoInfo.get("http://www.youtube.com/watch?v=mZqGqE0D0n4", "User-Agent" => "My Youtube Mashup Robot/1.0")
54
- video = VideoInfo.get("http://www.youtube.com/watch?v=mZqGqE0D0n4", "Referer" => "http://my-youtube-mashup.com/")
55
- video = VideoInfo.get("http://www.youtube.com/watch?v=mZqGqE0D0n4", "Referer" => "http://my-youtube-mashup.com/",
56
- "User-Agent" => "My Youtube Mashup Robot/1.0")
54
+ video = VideoInfo.get("http://www.youtube.com/watch?v=mZqGqE0D0n4", "User-Agent" => "My YouTube Mashup Robot/1.0")
55
+ video = VideoInfo.get("http://www.youtube.com/watch?v=mZqGqE0D0n4", "Referer" => "http://my-youtube-mashup.com/")
56
+ video = VideoInfo.get("http://www.youtube.com/watch?v=mZqGqE0D0n4", "Referer" => "http://my-youtube-mashup.com/",
57
+ "User-Agent" => "My YouTube Mashup Robot/1.0")
57
58
  ```
58
59
  You can also use **symbols** instead of strings (any non-word (`/[^a-z]/i`) character would be converted to hyphen).
59
60
 
60
61
  ``` ruby
61
- video = VideoInfo.get("http://www.youtube.com/watch?v=mZqGqE0D0n4", :referer => "http://my-youtube-mashup.com/",
62
- :user_agent => "My Youtube Mashup Robot/1.0")
62
+ video = VideoInfo.get("http://www.youtube.com/watch?v=mZqGqE0D0n4", :referer => "http://my-youtube-mashup.com/",
63
+ :user_agent => "My YouTube Mashup Robot/1.0")
63
64
  ```
64
65
 
65
66
  User-Agent when empty defaults to "VideoInfo/VERSION" - where version is current VideoInfo version, e.g. **"VideoInfo/0.2.7"**.
@@ -76,15 +77,13 @@ VideoInfo.get("http://www.youtube.com/watch?v=mZqGqE0D0n4").embed_code(:iframe_a
76
77
  => '<iframe src="http://www.youtube.com/embed/mZqGqE0D0n4?autoplay=1" frameborder="0" allowfullscreen="allowfullscreen"></iframe>'
77
78
  ```
78
79
 
79
-
80
-
81
80
  Author
82
81
  ------
83
82
 
84
- [Thibaud Guillaume-Gentil](https://github.com/thibaudgg) ([@thibaudgg](http://twitter.com/thibaudgg))
83
+ [Thibaud Guillaume-Gentil](https://github.com/thibaudgg) ([@thibaudgg](https://twitter.com/thibaudgg))
85
84
 
86
85
  Contributors
87
86
  ------------
88
87
 
89
- [https://github.com/thibaudgg/video_info/contributors](https://github.com/thibaudgg/video_info/contributors)
88
+ [https://github.com/thibaudgg/video_info/graphs/contributors](https://github.com/thibaudgg/video_info/graphs/contributors)
90
89
 
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new(:spec)
5
+ task :default => :spec
@@ -2,12 +2,7 @@ require "addressable/uri"
2
2
 
3
3
  module VideoInfo
4
4
  class Provider
5
-
6
- attr_accessor :url, :options, :iframe_attributes, :video_id
7
- attr_accessor :embed_url, :provider, :title, :description, :keywords,
8
- :duration, :date, :width, :height,
9
- :thumbnail_small, :thumbnail_medium, :thumbnail_large,
10
- :view_count
5
+ attr_accessor :url, :options, :iframe_attributes, :video_id, :video
11
6
 
12
7
  def initialize(url, options = {})
13
8
  @options = _clean_options(options)
@@ -21,22 +16,39 @@ module VideoInfo
21
16
  end
22
17
 
23
18
  def embed_code(options = {})
24
- url_attributes = options.fetch(:url_attributes, {})
25
- url_attrs = default_url_attributes.merge(url_attributes)
26
-
27
- url = embed_url
28
- url += "?#{_hash_to_params(url_attrs)}" unless url_attrs.empty?
29
-
30
- iframe_attrs = ["src=\"#{url}\"", "frameborder=\"0\""]
31
-
32
19
  iframe_attributes = options.fetch(:iframe_attributes, {})
33
- iframe_attrs << _hash_to_attributes(default_iframe_attributes.merge(iframe_attributes))
20
+ iframe_attrs = ["src=\"#{_embed_url(options)}\"", "frameborder=\"0\""]
21
+ iframe_attrs << _hash_to_attributes(_default_iframe_attributes.merge(iframe_attributes))
34
22
 
35
23
  "<iframe #{iframe_attrs.reject(&:empty?).join(" ")}></iframe>"
36
24
  end
37
25
 
38
26
  private
39
27
 
28
+ def _clean_options(options)
29
+ options = { 'User-Agent' => "VideoInfo/#{VideoInfo::VERSION}" }.merge(options)
30
+ options.dup.each do |key, value|
31
+ if _not_openuri_option_symbol?(key)
32
+ options[_http_header_field(key)] = value
33
+ options.delete key
34
+ end
35
+ end
36
+ options
37
+ end
38
+
39
+ def _set_info_from_api
40
+ uri = open(_api_url, options)
41
+ @video = MultiJson.load(uri.read)
42
+ end
43
+
44
+ def _not_openuri_option_symbol?(key)
45
+ key.is_a?(Symbol) && !OpenURI::Options.keys.include?(key)
46
+ end
47
+
48
+ def _http_header_field(key)
49
+ key.to_s.split(/[^a-z]/i).map(&:capitalize).join('-')
50
+ end
51
+
40
52
  def _set_video_id_from_url
41
53
  url.gsub(_url_regex) { @video_id = $1 || $2 || $3 }
42
54
  end
@@ -49,19 +61,17 @@ module VideoInfo
49
61
  raise NotImplementedError.new('Provider class must implement #_url_regex private method')
50
62
  end
51
63
 
52
- def _set_info_from_api
53
- raise NotImplementedError.new('Provider class must implement #_set_info_from_api private method')
64
+ def _api_url
65
+ raise NotImplementedError.new('Provider class must implement #_api_url private method')
54
66
  end
55
67
 
56
- def _clean_options(options)
57
- options = { 'User-Agent' => "VideoInfo/#{VideoInfo::VERSION}" }.merge(options)
58
- options.dup.each do |key, value|
59
- if key.is_a?(Symbol) && !OpenURI::Options.keys.include?(key)
60
- options[key.to_s.split(/[^a-z]/i).map(&:capitalize).join('-')] = value
61
- options.delete key
62
- end
63
- end
64
- options
68
+ def _embed_url(options)
69
+ url_attrs = options.fetch(:url_attributes, {})
70
+ url_attrs = _default_url_attributes.merge(url_attrs)
71
+
72
+ url = embed_url
73
+ url += "?#{_hash_to_params(url_attrs)}" unless url_attrs.empty?
74
+ url
65
75
  end
66
76
 
67
77
  def _hash_to_attributes(hash)
@@ -9,15 +9,40 @@ module VideoInfo
9
9
  url =~ /vimeo\.com/
10
10
  end
11
11
 
12
- def default_iframe_attributes
13
- {}
12
+ def provider
13
+ 'Vimeo'
14
14
  end
15
15
 
16
- def default_url_attributes
17
- { :title => 0,
18
- :byline => 0,
19
- :portrait => 0,
20
- :autoplay => 0 }
16
+ def url
17
+ video ? video['url'] : @url
18
+ end
19
+
20
+ %w[title description thumbnail_small thumbnail_medium thumbnail_large].each do |method|
21
+ define_method(method) { video[method] }
22
+ end
23
+
24
+ %w[duration width height].each do |method|
25
+ define_method(method) { video[method].to_i }
26
+ end
27
+
28
+ def keywords
29
+ video['tags']
30
+ end
31
+
32
+ def embed_url
33
+ "http://player.vimeo.com/video/#{video_id}"
34
+ end
35
+
36
+ def date
37
+ Time.parse(video['upload_date'], Time.now.utc).utc
38
+ end
39
+
40
+ def view_count
41
+ video['stats_number_of_plays'].to_i
42
+ end
43
+
44
+ def video
45
+ @video && @video.first
21
46
  end
22
47
 
23
48
  private
@@ -26,26 +51,19 @@ module VideoInfo
26
51
  /.*\.com\/(?:(?:groups\/[^\/]+\/videos\/)|(?:video\/))?([0-9]+).*$/i
27
52
  end
28
53
 
29
- def _set_info_from_api
30
- uri = open("http://vimeo.com/api/v2/video/#{video_id}.json", options)
31
- video = MultiJson.load(uri.read).first
32
-
33
- @provider = "Vimeo"
34
- @url = video['url']
35
- @embed_url = "http://player.vimeo.com/video/#{video_id}"
36
- @title = video['title']
37
- @description = video['description']
38
- @keywords = video['tags']
39
- @duration = video['duration'].to_i # seconds
40
- @width = video['width'].to_i
41
- @height = video['height'].to_i
42
- @date = Time.parse(video['upload_date'], Time.now.utc).utc
43
- @thumbnail_small = video['thumbnail_small']
44
- @thumbnail_medium = video['thumbnail_medium']
45
- @thumbnail_large = video['thumbnail_large']
46
- @view_count = video['stats_number_of_plays'].to_i
47
- rescue
48
- nil
54
+ def _api_url
55
+ "http://vimeo.com/api/v2/video/#{video_id}.json"
56
+ end
57
+
58
+ def _default_iframe_attributes
59
+ {}
60
+ end
61
+
62
+ def _default_url_attributes
63
+ { :title => 0,
64
+ :byline => 0,
65
+ :portrait => 0,
66
+ :autoplay => 0 }
49
67
  end
50
68
 
51
69
  end
@@ -0,0 +1,114 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'open-uri'
4
+ require 'multi_json'
5
+ require 'htmlentities'
6
+
7
+ if RUBY_VERSION.to_i < 2
8
+ require 'iconv'
9
+ end
10
+
11
+ module VideoInfo
12
+ module Providers
13
+ class Vkontakte < Provider
14
+ attr_accessor :video_owner
15
+
16
+ def self.usable?(url)
17
+ url =~ /(vk\.com)|(vkontakte\.ru)/
18
+ end
19
+
20
+ def provider
21
+ 'Vkontakte'
22
+ end
23
+
24
+ %w[description keywords].each do |method|
25
+ define_method(method) { HTMLEntities.new.decode(video[:description]) }
26
+ end
27
+
28
+ %w[width height duration view_count].each do |method|
29
+ define_method(method) { video[method.to_sym].to_i }
30
+ end
31
+
32
+ def title
33
+ video[:title]
34
+ end
35
+
36
+ def embed_url
37
+ "http://vk.com/video_ext.php?oid=#{video_owner}&id=#{video_id}&hash=#{video[:hash]}"
38
+ end
39
+
40
+ private
41
+
42
+ def _parse_hash
43
+ @html[/hash2\\":\\"(\w+)/,1]
44
+ end
45
+
46
+ def _parse_view_count
47
+ @html[/mv_num_views\\"><b>(\d+)/,1].to_i
48
+ end
49
+
50
+ def _parse_title
51
+ @html[/<title>(.*)<\/title>/,1].gsub(" | ВКонтакте", "")
52
+ end
53
+
54
+ def _parse_duration
55
+ @html[/"duration":(\d+)/,1].to_i
56
+ end
57
+
58
+ def _parse_height
59
+ @html[/url(\d+)/,1].to_i
60
+ end
61
+
62
+ def _get_width(height)
63
+ { 240 => 320,
64
+ 360 => 480,
65
+ 480 => 640,
66
+ 720 => 1280
67
+ }[height]
68
+ end
69
+
70
+ def _parse_description
71
+ @html[/<meta name="description" content="(.*)" \/>/,1]
72
+ end
73
+
74
+ def _set_info_from_api
75
+ uri = open(_api_url, options)
76
+ if RUBY_VERSION.to_i < 2
77
+ @html = Iconv.iconv('utf-8', 'cp1251', uri.read)[0]
78
+ else
79
+ @html = uri.read.encode("UTF-8")
80
+ end
81
+ @video = {
82
+ :hash => _parse_hash,
83
+ :view_count => _parse_view_count,
84
+ :title => _parse_title,
85
+ :duration => _parse_duration,
86
+ :width => _get_width(_parse_height),
87
+ :height => _parse_height,
88
+ :description => _parse_description
89
+ }
90
+ end
91
+
92
+ def _set_video_id_from_url
93
+ url.gsub(_url_regex) { @video_owner, @video_id = ($1 || $2 || $3).split('_') }
94
+ end
95
+
96
+ def _url_regex
97
+ /(?:vkontakte\.ru\/video|vk\.com\/video)(\d+_\d+)/i
98
+ end
99
+
100
+ def _api_url
101
+ "http://vk.com/video#{video_owner}_#{video_id}"
102
+ end
103
+
104
+ def _default_iframe_attributes
105
+ { :allowfullscreen => "allowfullscreen" }
106
+ end
107
+
108
+ def _default_url_attributes
109
+ {}
110
+ end
111
+
112
+ end
113
+ end
114
+ end
@@ -9,12 +9,48 @@ module VideoInfo
9
9
  url =~ /(youtube\.com)|(youtu\.be)/
10
10
  end
11
11
 
12
- def default_iframe_attributes
13
- { :allowfullscreen => "allowfullscreen" }
12
+ def provider
13
+ 'YouTube'
14
14
  end
15
15
 
16
- def default_url_attributes
17
- {}
16
+ def title
17
+ _video_entry['title']['$t']
18
+ end
19
+
20
+ %w[description keywords].each do |method|
21
+ define_method(method) { _video_media_group["media$#{method}"]['$t'] }
22
+ end
23
+
24
+ %w[width height].each do |method|
25
+ define_method(method) { nil }
26
+ end
27
+
28
+ def duration
29
+ _video_media_group['yt$duration']['seconds'].to_i
30
+ end
31
+
32
+ def embed_url
33
+ "http://www.youtube.com/embed/#{video_id}"
34
+ end
35
+
36
+ def date
37
+ Time.parse(_video_entry['published']['$t'], Time.now.utc)
38
+ end
39
+
40
+ def thumbnail_small
41
+ _video_thumbnail(0)
42
+ end
43
+
44
+ def thumbnail_medium
45
+ _video_thumbnail(1)
46
+ end
47
+
48
+ def thumbnail_large
49
+ _video_thumbnail(2)
50
+ end
51
+
52
+ def view_count
53
+ _video_entry['yt$statistics'] ? _video_entry['yt$statistics']['viewCount'].to_i : 0
18
54
  end
19
55
 
20
56
  private
@@ -23,25 +59,28 @@ module VideoInfo
23
59
  /(?:youtube(?:-nocookie)?\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/ ]{11})/i
24
60
  end
25
61
 
26
- def _set_info_from_api
27
- uri = open("http://gdata.youtube.com/feeds/api/videos/#{video_id}?v=2&alt=json", options)
28
- video = MultiJson.load(uri.read)
29
- @provider = "YouTube"
30
- @url = url
31
- @embed_url = "http://www.youtube.com/embed/#{video_id}"
32
- video['entry'].tap do |entry|
33
- @title = entry['title']['$t']
34
- @description = entry['media$group']['media$description']['$t']
35
- @keywords = entry['media$group']['media$keywords']['$t']
36
- @duration = entry['media$group']['yt$duration']['seconds'].to_i
37
- @date = Time.parse(entry['published']['$t'], Time.now.utc)
38
- @thumbnail_small = entry['media$group']['media$thumbnail'][0]['url']
39
- @thumbnail_medium = entry['media$group']['media$thumbnail'][1]['url']
40
- @thumbnail_large = entry['media$group']['media$thumbnail'][2]['url']
41
- @view_count = entry['yt$statistics'] ? entry['yt$statistics']['viewCount'].to_i : 0
42
- end
43
- rescue
44
- nil
62
+ def _api_url
63
+ "http://gdata.youtube.com/feeds/api/videos/#{video_id}?v=2&alt=json"
64
+ end
65
+
66
+ def _default_iframe_attributes
67
+ { :allowfullscreen => "allowfullscreen" }
68
+ end
69
+
70
+ def _default_url_attributes
71
+ {}
72
+ end
73
+
74
+ def _video_entry
75
+ video['entry']
76
+ end
77
+
78
+ def _video_media_group
79
+ video['entry']['media$group']
80
+ end
81
+
82
+ def _video_thumbnail(id)
83
+ _video_entry['media$group']['media$thumbnail'][id]['url']
45
84
  end
46
85
 
47
86
  end
@@ -1,3 +1,3 @@
1
1
  module VideoInfo
2
- VERSION = '1.5.0'
2
+ VERSION = '1.6.0'
3
3
  end
data/lib/video_info.rb CHANGED
@@ -2,7 +2,7 @@ require 'video_info/version'
2
2
  require 'video_info/provider'
3
3
 
4
4
  module VideoInfo
5
- PROVIDERS = %w[Vimeo Youtube]
5
+ PROVIDERS = %w[Vimeo Vkontakte Youtube]
6
6
  PROVIDERS.each { |p| require "video_info/providers/#{p.downcase}" }
7
7
 
8
8
  def self.get(url, options = {})