lumiere 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e20f4a873d50e02f09619cd156bf79f2cc7cefb8
4
+ data.tar.gz: 7f7fe10f03c200211d4076111112d3c569112033
5
+ SHA512:
6
+ metadata.gz: bfd62f901fd6c5216bcf70309604cb5c6c8f614f56d564f61be3aec64b1b89f0dbc5f273f259b8ae7fbfb2c285d42387601babe28cf6f8c25fd2995841179426
7
+ data.tar.gz: afe0be0945ea5f3eeac4c355041ffc821bb1cf44bdba6d7da7c449e92b80f5b0f9b345af132bd6a1c24a495ee751773f06b9196754169f1a51369f18e3b336cf
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Karl Entwistle
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,10 @@
1
+ module Lumiere
2
+ module URISchemeless
3
+ def self.parse(url)
4
+ url = url[2..-1] if url[0..1] == '//' # TODO: make this better
5
+ uri = URI.parse(url)
6
+ uri = URI.parse("http://#{url}") unless uri.absolute?
7
+ uri
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ module Lumiere
2
+ VERSION = "0.0.4"
3
+ end
data/lib/lumiere.rb ADDED
@@ -0,0 +1,27 @@
1
+ require "lumiere/version"
2
+ require 'open-uri'
3
+ require 'forwardable'
4
+ require 'net/http'
5
+ require 'json'
6
+ require 'representable'
7
+ require 'representable/coercion'
8
+ require 'representable/json'
9
+ require 'representable/json/collection'
10
+
11
+ require_relative 'extended_uri'
12
+ require_relative 'provider'
13
+
14
+ class Elluminate
15
+ extend Forwardable
16
+
17
+ def initialize(url)
18
+ @provider ||= Lumiere::Provider.delegate(url)
19
+ end
20
+
21
+ def_delegators :@provider, :provider, :upload_date
22
+ def_delegators :@provider, :title, :description, :duration
23
+ def_delegators :@provider, :thumbnail_small, :thumbnail_medium, :thumbnail_large
24
+ def_delegators :@provider, :embed_code, :embed_url
25
+ def_delegators :@provider, :accessible?
26
+ def_delegators :@provider, :videos
27
+ end
@@ -0,0 +1,20 @@
1
+ module Lumiere
2
+ module VimeoVideoRepresenter
3
+ include Representable::JSON
4
+ include Representable::Coercion
5
+
6
+ property :title
7
+ property :description
8
+ property :duration, type: Integer
9
+ property :upload_date, type: DateTime
10
+ property :thumbnail_small
11
+ property :thumbnail_medium
12
+ property :thumbnail_large
13
+ end
14
+
15
+ module VimeoVideosRepresenter
16
+ include Representable::JSON::Collection
17
+
18
+ items extend: VimeoVideoRepresenter, class: OpenStruct
19
+ end
20
+ end
@@ -0,0 +1,78 @@
1
+ module Lumiere
2
+ class Vimeo < Provider
3
+ attr_accessor :url
4
+
5
+ USEABLE = ['www.vimeo.com', 'vimeo.com', 'player.vimeo.com']
6
+
7
+ def self.useable?(url)
8
+ uri = URISchemeless.parse(url)
9
+ USEABLE.include?(uri.host.to_s)
10
+ end
11
+
12
+ def initialize(url)
13
+ @url = url
14
+ end
15
+
16
+ def provider
17
+ "Vimeo"
18
+ end
19
+
20
+ def video_id
21
+ @video_id ||= calculate_video_id
22
+ end
23
+
24
+ def api_url
25
+ "http://vimeo.com/api/v2/video/#{video_id}.json"
26
+ end
27
+
28
+ def embed_url
29
+ "http://player.vimeo.com/video/#{video_id}"
30
+ end
31
+
32
+ def embed_code
33
+ "<iframe src=\"//player.vimeo.com/video/#{video_id}\" frameborder=\"0\" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>"
34
+ end
35
+
36
+ def title
37
+ fetch.title
38
+ end
39
+
40
+ def description
41
+ fetch.description
42
+ end
43
+
44
+ def duration
45
+ fetch.duration
46
+ end
47
+
48
+ def upload_date
49
+ fetch.upload_date
50
+ end
51
+
52
+ def thumbnail_small
53
+ fetch.thumbnail_small
54
+ end
55
+
56
+ def thumbnail_medium
57
+ fetch.thumbnail_medium
58
+ end
59
+
60
+ def thumbnail_large
61
+ fetch.thumbnail_large
62
+ end
63
+
64
+ private
65
+
66
+ def fetch
67
+ @fetch ||= [].extend(VimeoVideosRepresenter).from_json(raw_response)[0]
68
+ end
69
+
70
+ def calculate_video_id
71
+ uri = URISchemeless.parse(url)
72
+ uri.path.gsub!('/video/', '')
73
+ uri.path.delete!('/')
74
+ uri.path
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,30 @@
1
+ module Lumiere
2
+ module YouTubeVideoRepresenter
3
+ include Representable::JSON
4
+ self.representation_wrap = :entry
5
+
6
+ nested 'title' do
7
+ property :title, as: '$t'
8
+ end
9
+
10
+ nested 'published' do
11
+ include Representable::Coercion
12
+ property :upload_date, as: '$t', type: DateTime
13
+ end
14
+
15
+ nested 'media$group' do
16
+ nested 'media$description' do
17
+ property :description, as: '$t'
18
+ end
19
+
20
+ nested 'yt$duration' do
21
+ include Representable::Coercion
22
+ property :duration, as: :seconds, type: Integer
23
+ end
24
+
25
+ collection :thumbnails, class: OpenStruct, as: 'media$thumbnail' do
26
+ property :url
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,91 @@
1
+ module Lumiere
2
+ class YouTube < Provider
3
+ attr_accessor :url
4
+
5
+ USEABLE = ['www.youtube.com', 'youtube.com', 'youtu.be']
6
+
7
+ def self.useable?(url)
8
+ uri = URISchemeless.parse(url)
9
+ USEABLE.include?(uri.host.to_s)
10
+ end
11
+
12
+ def self.new_from_video_id(video_id)
13
+ new("http://www.youtube.com/watch?v=#{video_id}")
14
+ end
15
+
16
+ def initialize(url)
17
+ @url = url
18
+ end
19
+
20
+ def provider
21
+ "YouTube"
22
+ end
23
+
24
+ def video_id
25
+ @video_id ||= calculate_video_id
26
+ end
27
+
28
+ def api_url
29
+ "http://gdata.youtube.com/feeds/api/videos/#{video_id}?v=2&alt=json"
30
+ end
31
+
32
+ def embed_url
33
+ "http://www.youtube.com/embed/#{video_id}"
34
+ end
35
+
36
+ def embed_code
37
+ "<iframe src=\"//www.youtube.com/embed/#{video_id}\" frameborder=\"0\" allowfullscreen></iframe>"
38
+ end
39
+
40
+ def thumbnail_small
41
+ fetch! unless defined?(@thumbnails)
42
+ @thumbnails[0].url
43
+ end
44
+
45
+ def thumbnail_medium
46
+ fetch! unless defined?(@thumbnails)
47
+ @thumbnails[1].url
48
+ end
49
+
50
+ def thumbnail_large
51
+ fetch! unless defined?(@thumbnails)
52
+ @thumbnails[2].url
53
+ end
54
+
55
+ REMOTE_ATTRIBUTES = [:title, :description, :duration, :upload_date]
56
+
57
+ REMOTE_ATTRIBUTES.each do |attribute|
58
+ define_method(attribute) do
59
+ fetch! unless instance_variable_get("@#{attribute}")
60
+ instance_variable_get("@#{attribute}")
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ REMOTE_ATTRIBUTES.each do |attribute|
67
+ attr_writer attribute
68
+ end
69
+
70
+ attr_writer :thumbnails
71
+
72
+ def fetch!
73
+ self.extend(YouTubeVideoRepresenter).from_json(raw_response)
74
+ end
75
+
76
+ def calculate_video_id
77
+ uri = URISchemeless.parse(url)
78
+ if uri.query
79
+ params_hash = Hash[URI::decode_www_form(uri.query)]
80
+ params_hash['v']
81
+ else
82
+ uri.path.gsub!('/embed/', '')
83
+ uri.path.gsub!('/v/', '')
84
+ uri.path.gsub!('/e/', '')
85
+ uri.path.delete!('/')
86
+ uri.path
87
+ end
88
+ end
89
+
90
+ end
91
+ end
@@ -0,0 +1,42 @@
1
+ module Lumiere
2
+
3
+ module YouTubePlaylistRepresenter
4
+ include Representable::JSON
5
+ self.representation_wrap = :feed
6
+
7
+ nested 'openSearch$totalResults' do
8
+ include Representable::Coercion
9
+ property :total_results, as: '$t', type: Integer
10
+ end
11
+
12
+ nested 'title' do
13
+ property :title, as: '$t'
14
+ end
15
+
16
+ nested 'subtitle' do
17
+ property :description, as: '$t'
18
+ end
19
+
20
+ nested 'media$group' do
21
+ collection :thumbnails, class: OpenStruct, as: 'media$thumbnail' do
22
+ property :url
23
+ end
24
+ end
25
+
26
+ collection :videos, as: :entry, class: OpenStruct do
27
+
28
+ nested 'links' do
29
+ property :url, :reader => lambda { |doc, args| self.url = doc[0]['href'] }
30
+ end
31
+
32
+ nested 'media$group' do
33
+ nested 'yt$videoid' do
34
+ property :video_id, as: '$t'
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,103 @@
1
+ module Lumiere
2
+ class YouTubePlaylist < Provider
3
+ attr_accessor :url
4
+
5
+ USEABLE = ['www.youtube.com', 'youtube.com', 'youtu.be']
6
+
7
+ def self.useable?(url)
8
+ uri = URISchemeless.parse(url)
9
+ USEABLE.include?(uri.host.to_s) && (uri.path == '/playlist' || uri.path == '/view_play_list')
10
+ end
11
+
12
+ def initialize(url, opts={})
13
+ @url = url
14
+ @start_index = opts[:start_index] || 1
15
+ @max_results = opts[:max_results] || 25
16
+ end
17
+
18
+ def provider
19
+ "YouTube"
20
+ end
21
+
22
+ def playlist_id
23
+ @playlist_id ||= calculate_playlist_id
24
+ end
25
+
26
+ def api_url
27
+ url = "http://gdata.youtube.com/feeds/api/playlists/#{playlist_id}"
28
+ url << "?max-results=#{@max_results}"
29
+ url << "&start-index=#{@start_index}"
30
+ url << "&v=2&alt=json"
31
+ url
32
+ end
33
+
34
+ def embed_url
35
+ "http://youtube.com/embed/?list=#{playlist_id}"
36
+ end
37
+
38
+ def embed_code
39
+ "<iframe src=\"//youtube.com/embed/?list=#{playlist_id}\" frameborder=\"0\" allowfullscreen></iframe>"
40
+ end
41
+
42
+ def videos
43
+ fetch! unless defined?(@videos)
44
+
45
+ while @start_index < @total_results && @videos.size < @total_results
46
+ @start_index =+ @videos.size + 1
47
+ fetch!
48
+ end
49
+
50
+ @all_videos = @videos.map do |video|
51
+ YouTube.new_from_video_id(video.video_id)
52
+ end
53
+ end
54
+
55
+ def thumbnail_small
56
+ fetch! unless defined?(@thumbnails)
57
+ @thumbnails[0].url
58
+ end
59
+
60
+ def thumbnail_medium
61
+ fetch! unless defined?(@thumbnails)
62
+ @thumbnails[1].url
63
+ end
64
+
65
+ def thumbnail_large
66
+ fetch! unless defined?(@thumbnails)
67
+ @thumbnails[2].url
68
+ end
69
+
70
+ REMOTE_ATTRIBUTES = [:title, :description, :total_results]
71
+
72
+ REMOTE_ATTRIBUTES.each do |attribute|
73
+ define_method(attribute) do
74
+ fetch! unless instance_variable_get("@#{attribute}")
75
+ instance_variable_get("@#{attribute}")
76
+ end
77
+ end
78
+
79
+ private
80
+
81
+ REMOTE_ATTRIBUTES.each do |attribute|
82
+ attr_writer attribute
83
+ end
84
+
85
+ attr_writer :thumbnails
86
+
87
+ def videos=(videos)
88
+ @videos ||= []
89
+ @videos += videos
90
+ end
91
+
92
+ def fetch!
93
+ self.extend(YouTubePlaylistRepresenter).from_json(raw_response)
94
+ end
95
+
96
+ def calculate_playlist_id
97
+ uri = URISchemeless.parse(url)
98
+ params_hash = Hash[URI::decode_www_form(uri.query)]
99
+ params_hash['list'] || params_hash['p']
100
+ end
101
+
102
+ end
103
+ end
data/lib/provider.rb ADDED
@@ -0,0 +1,86 @@
1
+ module Lumiere
2
+ class Provider
3
+
4
+ PROVIDERS = %w(YouTubePlaylist YouTube Vimeo)
5
+ PROVIDERS.each do |provider|
6
+ require_relative "provider/#{provider.downcase}/#{provider.downcase}"
7
+ require_relative "provider/#{provider.downcase}/representer"
8
+ end
9
+
10
+ def self.delegate(url)
11
+ PROVIDERS.each do |provider|
12
+ provider_class = Object.const_get("Lumiere").const_get(provider)
13
+ if provider_class.useable?(url)
14
+ return provider_class.new(url)
15
+ end
16
+ end
17
+
18
+ raise NotImplementedError
19
+ end
20
+
21
+ def api_url
22
+ raise NotImplementedError
23
+ end
24
+
25
+ def embed_url
26
+ raise NotImplementedError
27
+ end
28
+
29
+ def embed_code
30
+ raise NotImplementedError
31
+ end
32
+
33
+ def provider
34
+ raise NotImplementedError
35
+ end
36
+
37
+ def title
38
+ raise NotImplementedError
39
+ end
40
+
41
+ def description
42
+ raise NotImplementedError
43
+ end
44
+
45
+ def duration
46
+ raise NotImplementedError
47
+ end
48
+
49
+ def upload_date
50
+ raise NotImplementedError
51
+ end
52
+
53
+ def thumbnail_small
54
+ raise NotImplementedError
55
+ end
56
+
57
+ def thumbnail_medium
58
+ raise NotImplementedError
59
+ end
60
+
61
+ def thumbnail_large
62
+ raise NotImplementedError
63
+ end
64
+
65
+ def videos
66
+ raise NotImplementedError
67
+ end
68
+
69
+ def accessible?
70
+ code = Net::HTTP.get_response(URI(api_url)).code
71
+ @remote_status ||= !%w[403 404].include?(code)
72
+ end
73
+
74
+ def ==(other)
75
+ if other.respond_to?(:url)
76
+ url == other.url
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ def raw_response
83
+ open(api_url).read
84
+ end
85
+ end
86
+ end
metadata ADDED
@@ -0,0 +1,166 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lumiere
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Karl Entwistle
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: representable
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.8.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.8.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: virtus
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.5.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.5.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.6'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.6'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: webmock
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: vcr
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: activesupport
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Lumiere fetches metadata from video providers
126
+ email: karl.entwistle@unboxedconsulting.com
127
+ executables: []
128
+ extensions: []
129
+ extra_rdoc_files: []
130
+ files:
131
+ - LICENSE.txt
132
+ - lib/extended_uri.rb
133
+ - lib/lumiere.rb
134
+ - lib/lumiere/version.rb
135
+ - lib/provider.rb
136
+ - lib/provider/vimeo/representer.rb
137
+ - lib/provider/vimeo/vimeo.rb
138
+ - lib/provider/youtube/representer.rb
139
+ - lib/provider/youtube/youtube.rb
140
+ - lib/provider/youtubeplaylist/representer.rb
141
+ - lib/provider/youtubeplaylist/youtubeplaylist.rb
142
+ homepage: https://github.com/karlentwistle/lumiere
143
+ licenses:
144
+ - MIT
145
+ metadata: {}
146
+ post_install_message:
147
+ rdoc_options: []
148
+ require_paths:
149
+ - lib
150
+ required_ruby_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: 1.9.3
155
+ required_rubygems_version: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ requirements: []
161
+ rubyforge_project:
162
+ rubygems_version: 2.2.2
163
+ signing_key:
164
+ specification_version: 4
165
+ summary: Lumiere fetches metadata from video providers
166
+ test_files: []