tiegz-ruby-mtv 1.0 → 1.1
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.
- data/README +10 -3
- data/lib/mtv/artist.rb +112 -0
- data/lib/mtv/base.rb +57 -0
- data/lib/mtv/thumbnail.rb +10 -0
- data/lib/mtv/video.rb +131 -0
- data/lib/mtv.rb +13 -0
- data/ruby-mtv.gemspec +9 -5
- metadata +7 -3
- data/ruby-mtv.rb +0 -283
data/README
CHANGED
@@ -4,13 +4,13 @@ ruby-mtv
|
|
4
4
|
|
5
5
|
== DESCRIPTION:
|
6
6
|
|
7
|
-
This is a Ruby library for the MTV api. Right now it has classes for Artists and Videos, although
|
7
|
+
This is a Ruby library for the MTV Networks api. Right now it has classes for Artists and Videos, although
|
8
8
|
there is much to be done, spec'd and/or tested!
|
9
9
|
|
10
10
|
== REQUIREMENTS:
|
11
11
|
|
12
|
-
*
|
13
|
-
|
12
|
+
* ActiveSupport
|
13
|
+
|
14
14
|
== INSTALL:
|
15
15
|
|
16
16
|
$ gem sources -a http://gems.github.com/ (you only need to do this once)
|
@@ -42,6 +42,13 @@ To find a video,
|
|
42
42
|
v.artist
|
43
43
|
# => #<MTV::Artist name: "Dinosaur Jr.", uid: "dinosaur_jr", uri: "http://api.mtvnservices.com/1/artist/dinosaur_jr/">
|
44
44
|
|
45
|
+
To get html embed markup for the video swf,
|
46
|
+
|
47
|
+
v.embed_code(:width => 200)
|
48
|
+
# => "<embed src=\"http://media.mtvnservices.com/mgid:uma:video:api.mtvnservices.com:143042\"
|
49
|
+
type=\"application/x-shockwave-flash\" width=\"200\" height=\"163\"
|
50
|
+
allowFullScreen=\"true\" allowScriptAccess=\"always\" />"
|
51
|
+
|
45
52
|
To find all videos for an artist,
|
46
53
|
|
47
54
|
artist.videos
|
data/lib/mtv/artist.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
module MTV
|
2
|
+
# This class represents a music artist in MTV's database.
|
3
|
+
class Artist < Base
|
4
|
+
attr_accessor :name, :uid, :uri, :links, :updated
|
5
|
+
|
6
|
+
#-----------------
|
7
|
+
# Class Methods
|
8
|
+
#-----------------
|
9
|
+
class << self
|
10
|
+
# MTV::Artist.browse 'x' => X, X-Clan, The X-Ecutioners, Xiren, Xscape, Xtreme, Xzibit
|
11
|
+
def browse(letter='a')
|
12
|
+
response = request "artist/browse/#{letter.to_s.first}/"
|
13
|
+
raise Error, "That artist not found!" if response.nil? || response.empty?
|
14
|
+
parse_many response
|
15
|
+
end
|
16
|
+
|
17
|
+
# MTV::Artist.find 'beck'
|
18
|
+
# MTV::Artist.find 'meGADeath'
|
19
|
+
def find(name, options={})
|
20
|
+
return name if name.is_a? Artist
|
21
|
+
|
22
|
+
options.symbolize_keys!
|
23
|
+
name = string_to_uid(options[:name] || name)
|
24
|
+
|
25
|
+
response = request "artist/#{name}/"
|
26
|
+
raise Error, "That artist not found!" if response.nil? || response.empty?
|
27
|
+
parse_one response
|
28
|
+
end
|
29
|
+
|
30
|
+
# MTV::Artist.related 'qtip'
|
31
|
+
# MTV::Artist.related MTV::Artist.find('qtip')
|
32
|
+
def related(artist)
|
33
|
+
artist = find(artist)
|
34
|
+
response = request "artist/#{artist.uid}/related/"
|
35
|
+
raise Error, "That artist not found!" if response.nil? || response.empty?
|
36
|
+
parse_many response
|
37
|
+
end
|
38
|
+
|
39
|
+
# MTV::Artist.search 'beck', :max_results => 1, :start_index => 1
|
40
|
+
def search(term=nil, options={})
|
41
|
+
options.symbolize_keys!
|
42
|
+
params = {}
|
43
|
+
params[:'max-results'] = options[:max_results] || 1
|
44
|
+
params[:'start-index'] = options[:start_index]
|
45
|
+
term = options[:term] || term
|
46
|
+
params.reject! { |k,v| !v }
|
47
|
+
response = request "artist/search?#{term.to_query('term')}&#{params.to_param}"
|
48
|
+
raise Error, "That artist not found!" if response.nil? || response.empty?
|
49
|
+
parse_many response
|
50
|
+
end
|
51
|
+
|
52
|
+
# MTV::Artist.find('beck').videos
|
53
|
+
def videos(artist)
|
54
|
+
MTV::Video.from_artist(artist)
|
55
|
+
end
|
56
|
+
|
57
|
+
protected
|
58
|
+
def parse_many(body)
|
59
|
+
entries = XmlSimple.xml_in(body)['entry']
|
60
|
+
raise Error, "That artist not found!" if entries.nil?
|
61
|
+
entries = [entries] unless entries.is_a? Array
|
62
|
+
entries.map { |entry|
|
63
|
+
instantiate entry
|
64
|
+
}.reject { |artist| MTV::Artist.name.nil? || MTV::Artist.name.empty? }
|
65
|
+
end
|
66
|
+
|
67
|
+
def parse_one(body)
|
68
|
+
entry = XmlSimple.xml_in(body)
|
69
|
+
raise Error, "That artist not found!" if entry['author'].first['name'].nil? || entry['author'].first['name'].empty?
|
70
|
+
instantiate entry
|
71
|
+
end
|
72
|
+
|
73
|
+
def instantiate(entry={})
|
74
|
+
Artist.new(:name => entry['author'].first['name'].to_s,
|
75
|
+
:uri => entry['author'].first['uri'].to_s,
|
76
|
+
:links => entry['link'].map { |link| link['href'].to_s },
|
77
|
+
:updated => entry['updated'].to_s.to_datetime)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
#-----------------
|
82
|
+
# Instance Methods
|
83
|
+
#-----------------
|
84
|
+
def initialize(values={})
|
85
|
+
super(values)
|
86
|
+
self.uid = uri.gsub(self.class.base_url + "/artist", '').delete '/' unless @uri.nil?
|
87
|
+
end
|
88
|
+
|
89
|
+
def inspect
|
90
|
+
attrs = [:name].map { |name| "#{name}: #{attribute_for_inspect(name)}" }.compact.join(", ")
|
91
|
+
"#<#{self.class} #{attrs}>"
|
92
|
+
end
|
93
|
+
|
94
|
+
# artist = MTV::Artist.search('In Flames')[2]
|
95
|
+
# MTV::Artist.browse => I Am Ghost, IB3, INXS, Ice Cube, ...
|
96
|
+
def browse
|
97
|
+
@browse ||= Artist.browse(uid.first)
|
98
|
+
end
|
99
|
+
|
100
|
+
# artist = MTV::Artist.search 'Frank Zappa'
|
101
|
+
# MTV::Artist.browse => Amon Amarth, Amorphis, Arch Enemy, Arcturus, Borknagar, ...
|
102
|
+
def related
|
103
|
+
@related ||= Artist.related(self)
|
104
|
+
end
|
105
|
+
|
106
|
+
# artist = MTV::Artist.find('beck')
|
107
|
+
# MTV::Artist.videos => ...
|
108
|
+
def videos
|
109
|
+
@videos ||= Video.from_artist(self)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
data/lib/mtv/base.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module MTV
|
2
|
+
class Base
|
3
|
+
#-----------------
|
4
|
+
# Class Methods
|
5
|
+
#-----------------
|
6
|
+
|
7
|
+
class << self
|
8
|
+
cattr_accessor :host, :protocol, :base_url, :debug
|
9
|
+
|
10
|
+
def request path
|
11
|
+
url = URI.escape "#{base_url}/#{path}"
|
12
|
+
response = nil
|
13
|
+
seconds = Benchmark.realtime { response = open url }
|
14
|
+
puts " \e[4;36;1mREQUEST (#{sprintf("%f", seconds)})\e[0m \e[0;1m#{url}\e[0m" if debug
|
15
|
+
response.is_a?(String) ? response : response.read
|
16
|
+
rescue OpenURI::HTTPError => e
|
17
|
+
puts " \e[4;36;1mREQUEST (404)\e[0m \e[0;1m#{url}\e[0m" if debug
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
# assuming that the uid for the artist is downcase and no spaces, this tries to match better
|
23
|
+
def string_to_uid(str)
|
24
|
+
str.downcase.underscore.gsub(" ", "_")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# These are the default settings for the Base class. Change them, even per subclass if needed.
|
29
|
+
# Appears that MTVN doesn't have SSL enabled for the api yet (10/08).
|
30
|
+
self.host = "api.mtvnservices.com/1"
|
31
|
+
self.protocol = "http"
|
32
|
+
self.base_url = "#{protocol}://#{host}"
|
33
|
+
self.debug = true if ENV['DEBUG']
|
34
|
+
|
35
|
+
#-----------------
|
36
|
+
# Instance Methods
|
37
|
+
#-----------------
|
38
|
+
def initialize(values={})
|
39
|
+
values.each { |k, v| send "#{k}=", v }
|
40
|
+
end
|
41
|
+
|
42
|
+
# Copied from ActiveRecord::Base
|
43
|
+
def attribute_for_inspect(attr_name)
|
44
|
+
value = send(attr_name)
|
45
|
+
|
46
|
+
if value.is_a?(String) && value.length > 50
|
47
|
+
"#{value[0..50]}...".inspect
|
48
|
+
elsif value.is_a?(Date) || value.is_a?(Time)
|
49
|
+
%("#{value.to_s(:db)}")
|
50
|
+
else
|
51
|
+
value.inspect
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
data/lib/mtv/video.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
module MTV
|
2
|
+
# This class represents a music video in MTV's database.
|
3
|
+
class Video < Base
|
4
|
+
attr_accessor :artist, :artist_name, :artist_uri, :category, :content, :credit,
|
5
|
+
:media_player_url, :media_thumbnails, :media_title, :media_description,
|
6
|
+
:media_keywords, :media_duration, :media_expression, :media_url, :media_type,
|
7
|
+
:media_credits, :media_category, :media_medium,
|
8
|
+
:title, :published, :uid, :updated, :uri, :vid
|
9
|
+
|
10
|
+
#-----------------
|
11
|
+
# Class Methods
|
12
|
+
#-----------------
|
13
|
+
class << self
|
14
|
+
# MTV::Video.find '1234abcd'
|
15
|
+
def find(uid, options={})
|
16
|
+
return uid if uid.is_a? Artist
|
17
|
+
|
18
|
+
options.symbolize_keys!
|
19
|
+
uid = options[:uid] || uid
|
20
|
+
|
21
|
+
response = request "video/#{uid}/"
|
22
|
+
raise Error, "That video not found!" if response.nil? || response.empty?
|
23
|
+
parse_one response
|
24
|
+
end
|
25
|
+
|
26
|
+
# MTV::Video.from_artist(Artist.find('beck'))
|
27
|
+
# MTV::Video.from_artist('beck')
|
28
|
+
def from_artist(artist)
|
29
|
+
artist_uid = artist.is_a?(Artist) ? artist.uid : string_to_uid(artist)
|
30
|
+
|
31
|
+
response = request "artist/#{artist_uid}/videos"
|
32
|
+
raise Error, "No videos found!" if response.nil? || response.empty?
|
33
|
+
parse_many response
|
34
|
+
end
|
35
|
+
|
36
|
+
# http://api.mtvnservices.com/1/video/search/[parameters]
|
37
|
+
# MTV::Video.search 'the golden age', :max_results => 1, :start_index => 1
|
38
|
+
def search(term=nil, options={})
|
39
|
+
options.symbolize_keys!
|
40
|
+
params = { :'max-results' => (options[:max_results] || 1),
|
41
|
+
:'start-index' => options[:start_index] }.reject { |k,v| v.nil? || v.to_s.empty? }.to_query
|
42
|
+
params = "&#{params}" unless params.empty?
|
43
|
+
term = (options[:term] || term).to_query('term')
|
44
|
+
|
45
|
+
response = request "video/search?#{term}#{params}"
|
46
|
+
raise Error, "No videos not found!" if response.nil? || response.empty?
|
47
|
+
parse_many response
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
def parse_many(body)
|
52
|
+
body = hack_media_enclosures(body)
|
53
|
+
entries = XmlSimple.xml_in(body)['entry']
|
54
|
+
entries = [entries] unless entries.is_a? Array
|
55
|
+
entries.reject! { |entry| entry.nil? }
|
56
|
+
entries.map { |entry|
|
57
|
+
instantiate entry
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def parse_one(body)
|
62
|
+
body = hack_media_enclosures(body)
|
63
|
+
entry = XmlSimple.xml_in(body)
|
64
|
+
raise Error, "That artist not found!" if entry['author']['name'].nil? || entry['author']['name'].empty?
|
65
|
+
instantiate entry
|
66
|
+
end
|
67
|
+
|
68
|
+
# HACK because XmlSimple doesn't seem to handle enclosures, we'll replace colons with hyphens
|
69
|
+
# TODO write a better regexp for that hack :\
|
70
|
+
def hack_media_enclosures(body)
|
71
|
+
body.gsub("<media:", "<media_").gsub("</media:", "</media_")
|
72
|
+
end
|
73
|
+
|
74
|
+
def instantiate(entry={})
|
75
|
+
Video.new(:title => entry['title'].to_s,
|
76
|
+
:artist_uri => entry['author'].first['uri'].to_s,
|
77
|
+
:artist_name => entry['author'].first['name'].to_s,
|
78
|
+
:published => entry['published'].to_s,
|
79
|
+
:content => entry['content'], # Artist Name, Video Title, and Record Label
|
80
|
+
:uri => entry['link'].select { |link| link['rel'].to_s == 'self' }.first['href'].to_s,
|
81
|
+
:updated => (entry['updated'].to_s.to_datetime rescue nil),
|
82
|
+
:media_category => entry['media_category'].to_s, # governing agreement
|
83
|
+
:media_credits => entry['media_credit'].map { |credit| "#{credit['content'] || 'N/A'} (#{credit['role']})}" }.join(', '),
|
84
|
+
:media_description => entry['media_description'].to_s,
|
85
|
+
:media_duration => entry['media_content'].first['duration'].to_s,
|
86
|
+
:media_expression => entry['media_content'].first['expression'].to_s,
|
87
|
+
:media_keywords => entry['media_keywords'].to_s,
|
88
|
+
:media_medium => entry['media_content'].first['medium'].to_s,
|
89
|
+
:media_player_url => entry['media_player'].first['url'].to_s,
|
90
|
+
:media_thumbnails => entry['media_thumbnail'].to_s,
|
91
|
+
:media_title => entry['media_title'].to_s,
|
92
|
+
:media_type => entry['media_content'].first['type'].to_s,
|
93
|
+
:media_url => entry['media_content'].first['url'].to_s)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
#-----------------
|
98
|
+
# Instance Methods
|
99
|
+
#-----------------
|
100
|
+
def initialize(values={})
|
101
|
+
super(values)
|
102
|
+
self.uid = uri.gsub(self.class.base_url + "/video", '').delete '/' unless @uid
|
103
|
+
self.vid = media_url.split(':').last
|
104
|
+
end
|
105
|
+
|
106
|
+
# MTV::Video.search('gold').first.artist
|
107
|
+
def artist
|
108
|
+
@artist ||= Artist.find(artist_uri.gsub(self.class.base_url + "/artist", '').delete('/'))
|
109
|
+
end
|
110
|
+
|
111
|
+
# HTML to embed the Flash player for this video
|
112
|
+
def embed_code(options={})
|
113
|
+
options[:width] ||= (options[:height] ? ((options[:height]*448).to_f/366).to_i : 448)
|
114
|
+
options[:height] ||= (options[:width]==448 ? 366 : ((options[:width]*366).to_f/448).to_i)
|
115
|
+
|
116
|
+
<<-EOS
|
117
|
+
<embed src="#{media_url}" type="#{media_type}" width="#{options[:width]}" height="#{options[:height]}"
|
118
|
+
allowFullScreen="true" allowScriptAccess="always" />
|
119
|
+
EOS
|
120
|
+
end
|
121
|
+
|
122
|
+
def inspect
|
123
|
+
attrs = [:title, :artist_uri].map { |name| "#{name}: #{attribute_for_inspect(name)}" }.compact.join(", ")
|
124
|
+
"#<#{self.class} #{attrs}>"
|
125
|
+
end
|
126
|
+
|
127
|
+
def thumbnails=(val)
|
128
|
+
@thumbnails = (val.is_a?(Array) ? val : [val]).map { |t| Thumbnail.new(t['url'], t['width'], t['height']) unless t.nil? }
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
data/lib/mtv.rb
ADDED
data/ruby-mtv.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "ruby-mtv"
|
3
|
-
s.version = "1.
|
4
|
-
s.date = "2008-
|
3
|
+
s.version = "1.1"
|
4
|
+
s.date = "2008-10-27"
|
5
5
|
s.summary = "Ruby wrapper library for MTV api"
|
6
6
|
s.email = "tiegzaharia@gmail.com"
|
7
7
|
s.homepage = "http://github.com/tiegz/ruby-mtv"
|
@@ -12,10 +12,14 @@ Gem::Specification.new do |s|
|
|
12
12
|
"Rakefile",
|
13
13
|
"README",
|
14
14
|
"ruby-mtv.gemspec",
|
15
|
-
"
|
16
|
-
"
|
15
|
+
"TODO",
|
16
|
+
"lib/mtv.rb",
|
17
|
+
"lib/mtv/artist.rb",
|
18
|
+
"lib/mtv/base.rb",
|
19
|
+
"lib/mtv/thumbnail.rb",
|
20
|
+
"lib/mtv/video.rb"]
|
17
21
|
s.test_files = []
|
18
22
|
s.rdoc_options = ["--main", "README"]
|
19
23
|
s.extra_rdoc_files = ["README"]
|
20
24
|
s.add_dependency("active-support", ["> 2.0.2"])
|
21
|
-
end
|
25
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tiegz-ruby-mtv
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "1.
|
4
|
+
version: "1.1"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tieg Zaharia
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-10-27 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -34,8 +34,12 @@ files:
|
|
34
34
|
- Rakefile
|
35
35
|
- README
|
36
36
|
- ruby-mtv.gemspec
|
37
|
-
- ruby-mtv.rb
|
38
37
|
- TODO
|
38
|
+
- lib/mtv.rb
|
39
|
+
- lib/mtv/artist.rb
|
40
|
+
- lib/mtv/base.rb
|
41
|
+
- lib/mtv/thumbnail.rb
|
42
|
+
- lib/mtv/video.rb
|
39
43
|
has_rdoc: true
|
40
44
|
homepage: http://github.com/tiegz/ruby-mtv
|
41
45
|
post_install_message:
|
data/ruby-mtv.rb
DELETED
@@ -1,283 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'activesupport'
|
3
|
-
require 'open-uri'
|
4
|
-
require 'benchmark'
|
5
|
-
|
6
|
-
module MTV
|
7
|
-
class Error < StandardError; end
|
8
|
-
|
9
|
-
class << self
|
10
|
-
attr_accessor :base_url, :host, :protocol, :debug
|
11
|
-
|
12
|
-
end
|
13
|
-
|
14
|
-
self.host = "api.mtvnservices.com/1"
|
15
|
-
self.protocol = "http"
|
16
|
-
self.base_url = "#{protocol}://#{host}"
|
17
|
-
self.debug = true if ENV['DEBUG']
|
18
|
-
|
19
|
-
class Base
|
20
|
-
def initialize(values={})
|
21
|
-
values.each { |k, v| send "#{k}=", v }
|
22
|
-
end
|
23
|
-
|
24
|
-
class << self
|
25
|
-
def request path
|
26
|
-
url = URI.escape "#{MTV.base_url}/#{path}"
|
27
|
-
response = nil
|
28
|
-
seconds = Benchmark.realtime { response = open url }
|
29
|
-
puts " \e[4;36;1mREQUEST (#{sprintf("%f", seconds)})\e[0m \e[0;1m#{url}\e[0m" if MTV.debug
|
30
|
-
response.is_a?(String) ? response : response.read
|
31
|
-
rescue OpenURI::HTTPError => e
|
32
|
-
puts " \e[4;36;1mREQUEST (404)\e[0m \e[0;1m#{url}\e[0m" if MTV.debug
|
33
|
-
nil
|
34
|
-
end
|
35
|
-
|
36
|
-
protected
|
37
|
-
# assuming that the uid for the artist is downcase and no spaces, this tries to match better
|
38
|
-
def string_to_uid(str)
|
39
|
-
str.downcase.underscore.gsub(" ", "_")
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
# Copied from ActiveRecord::Base
|
44
|
-
def attribute_for_inspect(attr_name)
|
45
|
-
value = send(attr_name)
|
46
|
-
|
47
|
-
if value.is_a?(String) && value.length > 50
|
48
|
-
"#{value[0..50]}...".inspect
|
49
|
-
elsif value.is_a?(Date) || value.is_a?(Time)
|
50
|
-
%("#{value.to_s(:db)}")
|
51
|
-
else
|
52
|
-
value.inspect
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
# This class represents a musical artist in MTV's database.
|
58
|
-
class Artist < Base
|
59
|
-
attr_accessor :name, :uid, :uri, :links, :updated
|
60
|
-
|
61
|
-
def initialize(values={})
|
62
|
-
super(values)
|
63
|
-
self.uid = uri.gsub(MTV.base_url + "/artist", '').delete '/' unless @uid
|
64
|
-
end
|
65
|
-
|
66
|
-
def inspect
|
67
|
-
attrs = [:name, :uid, :uri].map { |name| "#{name}: #{attribute_for_inspect(name)}" }.compact.join(", ")
|
68
|
-
"#<#{self.class} #{attrs}>"
|
69
|
-
end
|
70
|
-
|
71
|
-
# artist = MTV::Artist.search('In Flames')[2]
|
72
|
-
# MTV::Artist.browse => I Am Ghost, IB3, INXS, Ice Cube, ...
|
73
|
-
def browse
|
74
|
-
@browse ||= Artist.browse(uid.first)
|
75
|
-
end
|
76
|
-
|
77
|
-
# artist = MTV::Artist.search 'Frank Zappa'
|
78
|
-
# MTV::Artist.browse => Amon Amarth, Amorphis, Arch Enemy, Arcturus, Borknagar, ...
|
79
|
-
def related
|
80
|
-
@related ||= Artist.related(self)
|
81
|
-
end
|
82
|
-
|
83
|
-
# artist = MTV::Artist.find('beck')
|
84
|
-
# MTV::Artist.videos => ...
|
85
|
-
def videos
|
86
|
-
@videos ||= Video.from_artist(self)
|
87
|
-
end
|
88
|
-
|
89
|
-
class << self
|
90
|
-
# MTV::Artist.browse 'x' => X, X-Clan, The X-Ecutioners, Xiren, Xscape, Xtreme, Xzibit
|
91
|
-
def browse(letter='a')
|
92
|
-
response = request "artist/browse/#{letter.to_s.first}/"
|
93
|
-
raise Error, "That artist not found!" if response.nil? || response.empty?
|
94
|
-
parse_many response
|
95
|
-
end
|
96
|
-
|
97
|
-
# MTV::Artist.find 'beck'
|
98
|
-
# MTV::Artist.find 'meGADeath'
|
99
|
-
def find(name, options={})
|
100
|
-
return name if name.is_a? Artist
|
101
|
-
|
102
|
-
options.symbolize_keys!
|
103
|
-
name = string_to_uid(options[:name] || name)
|
104
|
-
|
105
|
-
response = request "artist/#{name}/"
|
106
|
-
raise Error, "That artist not found!" if response.nil? || response.empty?
|
107
|
-
parse_one response
|
108
|
-
end
|
109
|
-
|
110
|
-
# MTV::Artist.related 'qtip'
|
111
|
-
# MTV::Artist.related MTV::Artist.find('qtip')
|
112
|
-
def related(artist)
|
113
|
-
artist = find(artist)
|
114
|
-
response = request "artist/#{artist.uid}/related/"
|
115
|
-
raise Error, "That artist not found!" if response.nil? || response.empty?
|
116
|
-
parse_many response
|
117
|
-
end
|
118
|
-
|
119
|
-
# MTV::Artist.search 'beck', :max_results => 1, :start_index => 1
|
120
|
-
def search(term=nil, options={})
|
121
|
-
options.symbolize_keys!
|
122
|
-
params = {}
|
123
|
-
params[:'max-results'] = options[:max_results] || 1
|
124
|
-
params[:'start-index'] = options[:start_index]
|
125
|
-
term = options[:term] || term
|
126
|
-
params.reject! { |k,v| !v }
|
127
|
-
response = request "artist/search?#{term.to_query('term')}&#{params.to_param}"
|
128
|
-
raise Error, "That artist not found!" if response.nil? || response.empty?
|
129
|
-
parse_many response
|
130
|
-
end
|
131
|
-
|
132
|
-
def videos(artist)
|
133
|
-
MTV::Video.from_artist(artist)
|
134
|
-
end
|
135
|
-
|
136
|
-
protected
|
137
|
-
def parse_many(body)
|
138
|
-
entries = XmlSimple.xml_in(body)['entry']
|
139
|
-
raise Error, "That artist not found!" if entries.nil?
|
140
|
-
entries = [entries] unless entries.is_a? Array
|
141
|
-
entries.map { |entry|
|
142
|
-
instantiate entry
|
143
|
-
}.reject { |artist| MTV::Artist.name.nil? || MTV::Artist.name.empty? }
|
144
|
-
end
|
145
|
-
|
146
|
-
def parse_one(body)
|
147
|
-
entry = XmlSimple.xml_in(body)
|
148
|
-
raise Error, "That artist not found!" if entry['author'].first['name'].nil? || entry['author'].first['name'].empty?
|
149
|
-
instantiate entry
|
150
|
-
end
|
151
|
-
|
152
|
-
def instantiate(entry={})
|
153
|
-
Artist.new(:name => entry['author'].first['name'].to_s,
|
154
|
-
:uri => entry['author'].first['uri'].to_s,
|
155
|
-
:links => entry['link'].map { |link| link['href'].to_s },
|
156
|
-
:updated => entry['updated'].to_s.to_datetime)
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
# This class represents a music video in MTV's database.
|
162
|
-
class Video < Base
|
163
|
-
attr_accessor :artist, :artist_name, :artist_uri, :category, :content, :credit,
|
164
|
-
:media_player_url, :media_thumbnails, :media_title, :media_description,
|
165
|
-
:media_keywords, :media_duration, :media_expression, :media_url, :media_type,
|
166
|
-
:media_credits, :media_category, :media_medium,
|
167
|
-
:title, :published, :uid, :updated, :uri, :vid
|
168
|
-
|
169
|
-
def initialize(values={})
|
170
|
-
super(values)
|
171
|
-
self.uid = uri.gsub(MTV.base_url + "/video", '').delete '/' unless @uid
|
172
|
-
self.vid = media_url.split(':').last
|
173
|
-
end
|
174
|
-
|
175
|
-
def artist
|
176
|
-
@artist ||= Artist.find(artist_uri.gsub(MTV.base_url + "/artist", '').delete('/'))
|
177
|
-
end
|
178
|
-
|
179
|
-
def inspect
|
180
|
-
attrs = [:title, :uid, :artist_name, :uri, :artist_uri].map { |name| "#{name}: #{attribute_for_inspect(name)}" }.compact.join(", ")
|
181
|
-
"#<#{self.class} #{attrs}>"
|
182
|
-
end
|
183
|
-
|
184
|
-
def thumbnails=(val)
|
185
|
-
@thumbnails = (val.is_a?(Array) ? val : [val]).map { |t| Thumbnail.new(t['url'], t['width'], t['height']) unless t.nil? }
|
186
|
-
end
|
187
|
-
|
188
|
-
class << self
|
189
|
-
# MTV::Video.find '1234abcd'
|
190
|
-
def find(uid, options={})
|
191
|
-
return uid if uid.is_a? Artist
|
192
|
-
|
193
|
-
options.symbolize_keys!
|
194
|
-
uid = options[:uid] || uid
|
195
|
-
|
196
|
-
response = request "video/#{uid}/"
|
197
|
-
raise Error, "That video not found!" if response.nil? || response.empty?
|
198
|
-
parse_one response
|
199
|
-
end
|
200
|
-
|
201
|
-
# MTV::Video.from_artist(Artist.find('beck'))
|
202
|
-
# MTV::Video.from_artist('beck')
|
203
|
-
def from_artist(artist)
|
204
|
-
artist_uid = artist.is_a?(Artist) ? artist.uid : string_to_uid(artist)
|
205
|
-
|
206
|
-
response = request "artist/#{artist_uid}/videos"
|
207
|
-
raise Error, "No videos found!" if response.nil? || response.empty?
|
208
|
-
parse_many response
|
209
|
-
end
|
210
|
-
|
211
|
-
# http://api.mtvnservices.com/1/video/search/[parameters]
|
212
|
-
# MTV::Video.search 'the golden age', :max_results => 1, :start_index => 1
|
213
|
-
def search(term=nil, options={})
|
214
|
-
options.symbolize_keys!
|
215
|
-
params = { :'max-results' => (options[:max_results] || 1),
|
216
|
-
:'start-index' => options[:start_index] }.reject { |k,v| v.nil? || v.to_s.empty? }.to_param
|
217
|
-
params = "&#{params}" unless params.empty?
|
218
|
-
term = (options[:term] || term).to_query('term')
|
219
|
-
|
220
|
-
response = request "video/search?#{term}#{params}"
|
221
|
-
raise Error, "No videos not found!" if response.nil? || response.empty?
|
222
|
-
parse_many response
|
223
|
-
end
|
224
|
-
|
225
|
-
protected
|
226
|
-
def parse_many(body)
|
227
|
-
body = hack_media_enclosures(body)
|
228
|
-
entries = XmlSimple.xml_in(body)['entry']
|
229
|
-
entries = [entries] unless entries.is_a? Array
|
230
|
-
entries.reject! { |entry| entry.nil? }
|
231
|
-
entries.map { |entry|
|
232
|
-
instantiate entry
|
233
|
-
}
|
234
|
-
end
|
235
|
-
|
236
|
-
def parse_one(body)
|
237
|
-
body = hack_media_enclosures(body)
|
238
|
-
entry = XmlSimple.xml_in(body)
|
239
|
-
raise Error, "That artist not found!" if entry['author']['name'].nil? || entry['author']['name'].empty?
|
240
|
-
instantiate entry
|
241
|
-
end
|
242
|
-
|
243
|
-
# HACK because XmlSimple doesn't seem to handle enclosures, we'll replace colons with hyphens
|
244
|
-
# TODO write a better regexp for that hack :\
|
245
|
-
def hack_media_enclosures(body)
|
246
|
-
body.gsub("<media:", "<media_").gsub("</media:", "</media_")
|
247
|
-
end
|
248
|
-
|
249
|
-
def instantiate(entry={})
|
250
|
-
Video.new(:title => entry['title'],
|
251
|
-
:artist_uri => entry['author'].first['uri'],
|
252
|
-
:artist_name => entry['author'].first['name'],
|
253
|
-
:published => entry['published'],
|
254
|
-
:content => entry['content'], # Artist Name, Video Title, and Record Label
|
255
|
-
:uri => entry['link'].select { |link| link['rel'] == 'self' }.first['href'],
|
256
|
-
:updated => (entry['updated'].to_datetime rescue nil),
|
257
|
-
:media_category => entry['media_category'], # governing agreement
|
258
|
-
:media_credits => entry['media_credit'].map { |credit| "#{credit['content'] || 'N/A'} (#{credit['role']})}" }.join(', '),
|
259
|
-
:media_description => entry['media_description'],
|
260
|
-
:media_duration => entry['media_content'].first['duration'],
|
261
|
-
:media_expression => entry['media_content'].first['expression'],
|
262
|
-
:media_keywords => entry['media_keywords'],
|
263
|
-
:media_medium => entry['media_content'].first['medium'],
|
264
|
-
:media_player_url => entry['media_player'].first['url'],
|
265
|
-
:media_thumbnails => entry['media_thumbnail'],
|
266
|
-
:media_title => entry['media_title'],
|
267
|
-
:media_type => entry['media_content'].first['type'],
|
268
|
-
:media_url => entry['media_content'].first['url'])
|
269
|
-
end
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
class Thumbnail
|
274
|
-
attr_accessor :url, :width, :height
|
275
|
-
def initialize(url, width, height)
|
276
|
-
self.url = url
|
277
|
-
self.width = width
|
278
|
-
self.height = height
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
end
|
283
|
-
|