meta-spotify 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,21 @@
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
+
21
+ ## PROJECT::SPECIFIC
data/HISTORY ADDED
@@ -0,0 +1,5 @@
1
+ === 0.1.0 / 2009-10-30
2
+
3
+ * 1 major enhancement
4
+
5
+ * First release
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 philnash
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,61 @@
1
+ = meta-spotify
2
+
3
+ A ruby wrapper for the Spotify Metadata API. See here for usage: http://developer.spotify.com/en/metadata-api/overview/
4
+
5
+ Use of the API is subject to the Terms and Conditions: http://developer.spotify.com/en/metadata-api/terms-of-use/
6
+
7
+ == Usage
8
+
9
+ The API has two services for the three types of data, artists, albums and tracks:
10
+
11
+ === Lookup
12
+
13
+ To look up an artist, album or track, simply call:
14
+
15
+ MetaSpotify::Artist.lookup(spotify_uri)
16
+ MetaSpotify::Album.lookup(spotify_uri)
17
+ or
18
+ MetaSpotify::Track.lookup(spotify_uri)
19
+
20
+ e.g.
21
+
22
+ artist = MetaSpotify::Artist.lookup("spotify:artist:4YrKBkKSVeqDamzBPWVnSJ")
23
+ #=> #<MetaSpotify::Artist:0x119764c @name="Basement Jaxx">
24
+
25
+ artist.name
26
+ #=> "Basement Jaxx"
27
+
28
+ You can also call lookup with the extras parameter, but only the acceptable extras will yield results, e.g.
29
+
30
+ artist = MetaSpotify::Artist.lookup('spotify:artist:4YrKBkKSVeqDamzBPWVnSJ', :extras => 'album')
31
+
32
+ artist.albums.first.name
33
+ #=> "Jaxx Unreleased"
34
+
35
+ === Search
36
+
37
+ To search for an artist, album or track works the same way as lookup, simply call:
38
+
39
+ MetaSpotify::Artist.search(search_term)
40
+ MetaSpotify::Album.search(search_term)
41
+ or
42
+ MetaSpotify::Track.search(search_term)
43
+
44
+ e.g.
45
+
46
+ search = MetaSpotify::Artist.search('foo')
47
+
48
+ search.artists.first.name
49
+ #=> "Foo fighters"
50
+
51
+ For searches with many results, the result also contains details on pages and you can return page 2 like this:
52
+
53
+ MetaSpotify::Artist.search('foo', :page => 2)
54
+
55
+ == Disclaimer
56
+
57
+ This is very new, so please let me know of any problems or anything that is missing.
58
+
59
+ == Copyright
60
+
61
+ Copyright (c) 2009 Phil Nash. See LICENSE for details.
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "meta-spotify"
8
+ gem.summary = %Q{A ruby wrapper for the Spotify Metadata API}
9
+ gem.description = %Q{A ruby wrapper for the Spotify Metadata API}
10
+ gem.email = "philnash@gmail.com"
11
+ gem.homepage = "http://github.com/philnash/meta-spotify"
12
+ gem.authors = ["philnash"]
13
+ gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
19
+ end
20
+
21
+ require 'rake/testtask'
22
+ Rake::TestTask.new(:test) do |test|
23
+ test.libs << 'lib' << 'test'
24
+ test.pattern = 'test/**/test_*.rb'
25
+ test.verbose = true
26
+ end
27
+
28
+ begin
29
+ require 'rcov/rcovtask'
30
+ Rcov::RcovTask.new do |test|
31
+ test.libs << 'test'
32
+ test.pattern = 'test/**/test_*.rb'
33
+ test.verbose = true
34
+ end
35
+ rescue LoadError
36
+ task :rcov do
37
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
38
+ end
39
+ end
40
+
41
+ task :test => :check_dependencies
42
+
43
+ task :default => :test
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "meta-spotify #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,99 @@
1
+ require 'rubygems'
2
+
3
+ $:.unshift File.dirname(__FILE__)
4
+
5
+ require 'httparty'
6
+
7
+ module MetaSpotify
8
+
9
+ API_VERSION = '1'
10
+
11
+ class Base
12
+ include HTTParty
13
+ base_uri 'http://ws.spotify.com'
14
+
15
+ attr_reader :name, :uri
16
+
17
+ def self.search(string, opts={})
18
+ item_name = self.name.downcase.gsub(/^.*::/,'')
19
+ query = {:q => string}
20
+ query[:page] = opts[:page].to_s if opts.has_key? :page
21
+ result = get("/search/#{API_VERSION}/#{item_name}", :query => query, :format => :xml)
22
+ raise_errors(result)
23
+ result = result[item_name+'s']
24
+ items = []
25
+ unless result[item_name].nil?
26
+ result[item_name].each do |item|
27
+ items << self.new(item)
28
+ end
29
+ end
30
+ return { (item_name+'s').to_sym => items,
31
+ :query => {
32
+ :start_page => result["opensearch:Query"]["startPage"].to_i,
33
+ :role => result["opensearch:Query"]["role"],
34
+ :search_terms => result["opensearch:Query"]["searchTerms"]
35
+ },
36
+ :items_per_page => result["opensearch:itemsPerPage"].to_i,
37
+ :start_index => result["opensearch:startIndex"].to_i,
38
+ :total_results => result["opensearch:totalResults"].to_i
39
+ }
40
+ end
41
+
42
+ def self.lookup(uri, opts={})
43
+ uri = uri.strip
44
+ raise URIError.new("Spotify URI not in the correct syntax") unless self::URI_REGEX.match(uri)
45
+ query = {:uri => uri}
46
+ query[:extras] = opts[:extras] if opts.has_key? :extras
47
+ result = get("/lookup/#{API_VERSION}/",:query => query, :format => :xml)
48
+ raise_errors(result)
49
+ result.each do |k,v|
50
+ case k
51
+ when "artist"
52
+ return Artist.new(v)
53
+ when "album"
54
+ return Album.new(v)
55
+ when "track"
56
+ return Track.new(v)
57
+ end
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def self.raise_errors(response)
64
+ case response.code
65
+ when 400
66
+ raise BadRequestError.new('400 - The request was not understood')
67
+ when 403
68
+ raise RateLimitError.new('403 - You are being rate limited, please wait 10 seconds before requesting again')
69
+ when 404
70
+ raise NotFoundError.new('404 - That resource could not be found.')
71
+ when 406
72
+ raise BadRequestError.new('406 - The requested format isn\'t available')
73
+ when 500
74
+ raise ServerError.new('500 - The server encountered an unexpected problem')
75
+ when 503
76
+ raise ServerError.new('503 - The API is temporarily unavailable')
77
+ end
78
+ end
79
+
80
+ end
81
+
82
+ class MetaSpotifyError < StandardError
83
+ attr_reader :data
84
+
85
+ def initialize(data)
86
+ @data = data
87
+ super
88
+ end
89
+ end
90
+ class URIError < MetaSpotifyError; end
91
+ class RateLimitError < MetaSpotifyError; end
92
+ class NotFoundError < MetaSpotifyError; end
93
+ class BadRequestError < MetaSpotifyError; end
94
+ class ServerError < MetaSpotifyError; end
95
+ end
96
+
97
+ require 'meta-spotify/artist'
98
+ require 'meta-spotify/track'
99
+ require 'meta-spotify/album'
@@ -0,0 +1,44 @@
1
+ module MetaSpotify
2
+ class Album < MetaSpotify::Base
3
+
4
+ URI_REGEX = /^spotify:album:[A-Za-z0-9]+$/
5
+
6
+ attr_reader :released, :artists, :available_territories, :tracks
7
+
8
+ def initialize(hash)
9
+ @name = hash['name']
10
+ if hash.has_key? 'artist'
11
+ @artists = []
12
+ if hash['artist'].is_a? Array
13
+ hash['artist'].each { |a| @artists << Artist.new(a) }
14
+ else
15
+ @artists << Artist.new(hash['artist'])
16
+ end
17
+ end
18
+ if hash.has_key? 'tracks'
19
+ @tracks = []
20
+ if hash['tracks']['track'].is_a? Array
21
+ hash['tracks']['track'].each { |a| @tracks << Track.new(a) }
22
+ else
23
+ @tracks << Track.new(hash['tracks']['track'])
24
+ end
25
+ end
26
+ @released = hash['released'] if hash.has_key? 'released'
27
+ @uri = hash['href'] if hash.has_key? 'href'
28
+ @available_territories = if hash.has_key?('availability') && !hash['availability']['territories'].nil?
29
+ hash['availability']['territories'].split(/\s+/).map {|t| t.downcase } || []
30
+ else
31
+ []
32
+ end
33
+ end
34
+
35
+ def is_available_in?(territory)
36
+ return @available_territories.include?('worldwide') || @available_territories.include?(territory.downcase)
37
+ end
38
+
39
+ def is_not_available_in?(territory)
40
+ return !is_available_in?(territory)
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,21 @@
1
+ module MetaSpotify
2
+ class Artist < MetaSpotify::Base
3
+
4
+ URI_REGEX = /^spotify:artist:[A-Za-z0-9]+$/
5
+
6
+ attr_reader :albums
7
+
8
+ def initialize(hash)
9
+ @name = hash['name']
10
+ @uri = hash['href'] if hash.has_key? 'href'
11
+ if hash.has_key? 'albums'
12
+ @albums = []
13
+ if hash['albums']['album'].is_a? Array
14
+ hash['albums']['album'].each { |a| @albums << Album.new(a) }
15
+ else
16
+ @albums << Album.new(hash['albums']['album'])
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,24 @@
1
+ module MetaSpotify
2
+ class Track < MetaSpotify::Base
3
+
4
+ URI_REGEX = /^spotify:track:[A-Za-z0-9]+$/
5
+
6
+ attr_reader :album, :artists, :track_number, :length, :popularity
7
+
8
+ def initialize(hash)
9
+ @name = hash['name']
10
+ if hash.has_key? 'artist'
11
+ @artists = []
12
+ if hash['artist'].is_a? Array
13
+ hash['artist'].each { |a| @artists << Artist.new(a) }
14
+ else
15
+ @artists << Artist.new(hash['artist'])
16
+ end
17
+ end
18
+ @album = Album.new(hash['album']) if hash.has_key? 'album'
19
+ @track_number = hash['track_number'].to_i if hash.has_key? 'track_number'
20
+ @popularity = hash['popularity'].to_f if hash.has_key? 'popularity'
21
+ @length = hash['length'].to_f if hash.has_key? 'length'
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,69 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{meta-spotify}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["philnash"]
12
+ s.date = %q{2009-10-30}
13
+ s.description = %q{A ruby wrapper for the Spotify Metadata API}
14
+ s.email = %q{philnash@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "HISTORY",
23
+ "LICENSE",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "lib/meta-spotify.rb",
28
+ "lib/meta-spotify/album.rb",
29
+ "lib/meta-spotify/artist.rb",
30
+ "lib/meta-spotify/track.rb",
31
+ "meta-spotify.gemspec",
32
+ "test/fixtures/album.xml",
33
+ "test/fixtures/album_search.xml",
34
+ "test/fixtures/artist.xml",
35
+ "test/fixtures/artist_search.xml",
36
+ "test/fixtures/track.xml",
37
+ "test/fixtures/track_search.xml",
38
+ "test/fixtures/track_search_page_2.xml",
39
+ "test/helper.rb",
40
+ "test/test_album.rb",
41
+ "test/test_artist.rb",
42
+ "test/test_track.rb"
43
+ ]
44
+ s.homepage = %q{http://github.com/philnash/meta-spotify}
45
+ s.rdoc_options = ["--charset=UTF-8"]
46
+ s.require_paths = ["lib"]
47
+ s.rubygems_version = %q{1.3.5}
48
+ s.summary = %q{A ruby wrapper for the Spotify Metadata API}
49
+ s.test_files = [
50
+ "test/helper.rb",
51
+ "test/test_album.rb",
52
+ "test/test_artist.rb",
53
+ "test/test_track.rb"
54
+ ]
55
+
56
+ if s.respond_to? :specification_version then
57
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
58
+ s.specification_version = 3
59
+
60
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
61
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
62
+ else
63
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
64
+ end
65
+ else
66
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
67
+ end
68
+ end
69
+
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <album xmlns="http://www.spotify.com/ns/music/1">
3
+ <name>Remedy</name>
4
+ <artist href="spotify:artist:4YrKBkKSVeqDamzBPWVnSJ">
5
+ <name>Basement Jaxx</name>
6
+ </artist>
7
+ <released>1999</released>
8
+ <id type="amgid" href="http://www.allmusic.com/cg/amg.dll?p=amg&amp;sql=10:dpfixqtkld0e">R 426481</id>
9
+
10
+ <id type="mbid" href="http://musicbrainz.org/release/3a3685aa-9c4d-42f8-a401-e34a89494041.html">3a3685aa-9c4d-42f8-a401-e34a89494041</id>
11
+ <id type="upc">634904012922</id>
12
+ <availability>
13
+ <territories>AD AE AF AG AI AL AM AN AO AQ AR AS AT AU AW AX AZ BA BB BD BE BF BG BH BI BJ BL BM BN BO BR BS BT BV BW BY BZ CA CC CD CF CG CH CI CK CL CM CN CO CR CU CV CX CY CZ DE DJ DK DM DO DZ EC EE EG EH ER ES ET FI FJ FK FM FO FR GA GB GD GE GF GG GH GI GL GM GN GP GQ GR GS GT GU GW GY HK HM HN HR HT HU ID IE IL IM IN IO IQ IR IS IT JE JM JO JP KE KG KH KI KM KN KP KR KW KY KZ LA LB LC LI LK LR LS LT LU LV LY MA MC MD ME MF MG MH MK ML MM MN MO MP MQ MR MS MT MU MV MW MX MY MZ NA NC NE NF NG NI NL NO NP NR NU NZ OM PA PE PF PG PH PK PL PM PN PR PS PT PW PY QA RE RO RS RU RW SA SB SC SD SE SG SH SI SJ SK SL SM SN SO SR ST SV SY SZ TC TD TF TG TH TJ TK TL TM TN TO TR TT TV TW TZ UA UG UM US UY UZ VA VC VE VG VI VN VU WF WS YE YT ZA ZM ZW ZZ</territories>
14
+ </availability>
15
+ </album>