spotify-api 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,6 @@
1
+ == 0.0.6 / 2009-10-26
2
+ * More interesting demo apps, more robust API
3
+
1
4
  == 0.0.4 / 2009-08-08
2
5
  * Fixes
3
6
 
data/LICENSE CHANGED
@@ -15,7 +15,7 @@ modification, are permitted provided that the following conditions are met:
15
15
  THIS SOFTWARE IS PROVIDED BY Jan Berkel 'AS IS'' AND ANY
16
16
  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
17
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
- DISCLAIMED. IN NO EVENT SHALL David R. MacIver BE LIABLE FOR ANY
18
+ DISCLAIMED. IN NO EVENT SHALL Jan Berkel BE LIABLE FOR ANY
19
19
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
20
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
21
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
data/README.md CHANGED
@@ -20,8 +20,7 @@ At the moment the following features are implemented:
20
20
 
21
21
  Prerequisites: *Java 6+*, JRuby 1.3.x.
22
22
 
23
- $ jruby -S gem sources -a http://gems.github.com # (you only have to do this once)
24
- $ jruby -S gem install jberkel-spotify-api
23
+ $ jruby -S gem install spotify-api --source http://gemcutter.org
25
24
  $ jruby -S spotify-api-server --account login:password
26
25
  == Sinatra/0.9.4 has taken the stage on 3000 for development with backup from WEBrick
27
26
  [2009-08-04 01:21:03] INFO WEBrick 1.3.1
@@ -38,14 +37,19 @@ Prerequisites: *Java 6+*, JRuby 1.3.x.
38
37
  "url": "http:\/\/open.spotify.com\/user\/jberkel\/playlist\/5EXLGE7HPVPjvlxPmIfrDe",
39
38
  "revision": 2,
40
39
  "id": "b9fe3dcf88945d146ef18117faa61ab4",
40
+ "size": 1,
41
41
  "collaborative": false
42
42
  }
43
43
  ]
44
44
  },
45
45
  "status": "OK"
46
46
  }
47
-
48
- See examples directory for usage.
47
+
48
+ ## Examples
49
+
50
+ See examples directory for usage. The demo application ([lastfm2spotify_loved_tracks](/jberkel/spotify-api/blob/master/examples/lastfm2spotify_loved_tracks)) will
51
+ grab all recently loved tracks by your last.fm friends to create a new
52
+ spotify playlist. A nice way to listen to some good new music (if you share a similar music taste with most of your friends :)).
49
53
 
50
54
  ## Credits
51
55
 
data/Rakefile CHANGED
@@ -15,6 +15,7 @@ begin
15
15
  gem.add_dependency "rack-test"
16
16
  gem.add_dependency "sinatra"
17
17
  gem.add_dependency "json-jruby"
18
+ gem.add_dependency "httparty"
18
19
  end
19
20
  rescue LoadError
20
21
  puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
- :patch: 5
2
+ :patch: 6
3
3
  :major: 0
4
4
  :minor: 0
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env jruby
2
+
3
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))
4
+
5
+ require 'rubygems'
6
+ gem 'spotify-api'
7
+
8
+ require 'clients/lastfm'
9
+ require 'clients/spotify'
10
+
11
+ # a demo app which grabs tracks from last.fm and creates a spotify
12
+ # playlist based on friends loved tracks
13
+ if __FILE__ == $0
14
+ username = ARGV.shift or raise "#{$0} <username>"
15
+
16
+ puts "fetching last.fm tracks (friends/recently_loved)"
17
+ limit = 10 # 10 tracks per friend
18
+ tracks = LastFM.friends_loved_tracks(username, limit).values.flatten
19
+
20
+ puts "resolving spotify ids"
21
+ spotify_tracks = begin
22
+ Spotify.resolve(tracks.map {|t| [t["title"], t["artist"]] })
23
+ rescue Errno::ECONNREFUSED
24
+ fail "Could not connect to spotify-api server. Make sure it it running."
25
+ end
26
+
27
+ if spotify_tracks.size > 0
28
+ puts "creating playlist with #{spotify_tracks.size} tracks"
29
+ puts Spotify.create_playlist("loved by friends of #{username}", spotify_tracks.map { |t| t['id'] })
30
+ end
31
+ end
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env jruby
2
+
3
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))
4
+
5
+ require 'rubygems'
6
+ gem 'spotify-api'
7
+
8
+ require 'clients/lastfm'
9
+ require 'clients/spotify'
10
+
11
+ # a demo app which grabs tracks from last.fm and creates a spotify
12
+ # playlist based on tracks popular in a city
13
+
14
+ # to batch create playlists, use lastfm_metro_playlists.rb
15
+ if __FILE__ == $0
16
+ city = ARGV.shift or raise "#{$0} <city,country>"
17
+
18
+ metro,country = *city.split(',')
19
+
20
+ puts "fetching last.fm tracks for #{metro}, #{country}"
21
+ unique = true
22
+ tracks = LastFM.metro_track_chart(metro,country, unique)
23
+
24
+ puts "resolving spotify ids"
25
+ spotify_tracks = begin
26
+ Spotify.resolve(tracks.map { |t| [t["name"], t["artist"]["name"]] })
27
+ rescue Errno::ECONNREFUSED
28
+ fail "Could not connect to spotify-api server. Make sure it it running."
29
+ end
30
+
31
+ if spotify_tracks.size > 0
32
+ puts "creating playlist with #{spotify_tracks.size} tracks"
33
+ puts Spotify.create_playlist("chart for #{metro}, #{country}", spotify_tracks.map { |t| t['id'] })
34
+ end
35
+ end
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env jruby
2
+
3
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))
4
+
5
+ require 'rubygems'
6
+ gem 'spotify-api'
7
+
8
+ require 'clients/lastfm'
9
+ require 'clients/spotify'
10
+
11
+ require 'json'
12
+
13
+ metro_areas = [
14
+ ["Berlin", "Germany"],
15
+ ["London", "United Kingdom"],
16
+ ["Barcelona", "Spain"],
17
+ ["Paris", "France"],
18
+ ["Rome", "Italy"],
19
+ ["Los Angeles", "United States"],
20
+ ["Istanbul", "Turkey"],
21
+ ["Vienna", "Austria"],
22
+ ["Zurich", "Switzerland"],
23
+ ["New York", "United States"],
24
+ ["Oslo", "Norway"],
25
+ ["Stockholm", "Sweden"],
26
+ ["Melbourne", "Australia"],
27
+ ["Montreal", "Canada"],
28
+ ["Auckland", "New Zealand"]
29
+ ]
30
+
31
+ def fetch_existing_playlists
32
+ Spotify.playlists['playlists'].inject({}) do |h, p|
33
+ if p['name'] =~ /chart for ([\w\s]+), ([\w\s]+) (\([\d-]+\))\Z/
34
+ city, metro = $1, $2
35
+ h[[city, metro]] = p
36
+ end
37
+ h
38
+ end
39
+ end
40
+
41
+ def generate_playlists(areas, update=false, unique=true)
42
+ puts "fetching existing playlists"
43
+ existing_playlists = fetch_existing_playlists
44
+ time_period = LastFM.metro_weekly_chartlist.first
45
+
46
+ areas.each do |(metro, country)|
47
+ if existing_playlists[[metro, country]] && !update
48
+ puts "#{metro}, #{country} already exists, skipping"
49
+ next
50
+ end
51
+
52
+ puts "fetching last.fm tracks for #{metro}, #{country}"
53
+ tracks = LastFM.metro_track_chart(metro, country, unique, time_period['from'], time_period['to'])
54
+ puts "resolving spotify ids"
55
+ spotify_tracks = Spotify.resolve(tracks.map { |t| [t["name"], t["artist"]["name"]] })
56
+
57
+ next if spotify_tracks.empty?
58
+
59
+ if playlist = existing_playlists[[metro, country]]
60
+ puts "update existing playlist #{playlist['id']} with #{spotify_tracks.size} tracks"
61
+ Spotify.update_playlist(playlist['id'], nil, spotify_tracks.map { |t| t['id'] })
62
+ else
63
+ tstamp = Time.new.strftime("%m-%d-%Y")
64
+ puts "creating new playlist with #{spotify_tracks.size} tracks"
65
+ puts Spotify.create_playlist("last.fm chart for #{metro}, #{country} (#{tstamp})", spotify_tracks.map { |t| t['id'] })
66
+ end
67
+ end
68
+ end
69
+
70
+ def dump_playlists
71
+ puts fetch_existing_playlists.values.to_json
72
+ end
73
+
74
+
75
+ if __FILE__ == $0
76
+ if ARGV.empty?
77
+ STDERR.puts "#{$0} [create|update|dump]"
78
+ exit(1)
79
+ end
80
+
81
+ case cmd = ARGV.shift
82
+ when 'update': generate_playlists(metro_areas, true)
83
+ when 'create': generate_playlists(metro_areas)
84
+ when 'dump': dump_playlists
85
+ else raise ArgumentError, "invalid command #{cmd}"
86
+ end
87
+ end
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'httparty'
5
+
6
+ #Last.fm API client, implemented
7
+ #using httparty (http://github.com/jnunemaker/httparty/)
8
+ #
9
+ #NOTE: you need to set the LAST_FM_API_KEY environment variable to your API key
10
+ #before you can use this class.
11
+ class LastFM
12
+ include HTTParty
13
+
14
+ base_uri 'ws.audioscrobbler.com'
15
+ default_params :api_key => (ENV['LAST_FM_API_KEY'] or raise "You need to set the LAST_FM_API_KEY environment variable")
16
+
17
+ class <<self
18
+ def loved_tracks(user_id, limit=5)
19
+ if tracks = query('user.getLovedTracks', :user=>user_id, :limit=>limit)['lovedtracks']['track']
20
+ tracks.map do |r|
21
+ { 'artist' => r['artist']['name'], 'title'=>r['name'], 'mbid' => r['mbid'] }
22
+ end
23
+ else
24
+ []
25
+ end
26
+ end
27
+
28
+ def recent_tracks(user_id)
29
+ query('user.getRecentTracks', :user=>user_id, :limit=>100)['recenttracks']['track'].map do |r|
30
+ { 'artist' => r['artist'], 'title'=>r['name'], 'mbid' => r['mbid'] }
31
+ end
32
+ end
33
+
34
+ def top_tracks(user_id, period='overall')
35
+ unless ['overall', '7day', '3month', '6month', '12month'].include?(period)
36
+ raise ArgumentError, "invalid period"
37
+ end
38
+
39
+ query('user.getTopTracks', :period=>period, :user=>user_id)['toptracks']['track'].map do |r|
40
+ { 'artist' => r['artist']['name'], 'title'=>r['name'], 'mbid' => r['mbid'] }
41
+ end
42
+ end
43
+
44
+ def friends(user_id)
45
+ query('user.getfriends', :user=>user_id, :recenttracks=>false)['friends']['user']
46
+ end
47
+
48
+ def neighbours(user_id, max=10)
49
+ query('user.getneighbours', :user=>user_id, :limit=>10)#['friends']['user']
50
+ end
51
+
52
+ # retrieve tracks recently loved by friends
53
+ def friends_loved_tracks(user_id, limit=5)
54
+ friends(user_id).inject({}) do |h, u|
55
+ h[u['name']] = loved_tracks(u['name'], limit)
56
+ sleep 0.5
57
+ h
58
+ end
59
+ end
60
+
61
+ def metro_weekly_chartlist
62
+ query("geo.getMetroWeeklyChartlist")['weeklychartlist']['chart'].reverse
63
+ end
64
+
65
+ def metro_track_chart(city, country, unique=false, from=nil, to=nil)
66
+ args = { :country=>country, :metro=>city }
67
+ args.merge!(:start=>from, :end=>to) if from && to
68
+
69
+ res = query("geo.getMetro#{unique ? 'Unique' : ''}TrackChart", args)
70
+ return [] unless res['toptracks'] && res['toptracks']['track']
71
+ res['toptracks']['track']
72
+ end
73
+
74
+ def query(method, args={})
75
+ result = get("/2.0/", :query => { :method => method }.merge(args))
76
+ raise result['lfm']['error'] if result['lfm'] && result['lfm']['status'] == 'failed'
77
+ result['lfm']
78
+ end
79
+
80
+ end
81
+ end
@@ -5,8 +5,7 @@ require 'httparty'
5
5
  require 'json'
6
6
  require 'pp'
7
7
 
8
- #A demo spotify API client, implemented
9
- #using httparty (http://github.com/jnunemaker/httparty/)
8
+ #A spotify-api API client.
10
9
  class Spotify
11
10
  include HTTParty
12
11
 
@@ -42,12 +41,12 @@ class Spotify
42
41
  get_or_bail("/playlists")
43
42
  end
44
43
 
45
- def self.update_playlist(id, name=nil, track_ids=[])
44
+ def self.update_playlist(playlist_id, name=nil, track_ids=[])
46
45
  data = {}
47
- data["tracks"] = track_ids.map { |id| { 'id' => id } } unless tracks_ids.empty?
46
+ data["tracks"] = track_ids.map { |t_id| { 'id' => t_id } } unless track_ids.empty?
48
47
  data["name"] = name if name
49
48
 
50
- resp = put("/playlists/#{id}", :body => data.to_json)
49
+ resp = put("/playlists/#{playlist_id}", :body => data.to_json)
51
50
  raise resp.inspect if resp['status'] != 'OK'
52
51
  end
53
52
 
@@ -64,6 +63,17 @@ class Spotify
64
63
  raise resp.inspect
65
64
  end
66
65
  end
66
+
67
+ def self.resolve(tracks)
68
+ tracks.map do |(title, artist)|
69
+ begin
70
+ Spotify.tracks(title, artist).first
71
+ rescue RuntimeError
72
+ nil
73
+ #raise
74
+ end
75
+ end.flatten.compact
76
+ end
67
77
  end
68
78
 
69
79
  if __FILE__ == $0
data/lib/jars/jotify.jar CHANGED
Binary file
data/lib/jotify/api.rb CHANGED
@@ -16,6 +16,11 @@ class Sinatra::Application
16
16
  def query(what, p=what)
17
17
  params[p] ? "#{what}:" + params[p] : ''
18
18
  end
19
+
20
+ def error(code, message)
21
+ [code, { 'status' => 'ERROR', 'message' => message }.to_json]
22
+ end
23
+
19
24
  end
20
25
 
21
26
  Sinatra::Application.error ArgumentError do
@@ -65,20 +70,28 @@ Sinatra::Application.get('/playlists') do
65
70
  'status'=>'OK',
66
71
  'result'=> { 'playlists' => jotify.playlists.map do |p|
67
72
  p.to_h
68
- end.each { |h| h.delete(:tracks) }
73
+ end.each { |h|
74
+ h['size'] = h.delete(:tracks).size
75
+ }
69
76
  }
70
77
  }.to_json
71
78
  end
72
79
 
73
80
  Sinatra::Application.get('/playlists/:id') do
74
81
  content_type :json
75
- if playlist = jotify.playlist(params[:id])
82
+ playlist = begin
83
+ jotify.playlist(params[:id])
84
+ rescue Exception => e
85
+ return error(500, "error getting playlist: #{e.message}")
86
+ end
87
+
88
+ if playlist
76
89
  {
77
90
  'status'=>'OK',
78
91
  'result'=>playlist.to_h
79
92
  }.to_json
80
93
  else
81
- return 404, { 'status' => 'ERROR', 'message' => 'playlist not found' }.to_json
94
+ error(404, 'playlist not found')
82
95
  end
83
96
  end
84
97
 
@@ -86,25 +99,36 @@ Sinatra::Application.post('/playlists') do
86
99
  content_type :json
87
100
  body = request.body.read
88
101
  data = JSON.parse(body)
89
- playlist = jotify.create_playlist(data['name'], !!data['collaborative'])
102
+
103
+ playlist = begin
104
+ jotify.create_playlist(data['name'], !!data['collaborative'])
105
+ rescue Exception => e
106
+ return error(500, "error creating playlist: #{e.message}")
107
+ end
108
+
90
109
  if playlist
91
110
  if data['tracks']
92
111
  ids = data['tracks'].map { |t| t['id'] }
93
112
  unless jotify.set_tracks_on_playlist(playlist, ids)
94
- return 500, 'status' => 'ERROR', 'message' => 'playlist created but tracks could not be added'
113
+ return error(500, 'playlist created but tracks could not be added')
95
114
  end
96
115
  end
97
116
  redirect playlist.link, 201 # created
98
117
  else
99
- return 500, { 'status' => 'ERROR', 'message' => 'playlist could not be created' }.to_json
118
+ error(500, 'playlist could not be created')
100
119
  end
101
120
  end
102
121
 
103
122
  Sinatra::Application.put('/playlists/:id') do
104
123
  content_type :json
105
- playlist = jotify.playlist(params[:id])
124
+
125
+ playlist = begin
126
+ jotify.playlist(params[:id])
127
+ rescue Exception => e
128
+ return error(500, "error getting playlist: #{e.message}")
129
+ end
106
130
 
107
- return 404, { 'status' => 'ERROR', 'message' => 'playlist not found' }.to_json unless playlist
131
+ return error(404, 'playlist not found') unless playlist
108
132
  body = request.body.read
109
133
  data = JSON.parse(body)
110
134
 
@@ -112,21 +136,26 @@ Sinatra::Application.put('/playlists/:id') do
112
136
 
113
137
  if data.has_key?('name') && data['name'] != playlist.name
114
138
  unless jotify.rename_playlist(playlist, data['name'])
115
- return 500, { 'status' => 'ERROR', 'message' => 'could rename playlist' }.to_json
139
+ return error(500, 'could rename playlist')
116
140
  end
117
141
  end
118
142
 
119
143
  if data.has_key?('collaborative') && data['collaborative'] != playlist.collaborative?
120
144
  unless jotify.set_collaborative_flag(playlist, data['collaborative'])
121
- return 500, { 'status' => 'ERROR', 'message' => 'could not change collaborative flag' }.to_json
145
+ return error(500, 'could not change collaborative flag')
122
146
  end
123
147
  end
124
148
 
125
149
  if data['tracks'].is_a?(Array)
126
150
  ids = data['tracks'].map { |t| t['id'] }
127
- unless jotify.set_tracks_on_playlist(playlist, ids)
128
- return 500, { 'status' => 'ERROR', 'message' => 'could update tracks' }.to_json
129
- end
151
+ begin
152
+ unless jotify.set_tracks_on_playlist(playlist, ids)
153
+ return error(500, 'could not update tracks')
154
+ end
155
+ rescue Exception => e
156
+ return error(500, e.to_s)
157
+ end
158
+
130
159
  end
131
160
  return 200, { 'status' => 'OK', 'message' => "update successful" }.to_json
132
161
  end
@@ -99,6 +99,7 @@ describe 'Api' do
99
99
  "id"=>"4d921ebcdd8c80f32ce1ed5acafbb9c8",
100
100
  "url"=>"http://open.spotify.com/user/test/playlist/2mnbxTkghYtlHMdX3jdP9C",
101
101
  "name"=>"my shiny playlist",
102
+ "size"=>0,
102
103
  "author"=>"test", "revision"=>-1, "collaborative"=>false
103
104
  ]
104
105
  }
@@ -204,7 +205,7 @@ describe 'Api' do
204
205
  @jotify.should_receive(:set_tracks_on_playlist).with(@playlist, ['1','2']).and_return(false)
205
206
  put '/playlists/foo', { 'tracks' => [ {'id'=>'1' }, { 'id'=>'2' } ] }.to_json
206
207
  last_response.status.should == 500
207
- json_response.should == {"status"=>"ERROR", "message"=>"could update tracks"}
208
+ json_response.should == {"status"=>"ERROR", "message"=>"could not update tracks"}
208
209
  end
209
210
 
210
211
  # it "should return 403 if invalid data is supplied" do
@@ -219,4 +220,4 @@ describe 'Api' do
219
220
  end
220
221
  end
221
222
  end
222
- end
223
+ end
data/spotify-api.gemspec CHANGED
@@ -1,12 +1,15 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
1
4
  # -*- encoding: utf-8 -*-
2
5
 
3
6
  Gem::Specification.new do |s|
4
7
  s.name = %q{spotify-api}
5
- s.version = "0.0.5"
8
+ s.version = "0.0.6"
6
9
 
7
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
11
  s.authors = ["Jan Berkel"]
9
- s.date = %q{2009-10-13}
12
+ s.date = %q{2009-10-26}
10
13
  s.default_executable = %q{spotify-api-server}
11
14
  s.description = %q{an api for spotify, based on jotify}
12
15
  s.email = %q{jan.berkel@gmail.com}
@@ -23,9 +26,11 @@ Gem::Specification.new do |s|
23
26
  "Rakefile",
24
27
  "VERSION.yml",
25
28
  "bin/spotify-api-server",
26
- "examples/lastfm.rb",
27
- "examples/lastfm2spotify.rb",
28
- "examples/spotify.rb",
29
+ "examples/lastfm2spotify_loved_tracks",
30
+ "examples/lastfm2spotify_metrochart",
31
+ "examples/lastfm_metro_playlists",
32
+ "lib/clients/lastfm.rb",
33
+ "lib/clients/spotify.rb",
29
34
  "lib/jars/jotify.jar",
30
35
  "lib/jotify.rb",
31
36
  "lib/jotify/api.rb",
@@ -47,10 +52,7 @@ Gem::Specification.new do |s|
47
52
  "spec/jotify/api_spec.rb",
48
53
  "spec/jotify/media_spec.rb",
49
54
  "spec/jotify_spec.rb",
50
- "spec/spec_helper.rb",
51
- "examples/lastfm.rb",
52
- "examples/lastfm2spotify.rb",
53
- "examples/spotify.rb"
55
+ "spec/spec_helper.rb"
54
56
  ]
55
57
 
56
58
  if s.respond_to? :specification_version then
@@ -62,16 +64,19 @@ Gem::Specification.new do |s|
62
64
  s.add_runtime_dependency(%q<rack-test>, [">= 0"])
63
65
  s.add_runtime_dependency(%q<sinatra>, [">= 0"])
64
66
  s.add_runtime_dependency(%q<json-jruby>, [">= 0"])
67
+ s.add_runtime_dependency(%q<httparty>, [">= 0"])
65
68
  else
66
69
  s.add_dependency(%q<rack>, [">= 0"])
67
70
  s.add_dependency(%q<rack-test>, [">= 0"])
68
71
  s.add_dependency(%q<sinatra>, [">= 0"])
69
72
  s.add_dependency(%q<json-jruby>, [">= 0"])
73
+ s.add_dependency(%q<httparty>, [">= 0"])
70
74
  end
71
75
  else
72
76
  s.add_dependency(%q<rack>, [">= 0"])
73
77
  s.add_dependency(%q<rack-test>, [">= 0"])
74
78
  s.add_dependency(%q<sinatra>, [">= 0"])
75
79
  s.add_dependency(%q<json-jruby>, [">= 0"])
80
+ s.add_dependency(%q<httparty>, [">= 0"])
76
81
  end
77
82
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spotify-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Berkel
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-13 00:00:00 +02:00
12
+ date: 2009-10-26 00:00:00 +01:00
13
13
  default_executable: spotify-api-server
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -52,6 +52,16 @@ dependencies:
52
52
  - !ruby/object:Gem::Version
53
53
  version: "0"
54
54
  version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: httparty
57
+ type: :runtime
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
55
65
  description: an api for spotify, based on jotify
56
66
  email: jan.berkel@gmail.com
57
67
  executables:
@@ -69,9 +79,11 @@ files:
69
79
  - Rakefile
70
80
  - VERSION.yml
71
81
  - bin/spotify-api-server
72
- - examples/lastfm.rb
73
- - examples/lastfm2spotify.rb
74
- - examples/spotify.rb
82
+ - examples/lastfm2spotify_loved_tracks
83
+ - examples/lastfm2spotify_metrochart
84
+ - examples/lastfm_metro_playlists
85
+ - lib/clients/lastfm.rb
86
+ - lib/clients/spotify.rb
75
87
  - lib/jars/jotify.jar
76
88
  - lib/jotify.rb
77
89
  - lib/jotify/api.rb
@@ -116,6 +128,3 @@ test_files:
116
128
  - spec/jotify/media_spec.rb
117
129
  - spec/jotify_spec.rb
118
130
  - spec/spec_helper.rb
119
- - examples/lastfm.rb
120
- - examples/lastfm2spotify.rb
121
- - examples/spotify.rb
data/examples/lastfm.rb DELETED
@@ -1,43 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'rubygems'
4
- require 'httparty'
5
-
6
- #A demo Last.fm API client, implemented
7
- #using httparty (http://github.com/jnunemaker/httparty/)
8
- class Lastfm
9
- include HTTParty
10
-
11
- base_uri 'ws.audioscrobbler.com'
12
- default_params :api_key => "PUT_API_KEY_HERE"
13
-
14
- class <<self
15
- def loved_tracks(user_id)
16
- query('user.getLovedTracks', :user=>user_id, :limit=>10)['lovedtracks']['track'].map do |r|
17
- { 'artist' => r['artist']['name'], 'title'=>r['name'], 'mbid' => r['mbid'] }
18
- end
19
- end
20
-
21
- def recent_tracks(user_id)
22
- query('user.getRecentTracks', :user=>user_id, :limit=>100)['recenttracks']['track'].map do |r|
23
- { 'artist' => r['artist'], 'title'=>r['name'], 'mbid' => r['mbid'] }
24
- end
25
- end
26
-
27
- def top_tracks(user_id, period='overall')
28
- unless ['overall', '7day', '3month', '6month', '12month'].include?(period)
29
- raise ArgumentError, "invalid period"
30
- end
31
-
32
- query('user.getTopTracks', :period=>period, :user=>user_id)['toptracks']['track'].map do |r|
33
- { 'artist' => r['artist']['name'], 'title'=>r['name'], 'mbid' => r['mbid'] }
34
- end
35
- end
36
-
37
- def query(method, args={})
38
- result = get("/2.0/", :query => { :method => method }.merge(args))
39
- raise result['lfm']['error'] if result['lfm'] && result['lfm']['status'] == 'failed'
40
- result['lfm']
41
- end
42
- end
43
- end
@@ -1,20 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require File.join(File.dirname(__FILE__), *%w[lastfm])
4
- require File.join(File.dirname(__FILE__), *%w[spotify])
5
-
6
- # a demo app which grabs tracks from last.fm and creates a spotify
7
- # playlist
8
- if __FILE__ == $0
9
- username = ARGV.shift or raise "#{$0} <username> [period=overall|7day|3month|6month|12month]"
10
- period = ARGV.shift || '7day'
11
-
12
- puts "fetching last.fm tracks (period=#{period})"
13
- tracks = Lastfm.top_tracks(username, period).map do |track|
14
- Spotify.tracks(track["title"], track["artist"]).first
15
- end.flatten.compact
16
-
17
- #puts "found tracks: #{tracks.inspect}"
18
- puts "creating playlist with #{tracks.size} tracks"
19
- puts Spotify.create_playlist(username, tracks.map { |t| t['id'] })
20
- end