scrobbler 0.1.0

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.
Files changed (59) hide show
  1. data/History.txt +1 -0
  2. data/Manifest.txt +58 -0
  3. data/README.txt +71 -0
  4. data/Rakefile +89 -0
  5. data/examples/album.rb +18 -0
  6. data/examples/artist.rb +14 -0
  7. data/examples/tag.rb +12 -0
  8. data/examples/track.rb +7 -0
  9. data/examples/user.rb +15 -0
  10. data/lib/scrobbler.rb +13 -0
  11. data/lib/scrobbler/album.rb +143 -0
  12. data/lib/scrobbler/artist.rb +127 -0
  13. data/lib/scrobbler/base.rb +29 -0
  14. data/lib/scrobbler/chart.rb +31 -0
  15. data/lib/scrobbler/rest.rb +47 -0
  16. data/lib/scrobbler/tag.rb +104 -0
  17. data/lib/scrobbler/track.rb +96 -0
  18. data/lib/scrobbler/user.rb +192 -0
  19. data/lib/scrobbler/version.rb +9 -0
  20. data/setup.rb +1585 -0
  21. data/test/fixtures/xml/album/info.xml +70 -0
  22. data/test/fixtures/xml/artist/fans.xml +18 -0
  23. data/test/fixtures/xml/artist/similar.xml +39 -0
  24. data/test/fixtures/xml/artist/topalbums.xml +36 -0
  25. data/test/fixtures/xml/artist/toptags.xml +18 -0
  26. data/test/fixtures/xml/artist/toptracks.xml +27 -0
  27. data/test/fixtures/xml/tag/topalbums.xml +39 -0
  28. data/test/fixtures/xml/tag/topartists.xml +39 -0
  29. data/test/fixtures/xml/tag/toptags.xml +252 -0
  30. data/test/fixtures/xml/tag/toptracks.xml +30 -0
  31. data/test/fixtures/xml/track/fans.xml +28 -0
  32. data/test/fixtures/xml/track/toptags.xml +33 -0
  33. data/test/fixtures/xml/user/friends.xml +21 -0
  34. data/test/fixtures/xml/user/neighbours.xml +18 -0
  35. data/test/fixtures/xml/user/profile.xml +12 -0
  36. data/test/fixtures/xml/user/recentbannedtracks.xml +24 -0
  37. data/test/fixtures/xml/user/recentlovedtracks.xml +24 -0
  38. data/test/fixtures/xml/user/recenttracks.xml +27 -0
  39. data/test/fixtures/xml/user/systemrecs.xml +18 -0
  40. data/test/fixtures/xml/user/topalbums.xml +42 -0
  41. data/test/fixtures/xml/user/topartists.xml +30 -0
  42. data/test/fixtures/xml/user/toptags.xml +18 -0
  43. data/test/fixtures/xml/user/toptracks.xml +27 -0
  44. data/test/fixtures/xml/user/weeklyalbumchart.xml +35 -0
  45. data/test/fixtures/xml/user/weeklyalbumchart_from_1138536002_to_1139140802.xml +35 -0
  46. data/test/fixtures/xml/user/weeklyartistchart.xml +38 -0
  47. data/test/fixtures/xml/user/weeklyartistchart_from_1138536002_to_1139140802.xml +59 -0
  48. data/test/fixtures/xml/user/weeklychartlist.xml +74 -0
  49. data/test/fixtures/xml/user/weeklytrackchart.xml +35 -0
  50. data/test/fixtures/xml/user/weeklytrackchart_from_1138536002_to_1139140802.xml +35 -0
  51. data/test/mocks/rest.rb +26 -0
  52. data/test/test_helper.rb +17 -0
  53. data/test/unit/album_test.rb +86 -0
  54. data/test/unit/artist_test.rb +82 -0
  55. data/test/unit/chart_test.rb +34 -0
  56. data/test/unit/tag_test.rb +65 -0
  57. data/test/unit/track_test.rb +42 -0
  58. data/test/unit/user_test.rb +291 -0
  59. metadata +120 -0
@@ -0,0 +1 @@
1
+ * v 0.1.0: initial release
@@ -0,0 +1,58 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ setup.rb
6
+ examples/album.rb
7
+ examples/artist.rb
8
+ examples/tag.rb
9
+ examples/track.rb
10
+ examples/user.rb
11
+ lib/scrobbler.rb
12
+ lib/scrobbler/album.rb
13
+ lib/scrobbler/artist.rb
14
+ lib/scrobbler/base.rb
15
+ lib/scrobbler/chart.rb
16
+ lib/scrobbler/rest.rb
17
+ lib/scrobbler/tag.rb
18
+ lib/scrobbler/track.rb
19
+ lib/scrobbler/user.rb
20
+ lib/scrobbler/version.rb
21
+ test/test_helper.rb
22
+ test/fixtures/xml/album/info.xml
23
+ test/fixtures/xml/artist/fans.xml
24
+ test/fixtures/xml/artist/similar.xml
25
+ test/fixtures/xml/artist/topalbums.xml
26
+ test/fixtures/xml/artist/toptags.xml
27
+ test/fixtures/xml/artist/toptracks.xml
28
+ test/fixtures/xml/tag/topalbums.xml
29
+ test/fixtures/xml/tag/topartists.xml
30
+ test/fixtures/xml/tag/toptags.xml
31
+ test/fixtures/xml/tag/toptracks.xml
32
+ test/fixtures/xml/track/fans.xml
33
+ test/fixtures/xml/track/toptags.xml
34
+ test/fixtures/xml/user/friends.xml
35
+ test/fixtures/xml/user/neighbours.xml
36
+ test/fixtures/xml/user/profile.xml
37
+ test/fixtures/xml/user/recentbannedtracks.xml
38
+ test/fixtures/xml/user/recentlovedtracks.xml
39
+ test/fixtures/xml/user/recenttracks.xml
40
+ test/fixtures/xml/user/systemrecs.xml
41
+ test/fixtures/xml/user/topalbums.xml
42
+ test/fixtures/xml/user/topartists.xml
43
+ test/fixtures/xml/user/toptags.xml
44
+ test/fixtures/xml/user/toptracks.xml
45
+ test/fixtures/xml/user/weeklyalbumchart.xml
46
+ test/fixtures/xml/user/weeklyalbumchart_from_1138536002_to_1139140802.xml
47
+ test/fixtures/xml/user/weeklyartistchart.xml
48
+ test/fixtures/xml/user/weeklyartistchart_from_1138536002_to_1139140802.xml
49
+ test/fixtures/xml/user/weeklychartlist.xml
50
+ test/fixtures/xml/user/weeklytrackchart.xml
51
+ test/fixtures/xml/user/weeklytrackchart_from_1138536002_to_1139140802.xml
52
+ test/mocks/rest.rb
53
+ test/unit/album_test.rb
54
+ test/unit/artist_test.rb
55
+ test/unit/chart_test.rb
56
+ test/unit/tag_test.rb
57
+ test/unit/track_test.rb
58
+ test/unit/user_test.rb
@@ -0,0 +1,71 @@
1
+ =Scrobbler
2
+
3
+ Scrobbler is a wrapper for the audioscrobbler web services (http://www.audioscrobbler.net/data/webservices/).
4
+
5
+ Below is just a sampling of how easy this lib is to use.
6
+
7
+ == Users
8
+
9
+ user = Scrobbler::User.new('jnunemaker')
10
+
11
+ puts "#{user.username}'s Recent Tracks"
12
+ puts "=" * (user.username.length + 16)
13
+ user.recent_tracks.each { |t| puts t.name }
14
+
15
+ puts
16
+ puts
17
+
18
+ puts "#{user.username}'s Top Tracks"
19
+ puts "=" * (user.username.length + 13)
20
+ user.top_tracks.each { |t| puts "(#{t.playcount}) #{t.name}" }
21
+
22
+ == Albums
23
+
24
+ album = Scrobbler::Album.new('Carrie Underwood', 'Some Hearts', :include_info => true)
25
+
26
+ puts "Album: #{album.name}"
27
+ puts "Artist: #{album.artist}"
28
+ puts "Reach: #{album.reach}"
29
+ puts "URL: #{album.url}"
30
+ puts "Release Date: #{album.release_date.strftime('%m/%d/%Y')}"
31
+
32
+ puts
33
+ puts
34
+
35
+ puts "Tracks"
36
+ longest_track_name = album.tracks.collect(&:name).sort { |x, y| y.length <=> x.length }.first.length
37
+ puts "=" * longest_track_name
38
+ album.tracks.each { |t| puts t.name }
39
+
40
+ ==Artists
41
+
42
+ artist = Scrobbler::Artist.new('Carrie Underwood')
43
+
44
+ puts 'Top Tracks'
45
+ puts "=" * 10
46
+ artist.top_tracks.each { |t| puts "(#{t.reach}) #{t.name}" }
47
+
48
+ puts
49
+
50
+ puts 'Similar Artists'
51
+ puts "=" * 15
52
+ artist.similar.each { |a| puts "(#{a.match}%) #{a.name}" }
53
+
54
+ ==Tags
55
+
56
+ tag = Scrobbler::Tag.new('country')
57
+
58
+ puts 'Top Albums'
59
+ tag.top_albums.each { |a| puts "(#{a.count}) #{a.name} by #{a.artist}" }
60
+
61
+ puts
62
+
63
+ puts 'Top Tracks'
64
+ tag.top_tracks.each { |t| puts "(#{t.count}) #{t.name} by #{t.artist}" }
65
+
66
+ ==Tracks
67
+
68
+ track = Scrobbler::Track.new('Carrie Underwood', 'Before He Cheats')
69
+ puts 'Fans'
70
+ puts "=" * 4
71
+ track.fans.each { |u| puts "(#{u.weight}) #{u.username}" }
@@ -0,0 +1,89 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
8
+ require 'rake/contrib/rubyforgepublisher'
9
+ require 'fileutils'
10
+ require 'hoe'
11
+ include FileUtils
12
+ require File.join(File.dirname(__FILE__), 'lib', 'scrobbler', 'version')
13
+
14
+ AUTHOR = 'nunemaker' # can also be an array of Authors
15
+ EMAIL = "nunemaker@gmail.com"
16
+ DESCRIPTION = "wrapper for audioscrobbler (last.fm) web services"
17
+ GEM_NAME = 'scrobbler' # what ppl will type to install your gem
18
+ RUBYFORGE_PROJECT = 'scrobbler' # The unix name for your project
19
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
20
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
21
+
22
+ NAME = "scrobbler"
23
+ REV = nil # UNCOMMENT IF REQUIRED: File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
24
+ VERS = Scrobbler::VERSION::STRING + (REV ? ".#{REV}" : "")
25
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store']
26
+ RDOC_OPTS = ['--quiet', '--title', 'scrobbler documentation',
27
+ "--opname", "index.html",
28
+ "--line-numbers",
29
+ "--main", "README",
30
+ "--inline-source"]
31
+
32
+ class Hoe
33
+ def extra_deps
34
+ @extra_deps.reject { |x| Array(x).first == 'hoe' }
35
+ end
36
+ end
37
+
38
+ # Generate all the Rake tasks
39
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
40
+ hoe = Hoe.new(GEM_NAME, VERS) do |p|
41
+ p.author = AUTHOR
42
+ p.description = DESCRIPTION
43
+ p.email = EMAIL
44
+ p.summary = DESCRIPTION
45
+ p.url = HOMEPATH
46
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
47
+ p.test_globs = ["test/**/test_*.rb"]
48
+ p.clean_globs = CLEAN #An array of file patterns to delete on clean.
49
+
50
+ # == Optional
51
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
52
+ p.extra_deps = [['hpricot', '>=0.4.86'], ['activesupport', '>=1.4.2']] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
53
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
54
+ end
55
+
56
+
57
+ desc 'Generate website files'
58
+ task :website_generate do
59
+ Dir['website/**/*.txt'].each do |txt|
60
+ sh %{ ruby scripts/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} }
61
+ end
62
+ end
63
+
64
+ desc 'Upload website files to rubyforge'
65
+ task :website_upload do
66
+ config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
67
+ host = "#{config["username"]}@rubyforge.org"
68
+ remote_dir = "/var/www/gforge-projects/#{RUBYFORGE_PROJECT}/"
69
+ # remote_dir = "/var/www/gforge-projects/#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
70
+ local_dir = 'website'
71
+ sh %{rsync -av #{local_dir}/ #{host}:#{remote_dir}}
72
+ end
73
+
74
+ desc 'Generate and upload website files'
75
+ task :website => [:website_generate, :website_upload]
76
+
77
+ desc 'Release the website and new gem version'
78
+ task :deploy => [:check_version, :website, :release]
79
+
80
+ task :check_version do
81
+ unless ENV['VERSION']
82
+ puts 'Must pass a VERSION=x.y.z release version'
83
+ exit
84
+ end
85
+ unless ENV['VERSION'] == VERS
86
+ puts "Please update your version.rb to match the release version, currently #{VERS}"
87
+ exit
88
+ end
89
+ end
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'scrobbler'
3
+
4
+ album = Scrobbler::Album.new('Carrie Underwood', 'Some Hearts', :include_info => true)
5
+
6
+ puts "Album: #{album.name}"
7
+ puts "Artist: #{album.artist}"
8
+ puts "Reach: #{album.reach}"
9
+ puts "URL: #{album.url}"
10
+ puts "Release Date: #{album.release_date.strftime('%m/%d/%Y')}"
11
+
12
+ puts
13
+ puts
14
+
15
+ puts "Tracks"
16
+ longest_track_name = album.tracks.collect(&:name).sort { |x, y| y.length <=> x.length }.first.length
17
+ puts "=" * longest_track_name
18
+ album.tracks.each { |t| puts t.name }
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'scrobbler'
3
+
4
+ artist = Scrobbler::Artist.new('Carrie Underwood')
5
+
6
+ puts 'Top Tracks'
7
+ puts "=" * 10
8
+ artist.top_tracks.each { |t| puts "(#{t.reach}) #{t.name}" }
9
+
10
+ puts
11
+
12
+ puts 'Similar Artists'
13
+ puts "=" * 15
14
+ artist.similar.each { |a| puts "(#{a.match}%) #{a.name}" }
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'scrobbler'
3
+
4
+ tag = Scrobbler::Tag.new('country')
5
+
6
+ puts 'Top Albums'
7
+ tag.top_albums.each { |a| puts "(#{a.count}) #{a.name} by #{a.artist}" }
8
+
9
+ puts
10
+
11
+ puts 'Top Tracks'
12
+ tag.top_tracks.each { |t| puts "(#{t.count}) #{t.name} by #{t.artist}" }
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'scrobbler'
3
+
4
+ track = Scrobbler::Track.new('Carrie Underwood', 'Before He Cheats')
5
+ puts 'Fans'
6
+ puts "=" * 4
7
+ track.fans.each { |u| puts "(#{u.weight}) #{u.username}" }
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'scrobbler'
3
+
4
+ user = Scrobbler::User.new('jnunemaker')
5
+
6
+ puts "#{user.username}'s Recent Tracks"
7
+ puts "=" * (user.username.length + 16)
8
+ user.recent_tracks.each { |t| puts t.name }
9
+
10
+ puts
11
+ puts
12
+
13
+ puts "#{user.username}'s Top Tracks"
14
+ puts "=" * (user.username.length + 13)
15
+ user.top_tracks.each { |t| puts "(#{t.playcount}) #{t.name}" }
@@ -0,0 +1,13 @@
1
+ %w{cgi rubygems hpricot active_support}.each { |x| require x }
2
+
3
+ require 'scrobbler/base'
4
+
5
+ require 'scrobbler/album'
6
+ require 'scrobbler/artist'
7
+ require 'scrobbler/chart'
8
+ require 'scrobbler/user'
9
+ require 'scrobbler/tag'
10
+ require 'scrobbler/track'
11
+
12
+ require 'scrobbler/rest'
13
+ require 'scrobbler/version'
@@ -0,0 +1,143 @@
1
+ # Getting information about an album such as release date and the tracks on it is very easy.
2
+ #
3
+ # album = Scrobbler::Album.new('Carrie Underwood', 'Some Hearts', :include_info => true)
4
+ #
5
+ # puts "Album: #{album.name}"
6
+ # puts "Artist: #{album.artist}"
7
+ # puts "Reach: #{album.reach}"
8
+ # puts "URL: #{album.url}"
9
+ # puts "Release Date: #{album.release_date.strftime('%m/%d/%Y')}"
10
+ #
11
+ # puts
12
+ # puts
13
+ #
14
+ # puts "Tracks"
15
+ # longest_track_name = album.tracks.collect(&:name).sort { |x, y| y.length <=> x.length }.first.length
16
+ # puts "=" * longest_track_name
17
+ # album.tracks.each { |t| puts t.name }
18
+ #
19
+ # Would output:
20
+ #
21
+ # Album: Some Hearts
22
+ # Artist: Carrie Underwood
23
+ # Reach: 18729
24
+ # URL: http://www.last.fm/music/Carrie+Underwood/Some+Hearts
25
+ # Release Date: 11/15/2005
26
+ #
27
+ #
28
+ # Tracks
29
+ # ===============================
30
+ # Wasted
31
+ # Don't Forget to Remember Me
32
+ # Some Hearts
33
+ # Jesus, Take the Wheel
34
+ # The Night Before (Life Goes On)
35
+ # Lessons Learned
36
+ # Before He Cheats
37
+ # Starts With Goodbye
38
+ # I Just Can't Live a Lie
39
+ # We're Young and Beautiful
40
+ # That's Where It Is
41
+ # Whenever You Remember
42
+ # I Ain't in Checotah Anymore
43
+ # Inside Your Heaven
44
+ module Scrobbler
45
+ class Album < Base
46
+ attr_accessor :artist, :artist_mbid, :name, :mbid, :playcount, :rank, :url, :reach, :release_date
47
+ attr_accessor :image_large, :image_medium, :image_small
48
+ attr_writer :tracks
49
+
50
+ # needed on top albums for tag
51
+ attr_accessor :count, :streamable
52
+
53
+ # needed for weekly album charts
54
+ attr_accessor :chartposition
55
+
56
+ class << self
57
+ def find(artist, name, o={})
58
+ new(artist, name, o)
59
+ end
60
+
61
+ def new_from_xml(xml, doc=nil)
62
+ name = (xml).at(:name).inner_html if (xml).at(:name)
63
+ name = xml['name'] if name.nil? && xml['name']
64
+ artist = (xml).at(:artist)['name'] if (xml).at(:artist) && (xml).at(:artist)['name']
65
+ artist = (xml).at(:artist).inner_html if artist.nil? && (xml).at(:artist)
66
+ artist = doc.root['artist'] if artist.nil? && doc.root['artist']
67
+ a = Album.new(artist, name)
68
+ a.artist_mbid = (xml).at(:artist)['mbid'] if (xml).at(:artist) && (xml).at(:artist)['mbid']
69
+ a.artist_mbid = (xml).at(:artist).at(:mbid).inner_html if a.artist_mbid.nil? && (xml).at(:artist) && (xml).at(:artist).at(:mbid)
70
+ a.mbid = (xml).at(:mbid).inner_html if (xml).at(:mbid)
71
+ a.playcount = (xml).at(:playcount).inner_html if (xml).at(:playcount)
72
+ a.chartposition = (xml).at(:chartposition).inner_html if (xml).at(:chartposition)
73
+ a.rank = (xml).at(:rank).inner_html if (xml).at(:rank)
74
+ a.url = (xml/:url).last.inner_html if (xml/:url).size > 1
75
+ a.url = (xml).at(:url).inner_html if a.url.nil? && (xml).at(:url)
76
+ a.reach = (xml).at(:reach).inner_html if (xml).at(:reach)
77
+ a.image_large = (xml).at(:image).at(:large).inner_html if (xml).at(:image) && (xml).at(:image).at(:large)
78
+ a.image_medium = (xml).at(:image).at(:medium).inner_html if (xml).at(:image) && (xml).at(:image).at(:medium)
79
+ a.image_small = (xml).at(:image).at(:small).inner_html if (xml).at(:image) && (xml).at(:image).at(:small)
80
+
81
+ # coverart element used on top albums for tag
82
+ a.image_large = (xml).at(:coverart).at(:large).inner_html if a.image_large.nil? && (xml).at(:coverart) && (xml).at(:coverart).at(:large)
83
+ a.image_medium = (xml).at(:coverart).at(:medium).inner_html if a.image_medium.nil? && (xml).at(:coverart) && (xml).at(:coverart).at(:medium)
84
+ a.image_small = (xml).at(:coverart).at(:small).inner_html if a.image_small.nil? && (xml).at(:coverart) && (xml).at(:coverart).at(:small)
85
+
86
+ # needed on top albums for tag
87
+ a.count = xml['count'] if xml['count']
88
+ a.streamable = xml['streamable'] if xml['streamable']
89
+ a
90
+ end
91
+ end
92
+
93
+ def initialize(artist, name, o={})
94
+ raise ArgumentError, "Artist is required" if artist.blank?
95
+ raise ArgumentError, "Name is required" if name.blank?
96
+ @artist = artist
97
+ @name = name
98
+ options = {:include_info => false}.merge(o)
99
+ load_info() if options[:include_info]
100
+ end
101
+
102
+ def api_path
103
+ "/#{API_VERSION}/album/#{CGI::escape(artist)}/#{CGI::escape(name)}"
104
+ end
105
+
106
+ def load_info
107
+ doc = self.class.fetch_and_parse("#{api_path}/info.xml")
108
+ @reach = (doc).at(:reach).inner_html
109
+ @url = (doc).at(:url).inner_html
110
+ @release_date = Time.parse((doc).at(:releasedate).inner_html.strip)
111
+ @image_large = (doc).at(:coverart).at(:large).inner_html
112
+ @image_medium = (doc).at(:coverart).at(:medium).inner_html
113
+ @image_small = (doc).at(:coverart).at(:small).inner_html
114
+ @mbid = (doc).at(:mbid).inner_html
115
+ @tracks = (doc/:track).inject([]) do |tracks, track|
116
+ t = Track.new(artist, track['title'])
117
+ t.artist_mbid = artist_mbid
118
+ t.album = name
119
+ t.album_mbid = mbid
120
+ t.url = (track).at(:url).inner_html
121
+ t.reach = (track).at(:reach).inner_html
122
+ tracks << t
123
+ tracks
124
+ end
125
+ end
126
+
127
+ def tracks
128
+ load_info if @tracks.nil?
129
+ @tracks
130
+ end
131
+
132
+ def image(which=:small)
133
+ which = which.to_s
134
+ raise ArgumentError unless ['small', 'medium', 'large'].include?(which)
135
+ img_url = instance_variable_get("@image_#{which}")
136
+ if img_url.nil?
137
+ load_info
138
+ img_url = instance_variable_get("@image_#{which}")
139
+ end
140
+ img_url
141
+ end
142
+ end
143
+ end