scrobbler-ng 2.0.4 → 2.0.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.
data/README.rdoc CHANGED
@@ -10,95 +10,18 @@ all functions is available at http://rdoc.info/projects/xhochy/scrobbler
10
10
  == Initialization
11
11
 
12
12
  Scrobbler::Base.api_key = 'foo123'
13
-
14
- == Users
15
-
16
- user = Scrobbler::User.new('jnunemaker')
17
-
18
- puts "#{user.username}'s Recent Tracks"
19
- puts "=" * (user.username.length + 16)
20
- user.recent_tracks.each { |t| puts t.name }
21
-
22
- puts
23
- puts
24
-
25
- puts "#{user.username}'s Top Tracks"
26
- puts "=" * (user.username.length + 13)
27
- user.top_tracks.each { |t| puts "(#{t.playcount}) #{t.name}" }
28
-
29
- == Albums
30
-
31
- album = Scrobbler::Album.new('Some Hearts', :artist => 'Carrie Underwood', :include_info => true)
32
-
33
- puts "Album: #{album.name}"
34
- puts "Artist: #{album.artist}"
35
- puts "Playcount: #{album.playcount}"
36
- puts "URL: #{album.url}"
37
- puts "Release Date: #{album.release_date.strftime('%m/%d/%Y')}"
38
-
39
- ==Artists
40
-
41
- artist = Scrobbler::Artist.new('Carrie Underwood')
42
13
 
43
- puts 'Top Tracks'
44
- puts "=" * 10
45
- artist.top_tracks.each { |t| puts "(#{t.playcount}) #{t.name}" }
46
-
47
- puts
48
-
49
- puts 'Similar Artists'
50
- puts "=" * 15
51
- artist.similar.each { |a| puts "(#{a.match}%) #{a.name}" }
52
-
53
- ==Geo
54
-
55
- geo = Scrobbler::Geo.new()
56
-
57
- puts 'Events'
58
- puts "=" * 10
59
- geo.events(:location => 'Manchester').each { |e| puts "(#{e.id}) #{e.title}" }
60
-
61
- puts
14
+ == Usage
62
15
 
63
- puts 'Top Artists'
64
- puts "=" * 10
65
- geo.top_artists(:location => 'Manchester').each { |a| puts "(#{a.name}) #{a.playcount}" }
66
-
67
- puts
68
-
69
- puts 'Top Tracks'
70
- puts "=" * 10
71
- geo.top_tracks(:location => 'Manchester').each { |t| puts "(#{a.name}) #{a.playcount}" }
72
-
73
-
74
- ==Tags
75
-
76
- tag = Scrobbler::Tag.new('country')
77
-
78
- puts 'Top Albums'
79
- tag.top_albums.each { |a| puts "(#{a.count}) #{a.name} by #{a.artist}" }
80
-
81
- puts
82
-
83
- puts 'Top Tracks'
84
- tag.top_tracks.each { |t| puts "(#{t.count}) #{t.name} by #{t.artist}" }
85
-
86
- ==Tracks
87
-
88
- track = Scrobbler::Track.new('Carrie Underwood', 'Before He Cheats')
89
- puts 'Fans'
90
- puts "=" * 4
91
- track.top_fans.each { |u| puts "(#{u.weight}) #{u.username}" }
92
-
93
- == Simple Authentication (for Scrobbling)
94
-
95
- work in progress...
96
-
97
- == Scrobbling
98
-
99
- work in progress...
100
-
101
- == Now Playing Submission
102
-
103
- work in progress...
16
+ coming soon ...
17
+
18
+ == Note on Patches/Pull Requests
19
+
20
+ * Fork the project.
21
+ * Make your feature addition or bug fix.
22
+ * Add tests for it. This is important so I don't break it in a
23
+ future version unintentionally.
24
+ * Commit, do not mess with rakefile, version, or history.
25
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
26
+ * Send me a pull request. Bonus points for topic branches.
104
27
 
data/VERSION.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
+ :patch: 5
2
3
  :major: 2
3
- :minor: 0
4
- :patch: 4
5
4
  :build:
5
+ :minor: 0
@@ -1,19 +1,28 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'digest/md5'
4
+ require 'net/https'
4
5
  require 'nokogiri'
6
+ require 'uri'
5
7
 
6
8
  # Only set KCODE in Ruby 1.8.X, not in 1.9.X as it is deprecated
7
9
  if RUBY_VERSION =~ /1\.8\.[0-9]/ then
8
10
  $KCODE = 'u'
9
11
  end
10
12
 
11
-
12
13
  module Scrobbler
13
14
 
14
- API_URL = 'http://ws.audioscrobbler.com/'
15
+ API_URL = 'http://ws.audioscrobbler.com/' unless defined? API_URL
15
16
 
16
17
  class Base
18
+
19
+ # By default, there is no cache
20
+ @@cache = []
21
+
22
+ def Base.add_cache(cache)
23
+ @@cache << cache
24
+ end
25
+
17
26
  # Set the default API key.
18
27
  #
19
28
  # This key will be used by all Scrobbler classes and objects.
@@ -72,6 +81,53 @@ module Scrobbler
72
81
  def Base.post_request(api_method, parameters = {})
73
82
  Base.request(api_method, parameters, 'post')
74
83
  end
84
+
85
+ # Load a request from cache if possible
86
+ #
87
+ # @param [Hash] parameters The parameters passed as URL params.
88
+ # @return [String,nil]
89
+ def Base.load_from_cache(parameters)
90
+ @@cache.each do |cache|
91
+ if cache.has?(parameters)
92
+ return cache.get(parameters)
93
+ end
94
+ end
95
+ nil
96
+ end
97
+
98
+ # Save a request answer to all caches that would store it.
99
+ #
100
+ # @param [String] xml The answer from the Last.fm API
101
+ # @param [Hash] parameters The parameters passed as URL params.
102
+ # @return [nil]
103
+ def Base.save_to_cache(xml, parameters)
104
+ @@cache.each do |cache|
105
+ if cache.writable? then
106
+ cache.set(xml, parameters)
107
+ end
108
+ end
109
+ end
110
+
111
+ # Fetch a http answer for the given request
112
+ #
113
+ # @param [String] request_method The HTTP verb for the request type
114
+ # @param [Array<String>] paramlist The URL(-query) parameters
115
+ # @return [String] The plain response from the Last.fm API
116
+ def Base.fetch_http(request_method, paramlist)
117
+ url = URI.join(API_URL, "/2.0/?#{paramlist.join('&')}")
118
+ case request_method.downcase
119
+ when "get"
120
+ req = Net::HTTP::Get.new(url.request_uri)
121
+ when "post"
122
+ req = Net::HTTP::Post.new(url.request_uri)
123
+ end
124
+ http = Net::HTTP.new(url.host, url.port)
125
+ http.use_ssl = (url.port == 443)
126
+ xml = http.start() do |conn|
127
+ conn.request(req)
128
+ end
129
+ xml.body
130
+ end
75
131
 
76
132
  # Execute a request to the Audioscrobbler webservice
77
133
  #
@@ -86,6 +142,7 @@ module Scrobbler
86
142
  parameters = {:signed => false}.merge(parameters)
87
143
  parameters['api_key'] = @@api_key
88
144
  parameters['method'] = api_method.to_s
145
+ check_cache = false
89
146
  paramlist = []
90
147
  # Check if we want a signed call and pop :signed
91
148
  if parameters.delete :signed
@@ -102,30 +159,25 @@ module Scrobbler
102
159
  paramlist << "#{sanitize(a.at(0))}=#{sanitize(a.at(1))}"
103
160
  end
104
161
  else
162
+ if request_method == 'get' then
163
+ check_cache = true
164
+ end
105
165
  parameters.each do |key, value|
106
166
  paramlist << "#{sanitize(key)}=#{sanitize(value)}"
107
167
  end
108
168
  end
109
169
 
110
- # TODO Caching!
111
-
112
- url = URI.join(API_URL, "/2.0/?#{paramlist.join('&')}")
113
-
114
- # Fetch the http answer
115
- case request_method
116
- when "get"
117
- req = Net::HTTP::Get.new(url.request_uri)
118
- when "post"
119
- req = Net::HTTP::Post.new(url.request_uri)
120
- end
121
- http = Net::HTTP.new(url.host, url.port)
122
- http.use_ssl = (url.port == 443)
123
-
170
+ xml = nil
171
+ # Check if we could read from cache
172
+ xml = load_from_cache(parameters) if check_cache
173
+ # Fetch the http answer if cache was empty
174
+ xml = fetch_http(request_method, paramlist) if xml.nil?
124
175
  # Process it
125
- res = http.start() { |conn| conn.request(req) }
126
- doc = Nokogiri::XML(res.body) do |config|
127
- config.noent.noblanks.nonet
128
- end
176
+ doc = Nokogiri::XML(xml) { |config| config.noent.noblanks.nonet }
177
+ # Write to cache
178
+ save_to_cache(xml, parameters) if check_cache
179
+
180
+ # Return the parsed result
129
181
  doc
130
182
  end
131
183
 
@@ -68,8 +68,31 @@ module Scrobbler
68
68
  end
69
69
 
70
70
  # Get a list of the user's friends on Last.fm.
71
- def friends(page=1, limit=50)
72
- call('user.getfriends', :friends, User, {:user => @name, :page => page, :limit => limit})
71
+ def friends(opts={})
72
+ result = []
73
+ if opts.delete :all
74
+ params = {:page => 1, :limit => 50, :user => @name}.merge(opts)
75
+ doc = Base.request('user.getfriends', params)
76
+ root = nil
77
+ doc.root.children.each do |child|
78
+ next unless child.name == 'friends'
79
+ root = child
80
+ end
81
+ total_pages = root['totalPages'].to_i
82
+ root.children.each do |child|
83
+ next unless child.name == 'user'
84
+ result << Scrobbler::User.new_from_libxml(child)
85
+ end
86
+ puts total_pages
87
+ (2..total_pages).each do |i|
88
+ params[:page] = i
89
+ result.concat call('user.getfriends', :friends, User, params)
90
+ end
91
+ else
92
+ params = {:page => 1, :limit => 50, :user => @name}.merge(opts)
93
+ result = call('user.getfriends', :friends, User, params)
94
+ end
95
+ result
73
96
  end
74
97
 
75
98
  # Get information about a user profile.
data/scrobbler-ng.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{scrobbler-ng}
8
- s.version = "2.0.4"
8
+ s.version = "2.0.5"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["John Nunemaker", "Jonathan Rudenberg", "Uwe L. Korn"]
12
- s.date = %q{2010-07-28}
12
+ s.date = %q{2010-07-30}
13
13
  s.description = %q{A ruby library for accessing the Last.fm 2.0 API. It is higly optimized so that it uses less memory and parses XML (through Nokogiri) than other implementations.}
14
14
  s.email = %q{uwelk@xhochy.org}
15
15
  s.extra_rdoc_files = [
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scrobbler-ng
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
4
+ hash: 5
5
5
  prerelease: false
6
6
  segments:
7
7
  - 2
8
8
  - 0
9
- - 4
10
- version: 2.0.4
9
+ - 5
10
+ version: 2.0.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - John Nunemaker
@@ -17,7 +17,7 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2010-07-28 00:00:00 +02:00
20
+ date: 2010-07-30 00:00:00 +02:00
21
21
  default_executable:
22
22
  dependencies:
23
23
  - !ruby/object:Gem::Dependency