video_info 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 = {})