echonest-ruby-api 0.1.2 → 0.1.5

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.
@@ -2,6 +2,7 @@ require "echonest-ruby-api/version"
2
2
  require 'echonest-ruby-api/artist'
3
3
  require 'echonest-ruby-api/song'
4
4
  require 'echonest-ruby-api/error'
5
+ require 'echonest-ruby-api/playlist'
5
6
 
6
7
  module Echonest
7
8
 
@@ -3,18 +3,18 @@ require "bundler/setup"
3
3
  require_relative 'base'
4
4
  require_relative 'blog'
5
5
  require_relative 'biography'
6
+ require_relative 'foreign_id'
6
7
 
7
8
  module Echonest
8
9
 
9
10
  class Artist < Echonest::Base
10
11
 
11
- def initialize(api_key, name = nil)
12
+ attr_accessor :id, :name, :foreign_ids
13
+
14
+ def initialize(api_key, name = nil, foreign_ids = nil)
12
15
  @name = name
13
16
  @api_key = api_key
14
- end
15
-
16
- def name
17
- @name
17
+ @foreign_ids = ForeignId.parse_array(foreign_ids) if foreign_ids
18
18
  end
19
19
 
20
20
  def biographies(options = { results: 1 })
@@ -58,6 +58,15 @@ module Echonest
58
58
  get_response[:genres]
59
59
  end
60
60
 
61
+ def search(options = {})
62
+ options = {name: @name}.merge(options)
63
+ artists = []
64
+ get_response(options)[:artists].each do |a|
65
+ artists << Artist.new(@api_key, a[:name], a[:foreign_ids])
66
+ end
67
+ artists
68
+ end
69
+
61
70
  def songs
62
71
  songs = []
63
72
  get_response(name: @name)[:songs].each do |s|
@@ -0,0 +1,18 @@
1
+ class ForeignId
2
+
3
+ attr_accessor :catalog, :foreign_id, :catalog_id
4
+
5
+ def initialize(options = {})
6
+ @catalog = options[:catalog]
7
+ @foreign_id = options[:foreign_id]
8
+ @catalog_id = foreign_id.split(":").last
9
+ end
10
+
11
+ def self.parse_array(array = [])
12
+ foreign_ids = []
13
+ array.each do |fid|
14
+ foreign_ids << ForeignId.new(fid)
15
+ end
16
+ foreign_ids
17
+ end
18
+ end
@@ -0,0 +1,30 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+ require_relative 'base'
4
+
5
+ module Echonest
6
+
7
+ class Playlist < Echonest::Base
8
+
9
+ def initialize(api_key, artist)
10
+ @api_key = api_key
11
+ @artist = artist
12
+ @type = 'artist-radio'
13
+ response = get('playlist/dynamic/create',
14
+ { artist: @artist, type: @type })
15
+ @session_id = response[:session_id]
16
+ end
17
+
18
+ def next
19
+ response = get('playlist/dynamic/next', { session_id: session_id })
20
+ artist = Echonest::Artist.new(@api_key, response[:songs].first[:artist_name])
21
+ { :artist => artist, :track => response[:songs].first[:title] }
22
+ end
23
+
24
+ def session_id
25
+ @session_id
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -1,3 +1,3 @@
1
1
  module Echonest
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.5"
3
3
  end
data/spec/artist_spec.rb CHANGED
@@ -15,8 +15,10 @@ describe Echonest::Artist do
15
15
  describe '#entity_name' do
16
16
 
17
17
  it 'should always return artist' do
18
- a = Echonest::Artist.new('Weezer', '12345')
19
- a.entity_name.should eql 'artist'
18
+ VCR.use_cassette('entity_name') do
19
+ a = Echonest::Artist.new('Weezer', '12345')
20
+ a.entity_name.should eql 'artist'
21
+ end
20
22
  end
21
23
 
22
24
  end
@@ -24,18 +26,24 @@ describe Echonest::Artist do
24
26
  describe '#biographies' do
25
27
 
26
28
  it 'should download a specified number of biographies' do
27
- create_valid_artist
28
- @a.biographies(results: 10).count.should be 10
29
+ VCR.use_cassette('biographies') do
30
+ create_valid_artist
31
+ @a.biographies(results: 10).count.should be 10
32
+ end
29
33
  end
30
34
 
31
35
  it 'should return one biography by default' do
32
- create_valid_artist
33
- @a.biographies.count.should be 1
36
+ VCR.use_cassette('single_biography') do
37
+ create_valid_artist
38
+ @a.biographies.count.should be 1
39
+ end
34
40
  end
35
41
 
36
42
  it 'should deal gracefully with an invalid API key' do
37
- a = Echonest::Artist.new('Weezer', 'THISISNOTAKEY')
38
- expect { a.biographies }.to raise_error(Echonest::Error)
43
+ VCR.use_cassette('invalid_api_key_error') do
44
+ a = Echonest::Artist.new('Weezer', 'THISISNOTAKEY')
45
+ expect { a.biographies }.to raise_error(Echonest::Error)
46
+ end
39
47
  end
40
48
 
41
49
  end
@@ -43,13 +51,17 @@ describe Echonest::Artist do
43
51
  describe '#blogs' do
44
52
 
45
53
  it 'should download a specified number of blogs' do
46
- create_valid_artist
47
- @a.blogs(results: 10).count.should be 10
54
+ VCR.use_cassette('ten_blogs') do
55
+ create_valid_artist
56
+ @a.blogs(results: 10).count.should be 10
57
+ end
48
58
  end
49
59
 
50
60
  it 'should return one blog by default' do
51
- create_valid_artist
52
- @a.blogs.count.should be 1
61
+ VCR.use_cassette('blogs') do
62
+ create_valid_artist
63
+ @a.blogs.count.should be 1
64
+ end
53
65
  end
54
66
 
55
67
  end
@@ -57,8 +69,10 @@ describe Echonest::Artist do
57
69
  describe '#familiarity' do
58
70
 
59
71
  it 'should allow us to find out how familiar an artist is' do
60
- create_valid_artist
61
- @a.familiarity.should be_a Float
72
+ VCR.use_cassette('familiarity') do
73
+ create_valid_artist
74
+ @a.familiarity.should be_a Float
75
+ end
62
76
  end
63
77
 
64
78
  end
@@ -66,8 +80,10 @@ describe Echonest::Artist do
66
80
  describe '#hotttnesss' do
67
81
 
68
82
  it 'should allow us to find out how hotttt an artist is' do
69
- create_valid_artist
70
- @a.hotttnesss.should be_a Float
83
+ VCR.use_cassette('hotttnesss') do
84
+ create_valid_artist
85
+ @a.hotttnesss.should be_a Float
86
+ end
71
87
  end
72
88
 
73
89
  end
@@ -75,14 +91,18 @@ describe Echonest::Artist do
75
91
  describe '#images' do
76
92
 
77
93
  it 'should allow us to get an array of urls' do
78
- create_valid_artist
79
- @a.images.should be_a Array
94
+ VCR.use_cassette('images') do
95
+ create_valid_artist
96
+ @a.images.should be_a Array
97
+ end
80
98
  end
81
99
 
82
100
  it 'should only return urls in the array' do
83
- create_valid_artist
84
- @a.images.each do |i|
85
- i.should match(/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/)
101
+ VCR.use_cassette('images') do
102
+ create_valid_artist
103
+ @a.images.each do |i|
104
+ i.should match(/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/)
105
+ end
86
106
  end
87
107
  end
88
108
 
@@ -91,30 +111,65 @@ describe Echonest::Artist do
91
111
  describe '#list_genres' do
92
112
 
93
113
  it 'should return an array of acceptable genres' do
94
- create_valid_artist
95
- @a.list_genres.should be_a Array
114
+ VCR.use_cassette('list_genres') do
115
+ create_valid_artist
116
+ @a.list_genres.should be_a Array
117
+ end
96
118
  end
97
119
 
98
120
  it 'should return an array in the correct format' do
99
- create_valid_artist
100
- @a.list_genres.each do |g|
101
- g[:name].should be_a String
121
+ VCR.use_cassette('list_genres') do
122
+ create_valid_artist
123
+ @a.list_genres.each do |g|
124
+ g[:name].should be_a String
125
+ end
102
126
  end
103
127
  end
104
128
 
105
129
  end
106
130
 
131
+ describe '#search' do
132
+ it 'should return an Array of artists' do
133
+ VCR.use_cassette('search') do
134
+ create_valid_artist
135
+ @a.search.should be_a Array
136
+ end
137
+ end
138
+
139
+ it 'should return an Artist object for each result' do
140
+ VCR.use_cassette('search') do
141
+ create_valid_artist
142
+ @a.search.each do |k|
143
+ k.class.should be Echonest::Artist
144
+ end
145
+ end
146
+ end
147
+
148
+ it 'should search the specified bucket' do
149
+ VCR.use_cassette('search_2') do
150
+ create_valid_artist
151
+ results = @a.search(bucket: "id:musicbrainz")
152
+ foreign_id = results.first.foreign_ids.first
153
+ foreign_id.catalog.should eq("musicbrainz")
154
+ end
155
+ end
156
+ end
157
+
107
158
  describe '#songs' do
108
159
 
109
160
  it 'should return an Array of a Hash of songs' do
110
- create_valid_artist
111
- @a.songs.should be_a Array
161
+ VCR.use_cassette('songs') do
162
+ create_valid_artist
163
+ @a.songs.should be_a Array
164
+ end
112
165
  end
113
166
 
114
167
  it 'should return a valid hash for each song' do
115
- create_valid_artist
116
- @a.songs.each do |k|
117
- k.should be_a Hash
168
+ VCR.use_cassette('songs') do
169
+ create_valid_artist
170
+ @a.songs.each do |k|
171
+ k.should be_a Hash
172
+ end
118
173
  end
119
174
  end
120
175
 
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe ForeignId do
4
+
5
+ it 'should parse the catalog id' do
6
+ foreign_id = ForeignId.new(catalog: "musicbrainz", foreign_id: "musicbrainz:artist:6fe07aa5-fec0-4eca-a456-f29bff451b04")
7
+ foreign_id.catalog_id.should eq("6fe07aa5-fec0-4eca-a456-f29bff451b04")
8
+ end
9
+
10
+ it 'should parse an array of results' do
11
+ results = [{catalog: "musicbrainz", foreign_id: "123"},{catalog: "musicbrainz", foreign_id: "456"}]
12
+ ForeignId.parse_array(results).count.should be 2
13
+ end
14
+
15
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe Echonest::Playlist do
4
+
5
+ describe '#initialize' do
6
+
7
+ it 'should iniaitlize with an API key and an artist ' do
8
+ VCR.use_cassette('playlist') do
9
+ seed = Echonest::Playlist.new('BNOAEBT3IZYZI6WXI', 'Weezer')
10
+ seed.should be
11
+ end
12
+ end
13
+
14
+ end
15
+
16
+ describe '#session_id' do
17
+
18
+ it 'should set a playlist session ID' do
19
+ VCR.use_cassette('playlist') do
20
+ seed = Echonest::Playlist.new('BNOAEBT3IZYZI6WXI', 'Weezer')
21
+ seed.session_id.should be_a String
22
+ end
23
+ end
24
+
25
+ end
26
+
27
+ describe '#next' do
28
+
29
+ it 'should return a Hash object' do
30
+ VCR.use_cassette('playlist_next') do
31
+ seed = Echonest::Playlist.new('BNOAEBT3IZYZI6WXI', 'Weezer')
32
+ seed.next.should be_a Hash
33
+ end
34
+ end
35
+
36
+ it 'should include the next Song' do
37
+ VCR.use_cassette('playlist_next_2') do
38
+ seed = Echonest::Playlist.new('BNOAEBT3IZYZI6WXI', 'Weezer')
39
+ seed.next[:artist].should be_a Echonest::Artist
40
+ seed.next[:track].should be_a String
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+
data/spec/song_spec.rb CHANGED
@@ -11,40 +11,44 @@ describe Echonest::Song do
11
11
  describe '#search' do
12
12
 
13
13
  it 'should return an array of tracks' do
14
- a = Echonest::Song.new('BNOAEBT3IZYZI6WXI')
15
- options = { title: 'Hello' }
16
- a.search(options).should be_a Array
14
+ VCR.use_cassette('song_search') do
15
+ a = Echonest::Song.new('BNOAEBT3IZYZI6WXI')
16
+ options = { title: 'Hello' }
17
+ a.search(options).should be_a Array
18
+ end
17
19
  end
18
20
 
19
21
  it 'should have the expected parameters' do
20
- a = Echonest::Song.new('BNOAEBT3IZYZI6WXI')
21
- options = { title: 'Hello' }
22
- a.search(options).each do |song|
23
- song.keys.should include :id, :artist_id, :artist_name, :title
22
+ VCR.use_cassette('song_search') do
23
+ a = Echonest::Song.new('BNOAEBT3IZYZI6WXI')
24
+ options = { title: 'Hello' }
25
+ a.search(options).each do |song|
26
+ song.keys.should include :id, :artist_id, :artist_name, :title
27
+ end
24
28
  end
25
29
  end
26
30
 
27
31
  it 'should happily find slow songs' do
28
- a = Echonest::Song.new('BNOAEBT3IZYZI6WXI')
29
- options = { max_tempo: 60 }
30
- a.search(options).each do |song|
31
- song.keys.should include :id, :artist_id, :artist_name, :title
32
+ VCR.use_cassette('song_search_slow') do
33
+ a = Echonest::Song.new('BNOAEBT3IZYZI6WXI')
34
+ options = { max_tempo: 60 }
35
+ a.search(options).each do |song|
36
+ song.keys.should include :id, :artist_id, :artist_name, :title
37
+ end
32
38
  end
33
39
  end
34
-
35
- # TODO: Write some comprehensive tests to make sure this breaks
36
- # if the API ever changes.
37
- # http://developer.echonest.com/docs/v4/song.html#search
38
40
 
39
41
  end
40
42
 
41
43
  describe '#identify' do
42
44
 
43
45
  it 'should identify billie jean with ease' do
44
- a = Echonest::Song.new('BNOAEBT3IZYZI6WXI')
45
- result = a.identify('eJxVlIuNwzAMQ1fxCDL133-xo1rnGqNAEcWy_ERa2aKeZmW9ustWVYrXrl5bthn_laFkzguNWpklEmoTB74JKYZSPlbJ0sy9fQrsrbEaO9W3bsbaWOoK7IhkHFaf_ag2d75oOQSZczbz5CKA7XgTIBIXASvFi0A3W8pMUZ7FZTWTVbujCcADlQ_f_WbdRNJ2vDUwSF0EZmFvAku_CVy440fgiIvArWZZWoJ7GWd-CVTYC5FCFI8GQdECdROE20UQfLoIUmhLC7IiByF1gzbAs3tsSKctyC76MPJlHRsZ5qhSQhu_CJFcKtW4EMrHSIrpTGLFqsdItj1H9JYHQYN7W2nkC6GDPjZTAzL9dx0fS4M1FoROHh9YhLHWdRchQSd_CLTpOHkQQP3xQsA2-sLOUD7CzxU0GmHVdIxh46Oide0NrNEmjghG44Ax_k2AoDHsiV6WsiD6OFm8y-0Lyt8haDBBzeMlAnTuuGYIB4WA2lEPAWbdeOabgFN6TQMs6ctLA5fHyKMBB0veGrjPfP00IAlWNm9n7hEh5PiYYBGKQDP-x4F0CL8HkhoQnRWN997JyEpnHFR7EhLPQMZmgXS68hsHktEVErranvSSR2VwfJhQCnkuwhBUcINNY-xu1pmw3PmBqU9-8xu0kiF1ngOa8vwBSSzzNw==')
46
- result.should be_a Array
47
- result.first[:artist_name].should eql 'Michael Jackson'
46
+ VCR.use_cassette('song_identify') do
47
+ a = Echonest::Song.new('BNOAEBT3IZYZI6WXI')
48
+ result = a.identify('eJxVlIuNwzAMQ1fxCDL133-xo1rnGqNAEcWy_ERa2aKeZmW9ustWVYrXrl5bthn_laFkzguNWpklEmoTB74JKYZSPlbJ0sy9fQrsrbEaO9W3bsbaWOoK7IhkHFaf_ag2d75oOQSZczbz5CKA7XgTIBIXASvFi0A3W8pMUZ7FZTWTVbujCcADlQ_f_WbdRNJ2vDUwSF0EZmFvAku_CVy440fgiIvArWZZWoJ7GWd-CVTYC5FCFI8GQdECdROE20UQfLoIUmhLC7IiByF1gzbAs3tsSKctyC76MPJlHRsZ5qhSQhu_CJFcKtW4EMrHSIrpTGLFqsdItj1H9JYHQYN7W2nkC6GDPjZTAzL9dx0fS4M1FoROHh9YhLHWdRchQSd_CLTpOHkQQP3xQsA2-sLOUD7CzxU0GmHVdIxh46Oide0NrNEmjghG44Ax_k2AoDHsiV6WsiD6OFm8y-0Lyt8haDBBzeMlAnTuuGYIB4WA2lEPAWbdeOabgFN6TQMs6ctLA5fHyKMBB0veGrjPfP00IAlWNm9n7hEh5PiYYBGKQDP-x4F0CL8HkhoQnRWN997JyEpnHFR7EhLPQMZmgXS68hsHktEVErranvSSR2VwfJhQCnkuwhBUcINNY-xu1pmw3PmBqU9-8xu0kiF1ngOa8vwBSSzzNw==')
49
+ result.should be_a Array
50
+ result.first[:artist_name].should eql 'Michael Jackson'
51
+ end
48
52
  end
49
53
 
50
54
  it 'should raise ArgumentError if the code is blank' do
data/spec/spec_helper.rb CHANGED
@@ -2,7 +2,16 @@ require 'rubygems'
2
2
  require 'bundler/setup'
3
3
  require_relative '../lib/echonest-ruby-api/base.rb'
4
4
  require 'echonest-ruby-api'
5
+ require 'vcr'
6
+ require 'webmock/rspec'
5
7
 
6
8
  RSpec.configure do |config|
7
9
 
10
+ end
11
+
12
+ VCR.configure do |c|
13
+ c.cassette_library_dir = 'fixtures/vcr_cassettes'
14
+ c.hook_into :webmock
15
+ # TODO: Get rid of this when possible!
16
+ c.allow_http_connections_when_no_cassette = true
8
17
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: echonest-ruby-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-18 00:00:00.000000000 Z
12
+ date: 2013-02-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: httparty
@@ -107,6 +107,38 @@ dependencies:
107
107
  - - ! '>='
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: vcr
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
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
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: webmock
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
110
142
  description: A simple ruby wrapper around the Echonest API
111
143
  email:
112
144
  - max.woolf@boxuk.com
@@ -115,23 +147,46 @@ extensions: []
115
147
  extra_rdoc_files: []
116
148
  files:
117
149
  - .gitignore
150
+ - CONTRIBUTING.md
118
151
  - Gemfile
119
152
  - Guardfile
120
153
  - LICENSE.txt
121
154
  - README.md
122
155
  - Rakefile
123
156
  - echonest-ruby-api.gemspec
157
+ - fixtures/vcr_cassettes/biographies.yml
158
+ - fixtures/vcr_cassettes/blogs.yml
159
+ - fixtures/vcr_cassettes/familiarity.yml
160
+ - fixtures/vcr_cassettes/hotttnesss.yml
161
+ - fixtures/vcr_cassettes/images.yml
162
+ - fixtures/vcr_cassettes/invalid_api_key_error.yml
163
+ - fixtures/vcr_cassettes/list_genres.yml
164
+ - fixtures/vcr_cassettes/playlist.yml
165
+ - fixtures/vcr_cassettes/playlist_next.yml
166
+ - fixtures/vcr_cassettes/playlist_next_2.yml
167
+ - fixtures/vcr_cassettes/search.yml
168
+ - fixtures/vcr_cassettes/search_2.yml
169
+ - fixtures/vcr_cassettes/single_biography.yml
170
+ - fixtures/vcr_cassettes/song_identify.yml
171
+ - fixtures/vcr_cassettes/song_search.yml
172
+ - fixtures/vcr_cassettes/song_search_slow.yml
173
+ - fixtures/vcr_cassettes/songs.yml
174
+ - fixtures/vcr_cassettes/ten_blogs.yml
124
175
  - lib/echonest-ruby-api.rb
125
176
  - lib/echonest-ruby-api/artist.rb
126
177
  - lib/echonest-ruby-api/base.rb
127
178
  - lib/echonest-ruby-api/biography.rb
128
179
  - lib/echonest-ruby-api/blog.rb
129
180
  - lib/echonest-ruby-api/error.rb
181
+ - lib/echonest-ruby-api/foreign_id.rb
182
+ - lib/echonest-ruby-api/playlist.rb
130
183
  - lib/echonest-ruby-api/song.rb
131
184
  - lib/echonest-ruby-api/version.rb
132
185
  - spec/artist_spec.rb
133
186
  - spec/base_spec.rb
134
187
  - spec/error_spec.rb
188
+ - spec/foreign_id_spec.rb
189
+ - spec/playlist_spec.rb
135
190
  - spec/song_spec.rb
136
191
  - spec/spec_helper.rb
137
192
  - tmp/rspec_guard_result
@@ -163,6 +218,8 @@ test_files:
163
218
  - spec/artist_spec.rb
164
219
  - spec/base_spec.rb
165
220
  - spec/error_spec.rb
221
+ - spec/foreign_id_spec.rb
222
+ - spec/playlist_spec.rb
166
223
  - spec/song_spec.rb
167
224
  - spec/spec_helper.rb
168
225
  has_rdoc: