videodrome 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --fail-fast
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in videodrome.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Linking Paths
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # Videodrome
2
+
3
+ Access metadata of **public videos** on Youtube using YouTube Data API v3. Please see the documentation for this API at https://developers.google.com/youtube/v3/.
4
+
5
+ Videodrome is designed to be minimal on its features and dependencies and to work with all Ruby versions (>= 1.8.6). Videodrome can only access public information since it **does not provides** any authentication method to access to [private user data](https://developers.google.com/youtube/v3/guides/authentication).
6
+
7
+ If you want a fully featured YouTube API client please check the excelent [yt](https://github.com/Fullscreen/yt) gem.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'videodrome'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install videodrome
22
+
23
+ ## Setup
24
+
25
+ Although Videodrome does not require any user authentication, the new Youtube API requires to sign all calls with an API key, even if you are accessing only public data. Please follow the steps at [Obtaining authorization credentials](https://developers.google.com/youtube/registering_an_application) to generate a server key.
26
+
27
+ Once you have the API key, the easiest to provide it to Videodrome is to set it up in your environment:
28
+
29
+ ``` sh
30
+ VIDEODROME_YOUTUBE_API_KEY="AIzaS…wGhuD"
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ Once the API Key is available to Videodrome, retrieve the metadata of a video using its URL:
36
+
37
+ ``` ruby
38
+ video = Videodrome::Video.new("https://youtube.com/watch?v=NZ8RiLLt6yg")
39
+ video.title # "The Mercedes-Benz CLA (a car commercial)"
40
+ video.published_at # Thu Sep 05 21:01:57 UTC 2013
41
+ video.thumbnail["url"] # "https://i.ytimg.com/vi/NZ8RiLLt6yg/sddefault.jpg"
42
+ video.embed_html # <iframe type='text/html' src='http://www.youtube.com/embed/NZ8RiLLt6yg' … />
43
+ ```
44
+
45
+ URL short versions are also supported:
46
+
47
+ ``` ruby
48
+ Videodrome::Video.new("https://youtu.be/NZ8RiLLt6yg")
49
+ ```
50
+
51
+ Customize the API call by proving an option hash to the initialization. For details on the parameters you can use please check [the Videos:list documentation](https://developers.google.com/youtube/v3/docs/videos/list#part).
52
+
53
+ ``` ruby
54
+ Videodrome::Video.new("https://youtu.be/NZ8RiLLt6yg", :part => "snippet,player,contentDetails,status,fileDetails")
55
+ ```
56
+
57
+ This customization can be used too to explictly provide the API key to sign the calls:
58
+
59
+ ``` ruby
60
+ Videodrome::Video.new("https://youtu.be/NZ8RiLLt6yg", :key => "AIzaS…wGhuD")
61
+ ```
62
+
63
+
64
+ ## To-do
65
+
66
+ Provide mocks to prevent real requests to the Youtube API when running the specs.
67
+
68
+ ## Contributing
69
+
70
+ 1. Fork it ( http://github.com/<my-github-username>/videodrome/fork )
71
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
72
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
73
+ 4. Push to the branch (`git push origin my-new-feature`)
74
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require "bundler/gem_tasks"
2
+ require "videodrome"
3
+
4
+ Dir.glob('tasks/**/*.rake').each(&method(:import))
@@ -0,0 +1,31 @@
1
+ module Videodrome
2
+ # Connection class to make the requests to Youtube API.
3
+ class Connection
4
+ API_SERVER = "https://www.googleapis.com"
5
+ API_SERVICE = "youtube"
6
+ API_VERSION = "v3"
7
+
8
+ def get(params = {})
9
+ defaults = {
10
+ :part => "snippet,player,contentDetails,status"
11
+ }
12
+ defaults[:key] = ENV["VIDEODROME_YOUTUBE_API_KEY"] if ENV["VIDEODROME_YOUTUBE_API_KEY"]
13
+ response = connection.get(search_path, defaults.merge(params))
14
+ JSON.parse(response.body)
15
+ end
16
+
17
+ protected
18
+
19
+ def connection
20
+ @connection ||= Faraday.new(:url => API_SERVER) do |faraday|
21
+ faraday.request :url_encoded
22
+ faraday.response :logger if ENV["VIDEODROME_DEBUG"]
23
+ faraday.adapter Faraday.default_adapter
24
+ end
25
+ end
26
+
27
+ def search_path
28
+ "/#{API_SERVICE}/#{API_VERSION}/videos"
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,10 @@
1
+ module Videodrome
2
+ module Errors
3
+ # :nodoc
4
+ class InvalidURL < StandardError
5
+ def message
6
+ "The URL provided is not a valid Youtube Video URL."
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ module Videodrome
2
+ module Errors
3
+ # :nodoc
4
+ class RequestError < StandardError
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,30 @@
1
+ module Videodrome
2
+ # ID extraction utility class for Youtube video URLs
3
+ class URL
4
+ def initialize(url)
5
+ @url = url
6
+ match_url(url)
7
+ end
8
+
9
+ def id
10
+ @match_data[1]
11
+ end
12
+
13
+ protected
14
+
15
+ def match_url(url)
16
+ found = patterns.find do |pattern|
17
+ @match_data = url.match(pattern)
18
+ end
19
+ raise Videodrome::Errors::InvalidURL unless found
20
+ end
21
+
22
+ def patterns
23
+ prefix = "^(?:https?://)?(?:www\.)?"
24
+ suffix = "(?:|/)"
25
+ video_id = "([a-zA-Z0-9_-]+)"
26
+ domains = ["youtube\\.com/watch\\?v=#{video_id}", "youtu\\.be/#{video_id}"]
27
+ domains.map { |domain| %r{#{prefix}#{domain}#{suffix}} }
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,3 @@
1
+ module Videodrome
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,59 @@
1
+ require "ostruct"
2
+ require "time"
3
+
4
+ module Videodrome
5
+ # Video wrapper for Youtube info
6
+ class Video
7
+ attr_reader :id, :raw_data, :snippet, :details, :player, :status
8
+
9
+ def initialize(url, options = {})
10
+ @url = URL.new(url)
11
+ @id = @url.id
12
+ @raw_data = Videodrome.connection.get(options.merge(:id => @id))
13
+ parse_raw_data
14
+ end
15
+
16
+ def published_at
17
+ Time.iso8601(snippet.publishedAt)
18
+ end
19
+
20
+ def title
21
+ snippet.title
22
+ end
23
+
24
+ def description
25
+ snippet.description
26
+ end
27
+
28
+ def thumbnails
29
+ snippet.thumbnails
30
+ end
31
+
32
+ def thumbnail(size = "standard")
33
+ thumbnails.find { |k, _| k == size }[1]
34
+ end
35
+
36
+ def embed_html
37
+ player.embedHtml if embeddable
38
+ end
39
+
40
+ def duration
41
+ details.duration
42
+ end
43
+
44
+ def embeddable
45
+ status.embeddable
46
+ end
47
+
48
+ protected
49
+
50
+ def parse_raw_data
51
+ raise Videodrome::Errors::RequestError, @raw_data["error"]["message"] if @raw_data["error"]
52
+ item = @raw_data["items"][0]
53
+ @snippet = OpenStruct.new(item["snippet"])
54
+ @details = OpenStruct.new(item["contentDetails"])
55
+ @player = OpenStruct.new(item["player"])
56
+ @status = OpenStruct.new(item["status"])
57
+ end
58
+ end
59
+ end
data/lib/videodrome.rb ADDED
@@ -0,0 +1,16 @@
1
+ require "videodrome/version"
2
+ require "videodrome/errors/invalid_url"
3
+ require "videodrome/errors/request_error"
4
+ require "videodrome/connection"
5
+ require "videodrome/video"
6
+ require "videodrome/url"
7
+
8
+ require "faraday"
9
+ require "json"
10
+
11
+ # nodoc
12
+ module Videodrome
13
+ def self.connection
14
+ @connection ||= Videodrome::Connection.new
15
+ end
16
+ end
@@ -0,0 +1 @@
1
+ require "videodrome"
data/spec/url_spec.rb ADDED
@@ -0,0 +1,28 @@
1
+ require "spec_helper"
2
+
3
+ describe Videodrome::URL do
4
+ context "given an valid video URL" do
5
+ subject(:parser) { Videodrome::URL.new(url) }
6
+ describe "parsing a long video URL" do
7
+ let(:url) { "https://youtube.com/watch?v=NZ8RiLLt6yg" }
8
+ it { expect(parser.id).to eq "NZ8RiLLt6yg" }
9
+ end
10
+
11
+ context "parsing a short video URL" do
12
+ let(:url) { "https://youtu.be/NZ8RiLLt6yg" }
13
+ it { expect(parser.id).to eq "NZ8RiLLt6yg" }
14
+ end
15
+
16
+ context "parsing a URL with a trailing slash" do
17
+ let(:url) { "https://youtube.com/watch?v=NZ8RiLLt6yg" }
18
+ it { expect(parser.id).to eq "NZ8RiLLt6yg" }
19
+ end
20
+ end
21
+
22
+ #context "given an invalid video URL" do
23
+ # #subject(:parser) { Videodrome::URL.new(url) }
24
+ # let(:url) { "https://vimeo.com" }
25
+ # #it { expect(Videodrome::URL.new("")).to raise_error Videodrome::Errors::InvalidURL }
26
+ # it { expect(Videodrome::URL.new("")).to raise_error }
27
+ #end
28
+ end
@@ -0,0 +1,45 @@
1
+ require "spec_helper"
2
+
3
+
4
+ describe Videodrome::Video do
5
+ subject(:video) { Videodrome::Video.new(url) }
6
+
7
+ context "given a valid URL" do
8
+ let(:url) { "https://youtube.com/watch?v=NZ8RiLLt6yg" }
9
+ let(:attrs) do
10
+ {
11
+ :published_at => Time.iso8601("2013-09-05T21:01:57.000Z"),
12
+ :title => "The Mercedes-Benz CLA (a car commercial)",
13
+ :thumbnails => {
14
+ "default" => { "url" => "https://i.ytimg.com/vi/NZ8RiLLt6yg/default.jpg", "width" => 120, "height" => 90 },
15
+ "medium" => { "url" => "https://i.ytimg.com/vi/NZ8RiLLt6yg/mqdefault.jpg", "width" => 320, "height" => 180 },
16
+ "high" => { "url" => "https://i.ytimg.com/vi/NZ8RiLLt6yg/hqdefault.jpg", "width" => 480, "height" => 360 },
17
+ "standard" => { "url" => "https://i.ytimg.com/vi/NZ8RiLLt6yg/sddefault.jpg", "width" => 640, "height" => 480 }
18
+ },
19
+ :embeddable => true,
20
+ :embed_html => "<iframe type='text/hftml' src='http://www.youtube.com/embed/NZ8RiLLt6yg' width='640' height='360' frameborder='0' allowfullscreen='true'/>"
21
+ }
22
+ end
23
+ describe "#published_at" do
24
+ it { expect(video.published_at).to eq attrs[:published_at] }
25
+ end
26
+ describe "#title" do
27
+ it { expect(video.title).to eq attrs[:title] }
28
+ end
29
+ describe "#thumbnails" do
30
+ it("returns multiple thumbnails") { expect(video.thumbnails.size).to eq attrs[:thumbnails].size }
31
+ end
32
+ describe "#thumbnail" do
33
+ it { expect(video.thumbnail["width"]).to eq attrs[:thumbnails]["standard"]["width"] }
34
+ it { expect(video.thumbnail["height"]).to eq attrs[:thumbnails]["standard"]["height"] }
35
+ it { expect(video.thumbnail["url"]).to eq attrs[:thumbnails]["standard"]["url"] }
36
+ end
37
+ describe "#embeddable" do
38
+ it { expect(video.embeddable).to be attrs[:embeddable] }
39
+ end
40
+ describe "#embed_html" do
41
+ it("returns the embeddable player iframe") { expect(video.embed_html).to eq attrs[:embed_html] }
42
+ end
43
+ end
44
+
45
+ end
data/tasks/rspec.rake ADDED
@@ -0,0 +1,4 @@
1
+ require "rspec/core/rake_task"
2
+
3
+ desc "Run all tests"
4
+ RSpec::Core::RakeTask.new(:spec)
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'videodrome/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "videodrome"
8
+ spec.version = Videodrome::VERSION
9
+ spec.authors = ["Aitor García"]
10
+ spec.email = ["aitor@linkingpaths.com"]
11
+ spec.summary = %q{Access metadata of public videos on Youtube.}
12
+ spec.homepage = "http://github.com/linkingpaths/videodrome"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "faraday"
21
+ spec.add_dependency "json"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.5"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec"
26
+ end
metadata ADDED
@@ -0,0 +1,155 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: videodrome
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - "Aitor Garc\xC3\xADa"
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2015-05-12 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ prerelease: false
22
+ type: :runtime
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ version_requirements: *id001
33
+ name: faraday
34
+ - !ruby/object:Gem::Dependency
35
+ prerelease: false
36
+ type: :runtime
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
45
+ version: "0"
46
+ version_requirements: *id002
47
+ name: json
48
+ - !ruby/object:Gem::Dependency
49
+ prerelease: false
50
+ type: :development
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ hash: 5
57
+ segments:
58
+ - 1
59
+ - 5
60
+ version: "1.5"
61
+ version_requirements: *id003
62
+ name: bundler
63
+ - !ruby/object:Gem::Dependency
64
+ prerelease: false
65
+ type: :development
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ version_requirements: *id004
76
+ name: rake
77
+ - !ruby/object:Gem::Dependency
78
+ prerelease: false
79
+ type: :development
80
+ requirement: &id005 !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ version_requirements: *id005
90
+ name: rspec
91
+ description:
92
+ email:
93
+ - aitor@linkingpaths.com
94
+ executables: []
95
+
96
+ extensions: []
97
+
98
+ extra_rdoc_files: []
99
+
100
+ files:
101
+ - .gitignore
102
+ - .rspec
103
+ - Gemfile
104
+ - LICENSE
105
+ - README.md
106
+ - Rakefile
107
+ - lib/videodrome.rb
108
+ - lib/videodrome/connection.rb
109
+ - lib/videodrome/errors/invalid_url.rb
110
+ - lib/videodrome/errors/request_error.rb
111
+ - lib/videodrome/url.rb
112
+ - lib/videodrome/version.rb
113
+ - lib/videodrome/video.rb
114
+ - spec/spec_helper.rb
115
+ - spec/url_spec.rb
116
+ - spec/video_spec.rb
117
+ - tasks/rspec.rake
118
+ - videodrome.gemspec
119
+ homepage: http://github.com/linkingpaths/videodrome
120
+ licenses:
121
+ - MIT
122
+ post_install_message:
123
+ rdoc_options: []
124
+
125
+ require_paths:
126
+ - lib
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ none: false
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ hash: 3
133
+ segments:
134
+ - 0
135
+ version: "0"
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ hash: 3
142
+ segments:
143
+ - 0
144
+ version: "0"
145
+ requirements: []
146
+
147
+ rubyforge_project:
148
+ rubygems_version: 1.8.24
149
+ signing_key:
150
+ specification_version: 3
151
+ summary: Access metadata of public videos on Youtube.
152
+ test_files:
153
+ - spec/spec_helper.rb
154
+ - spec/url_spec.rb
155
+ - spec/video_spec.rb